In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
I believe many inexperienced people don't know what to do about how to use @ ControllerAdvice and ResponseBodyAdvice interfaces to deal with return values in SpringMVC. This article summarizes the causes and solutions of the problem. I hope you can solve this problem through this article.
When we develop Web applications for Java, how to write less code and do more things. How to make the development easier to start, more focused on the business level, do not need to care too much about the underlying implementation. Here is to share some of my usual experience in building the basic framework.
Unified processing return value
In web applications, the front and back ends usually define a unified object to encapsulate the return value, which may contain some request-related data in addition to business data
For example, the following object
Code to identify the result of the entire request
Msg is used to return error messages
Data is used to return actual business data.
{"code": 0, "msg": "success", "data": {}}
The advantage of unified encapsulation is that the front end can use unified logic for request processing and can write general code to handle the return value.
Of course, this also requires some development at the back end. Usually we write directly in the code, manually create a wrapper object, and then set the data, or add some static methods to the wrapper class. In most cases, this work is repetitive.
The execution process of ResponseBodyAdvice
The interface introduced today, ResponseBodyAdvice, is an interface provided by SpringMvc to process the return value before message conversion. The source code is as follows:
Public interface ResponseBodyAdvice {boolean supports (MethodParameter returnType, Class > converterType); T beforeBodyWrite (T body, MethodParameter returnType, MediaType selectedContentType, Class > selectedConverterType, ServerHttpRequest request, ServerHttpResponse response);}
This API is processed before the return value is written back to the front end by the message converter, and the processing flow is as follows:
Our code that implements this interface is mainly called RequestResponseBodyAdviceChain.processBody in this method, and you can see that this logic is very simple.
First execute ResponseBodyAdvice.supports to see if the current aspect class supports it. If so, call the ResponseBodyAdvice.beforeBodyWrite method and return
The return value will be finally converted by the HttpMessageConverter.write interface (for example, to JSON), and then written back to the front end
Private Object processBody (@ Nullable Object body, MethodParameter returnType, MediaType contentType, Class > converterType, ServerHttpRequest request, ServerHttpResponse response) {for (ResponseBodyAdvice advice: getMatchingAdvice (returnType, ResponseBodyAdvice.class)) {if (advice.supports (returnType, converterType)) {body = ((ResponseBodyAdvice) advice). BeforeBodyWrite ((T) body, returnType ContentType, converterType, request, response) Initialization of}} return body;} ResponseBodyAdvice
When SpringMVC initializes, it calls RequestMappingHandlerAdapter.initControllerAdviceCache to initialize ResponseBodyAdvice into the container.
ControllerAdviceBean.findAnnotatedBeans is called inside to get all the classes with @ ControllerAdvice annotations
Put all the Bean that implements the ResponseBodyAdvice interface into requestResponseBodyAdviceBeans, which is the object obtained by the getAdvice () method described earlier.
/ / Code snippet public static List findAnnotatedBeans (ApplicationContext context) {return Arrays.stream (BeanFactoryUtils.beanNamesForTypeIncludingAncestors (context, Object.class)) .filter (name-> context.findAnnotationOnBean (name, ControllerAdvice.class)! = null) .map (name-> new ControllerAdviceBean (name, context)) .filter (Collectors.toList ()) } / / Code fragment for (ControllerAdviceBean adviceBean: adviceBeans) {Class beanType = adviceBean.getBeanType (); if (beanType = = null) {throw new IllegalStateException ("Unresolvable type for ControllerAdviceBean:" + adviceBean);} Set attrMethods = MethodIntrospector.selectMethods (beanType, MODEL_ATTRIBUTE_METHODS); if (! attrMethods.isEmpty ()) {this.modelAttributeAdviceCache.put (adviceBean, attrMethods) } Set binderMethods = MethodIntrospector.selectMethods (beanType, INIT_BINDER_METHODS); if (! binderMethods.isEmpty ()) {this.initBinderAdviceCache.put (adviceBean, binderMethods);} if (RequestBodyAdvice.class.isAssignableFrom (beanType)) {requestResponseBodyAdviceBeans.add (adviceBean) } if (ResponseBodyAdvice.class.isAssignableFrom (beanType)) {requestResponseBodyAdviceBeans.add (adviceBean);}}
Knowing this, it's easy to implement a general return value handling, just implement the ResponseBodyAdvice interface and add the @ ControllerAdvice annotation.
This is an implementation that I have implemented, which uniformly encapsulates the return value. You can refer to it and modify it according to your own business needs.
Package com.diamondfsd.fast.mvc.advice;import com.diamondfsd.fast.mvc.annotations.IgnoreAware;import com.diamondfsd.fast.mvc.entity.FastResult;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.ObjectMapper;import org.springframework.core.MethodParameter;import org.springframework.http.MediaType;import org.springframework.http.converter.HttpMessageConverter;import org.springframework.http.server.ServerHttpRequest;import org.springframework.http.server.ServerHttpResponse;import org.springframework.web.bind.annotation.ControllerAdvice Import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;import java.lang.reflect.Method;import java.util.Map;import java.util.WeakHashMap;/** * Unified return data Encapsulation * @ author Diamond * / @ ControllerAdvicepublic class FastMvcResponseBodyAwareAdvice implements ResponseBodyAdvice {private final Map supportsCache = new WeakHashMap (); private final String [] basePackages; private ObjectMapper objectMapper = new ObjectMapper (); public FastMvcResponseBodyAwareAdvice (String [] basePackages) {this.basePackages = basePackages } @ Override public boolean supports (MethodParameter returnType, Class > converterType) {if (supportsCache.containsKey (returnType.getMethod () {return supportsCache.get (returnType.getMethod ());} boolean isSupport = getIsSupport (returnType); supportsCache.put (returnType.getMethod (), isSupport); return isSupport;} private boolean getIsSupport (MethodParameter returnType) {Class declaringClass = returnType.getMember (). GetDeclaringClass () IgnoreAware classIgnore = declaringClass.getAnnotation (IgnoreAware.class); IgnoreAware methodIgnore = returnType.getMethod () .getAnnotation (IgnoreAware.class); if (classIgnore! = null | | methodIgnore! = null | | FastResult.class.equals (returnType.getGenericParameterType ()) {return false;} for (int I = 0; I)
< basePackages.length; i++) { if (declaringClass.getPackage().getName().startsWith(basePackages[i])) { return true; } } return false; } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class>SelectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {FastResult result = new FastResult (); result.setData (body); if (returnType.getGenericParameterType (). Equals (String.class)) {try {response.getHeaders () .set ("Content-Type", "application/json;charset=utf-8"); return objectMapper.writeValueAsString (result) } catch (JsonProcessingException e) {e.printStackTrace ();}} return result;}} after reading the above, have you mastered how to use the @ ControllerAdvice and ResponseBodyAdvice interfaces in SpringMVC to uniformly deal with the return value? If you want to learn more skills or want to know more about it, you are welcome to follow the industry information channel, thank you for reading!
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.