1. 程式人生 > >@ControllerAdvice,ResponseBodyAdvice 統一處理返回值/響應體

@ControllerAdvice,ResponseBodyAdvice 統一處理返回值/響應體

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