ResponseBodyAdvice是spring4.1的新特性,其作用是在响应体写出之前做一些处理;比如,修改返回值、加密等。
我在项目中的用到@ControllerAdvice,ResponseBodyAdvice的目的,是为每个请求的返回json中修改一个属性值。
package org.springframework.web.servlet.mvc.method.annotation; 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; /** * Allows customizing the response after the execution of an {@code @ResponseBody} * or an {@code ResponseEntity} controller method but before the body is written * with an {@code HttpMessageConverter}. Implementations may be may be registered directly with * {@code RequestMappingHandlerAdapter} and {@code ExceptionHandlerExceptionResolver} * or more likely annotated with {@code @ControllerAdvice} in which case they * will be auto-detected by both. * * @author Rossen Stoyanchev * @since 4.1 */ public interface ResponseBodyAdvice { /** * Whether this component supports the given controller method return type * and the selected {@code HttpMessageConverter} type. * @param returnType the return type * @param converterType the selected converter type * @return {@code true} if {@link #beforeBodyWrite} should be invoked, {@code false} otherwise */ boolean supports(MethodParameter returnType, Class> converterType); /** * Invoked after an {@code HttpMessageConverter} is selected and just before * its write method is invoked. * @param body the body to be written * @param returnType the return type of the controller method * @param selectedContentType the content type selected through content negotiation * @param selectedConverterType the converter type selected to write to the response * @param request the current request * @param response the current response * @return the body that was passed in or a modified, possibly new instance */ T beforeBodyWrite(T body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response); }
package com.xxx; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import com.xxx.Messages; /** * 处理 返回值 * @Description:TODO * @author lh * @time:2015-8-31 上午11:24:08 */ @ControllerAdvice public class MyResponseBodyAdvice implements ResponseBodyAdvice{ @Override public Object beforeBodyWrite(Object returnValue, MethodParameter methodParameter, MediaType mediaType, Class clas, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { //通过 ServerHttpRequest的实现类ServletServerHttpRequest 获得HttpServletRequest //ServletServerHttpRequest sshr=(ServletServerHttpRequest) serverHttpRequest; //此处获取到request 是为了取到在拦截器里面设置的一个对象 是我项目需要,可以忽略 //HttpServletRequest request= sshr.getServletRequest(); //将返回值returnValue转成我需要的类型Message<?> 方便统一修改其中的某个属性 // Messages是我自定义的一个类 Messages<?> msg=(Messages<?>) returnValue; //统一修改返回值/响应体 msg.setXXX("测试修改返回值"); //返回修改后的值 return msg; } @Override public boolean supports(MethodParameter methodParameter, Class clas) { //获取当前处理请求的controller的方法 String methodName=methodParameter.getMethod().getName(); // 不拦截/不需要处理返回值 的方法 String method= "loginCheck"; //如登录 //不拦截 return !method.equals(methodName); } }
这样得到的处理过的返回值,属性xxx的值都是“测试修改返回值”;