In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article focuses on "how to reconstruct an elegant background API interface", interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn how to reconstruct an elegant background API interface.
Before showing the specific refactoring code, let's take a look at how the external API interface was developed.
This API interface is mainly used to interact with our APP. In this process, we uniformly define an interaction protocol. Both the APP side and the background API interface use JSON format.
In addition, when the backend API API returns to APP, unify some error codes, and the APP side needs to pop up some prompts on the page according to the corresponding error codes.
The following shows the interface data returned by querying user information:
{"code": "000000", "msg": "success", "result": {"id": "1", "name": "test"}}
Code represents the external error code, msg represents the error message, and result represents the specific returned information.
The front-end APP acquires this return information, first determines whether the code returned by the interface is "000000", if it means the query is successful, and then obtains the result information to display accordingly. Otherwise, the corresponding error message pops up directly.
Before refactoring
Let's take a look at how to code the background API layer before refactoring.
/ * * V1 version * * @ return * / @ RequestMapping ("testv1") public APIResult testv1 () {try {User user = new User (); user.setId ("1"); user.setName ("test"); return APIResult.success (user);} catch (APPException e) {log.error ("internal exception", e) Return APIResult.error (e.getCode (), e.getMsg ());} catch (Exception e) {log.error (system exception, e); return APIResult.error (RetCodeEnum.FAILED);}}
The above code is actually very simple, encapsulating a utility class APIResult internally, and then wrapping the specific results with it.
@ Data public class APIResult implements Serializable {private static final long serialVersionUID = 4747774542107711845L; private String code; private String msg; private T result; public static APIResult success (T result) {APIResult apiResult = new APIResult (); apiResult.setResult (result); apiResult.setCode ("000000"); apiResult.setMsg ("success"); return apiResult } public static APIResult error (String code, String msg) {APIResult apiResult = new APIResult (); apiResult.setCode (code); apiResult.setMsg (msg); return apiResult;} public static APIResult error (RetCodeEnum codeEnum) {APIResult apiResult = new APIResult (); apiResult.setCode (codeEnum.getCode ()); apiResult.setMsg (codeEnum.getMsg ()); return apiResult;}
In addition to this, an exception object, APPException, is defined to unify the wrapping of internal exceptions.
The above code is very simple, but it can be said to be cumbersome, and there is a lot of repetitive code. Each interface needs to be wrapped with try...catch, and then use APIResult to include normal return messages and error messages.
Second, the interface object can only return APIResult, and the real business object can only be hidden in APIResult. This is not very elegant, and it is not very intuitive to know the real business objects.
After refactoring
Let's start refactoring the above code, the main purpose of which is to remove the duplicate try...catch code.
We need to use the Spring annotation @ ControllerAdvice and ResponseBodyAdvice for this refactoring. Let's take a look at the refactored code first.
Ps: ResponseBodyAdvice is from Spring 4.2 API. If you need to use this, you may need to upgrade the Spring version.
Rewrite the returned information
First we need to implement ResponseBodyAdvice and implement our own processing class.
@ ControllerAdvice public class CustomResponseAdvice implements ResponseBodyAdvice {/ * whether you need to process the returned result * @ param methodParameter * @ param aClass * @ return * / @ Override public boolean supports (MethodParameter methodParameter, Class aClass) {System.out.println ("In supports () method of" + getClass () .getSimpleName ()); return true } / * processing returned result * @ param body * @ param methodParameter * @ param mediaType * @ param aClass * @ param serverHttpRequest * @ param serverHttpResponse * @ return * / @ Override public Object beforeBodyWrite (Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest ServerHttpResponse serverHttpResponse) {System.out.println ("In beforeBodyWrite () method of" + getClass () .getSimpleName ()) If (body instanceof APIResult) {return body;} return APIResult.success (body);}}
By implementing the above interface, we can modify the returned result in the beforeBodyWrite method.
In the above code, the return result is simply wrapped in APIResult and then returned. In fact, we can also add some additional logic here, for example, if the information returned by the interface is encrypted, we can uniformly encrypt it at this layer.
In addition, let's determine whether body is an APIResult class, and if so, return it directly without modification.
This is compatible with the old interface, because by default, our own implementation of the CustomResponseAdvice class will work for all Controller.
If no judgment is made, the old return will be wrapped in two layers of APIResul, affecting APP parsing.
In addition, if you are worried about the impact of this change on the old interface, you can use the following way to take effect only for the specified method.
First, customize an annotation, such as:
Target ({ElementType.TYPE, ElementType.METHOD}) @ Retention (RetentionPolicy.RUNTIME) @ Documented public @ interface CustomResponse {}
Then mark it in the method that needs to be changed, and then we determine in ResponseBodyAdvice#supports whether there is a custom annotation CustomResponse on the specific method, and if so, return true, which means that the return class will be modified finally. If it does not exist, false is returned, and the process will be the same as before.
/ * whether you need to process the returned result * * @ param methodParameter * @ param aClass * @ return * / @ Override public boolean supports (MethodParameter methodParameter, Class aClass) {System.out.println ("In supports () method of" + getClass (). GetSimpleName ()); Method method = methodParameter.getMethod (); return method.isAnnotationPresent (CustomResponse.class);}
Global exception handling
After the above code is refactored, the repetitive code is extracted, and the overall code is left with our business logic, which becomes very concise and elegant.
However, there are still problems with the above refactored code, mainly exception handling.
If the above business code throws an exception, the interface will return a stack error message instead of the error message we defined. So let's, um, optimize it again.
This time we mainly need to use the @ ExceptionHandler annotation, which needs to be used with @ ControllerAdvice.
@ Slf4j @ ControllerAdvice public class CustomExceptionHandler {@ ExceptionHandler (Exception.class) @ ResponseBody public APIResult handleException (Exception e) {log.error (system exception, e); return APIResult.error (RetCodeEnum.FAILED);} @ ExceptionHandler (APPException.class) @ ResponseBody public APIResult handleAPPException (APPException e) {log.error (Internal exception, e) Return APIResult.error (e.getCode (), e.getMsg ());}}
Using this @ ExceptionHandler, the corresponding exception will be intercepted and the corresponding method will be called to handle the exception. Here we will use APIResult to wrap some error messages back.
At this point, I believe you have a deeper understanding of "how to reconstruct an elegant background API interface". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.