Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to deal with the return value uniformly by using @ ControllerAdvice and ResponseBodyAdvice interfaces in SpringMVC

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.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report