@ControllerAdvice,ResponseBodyAdvice 统一处理返回值/响应体

2023年2月16日11:27:44

ResponseBodyAdvice是spring4.1的新特性,其作用是在响应体写出之前做一些处理;比如,修改返回值、加密等。

我在项目中的用到@ControllerAdvice,ResponseBodyAdvice的目的,是为每个请求的返回json中修改一个属性值。

ResponseBodyAdvice 接口源码:

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的值都是“测试修改返回值”;

  • 作者:blueriver1125
  • 原文链接:https://blog.csdn.net/u012852374/article/details/53837156
    更新时间:2023年2月16日11:27:44 ,共 3451 字。