溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ResponseBodyAdvice常見問題及解決方法

發(fā)布時間:2021-06-29 12:00:42 來源:億速云 閱讀:1710 作者:chen 欄目:開發(fā)技術

這篇文章主要講解了“ResponseBodyAdvice常見問題及解決方法”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“ResponseBodyAdvice常見問題及解決方法”吧!

場景

通過ResponseBodyAdvice實現Rest接口的日志統(tǒng)一管理

正文

ResponseBodyAdvice原理自己百度,代碼比較少但是我實踐的時候發(fā)現有幾個坑需要注意一下

@RestControllerAdvice(basePackages = "com.alan.api.controller")
public class ApiResponseBodyAdvice implements ResponseBodyAdvice {
    static org.slf4j.Logger logger = LoggerFactory.getLogger("logback_api");
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||
                returnType.hasMethodAnnotation(ResponseBody.class));
    }
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                  Class selectedConverterType, ServerHttpRequest serverHttpRequest, ServerHttpResponse response) {
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        if(request != null){
            Object obj = request.getSession().getAttribute(BaseController.session_user);
            String path = request.getServletPath();
            if (StringUtils.isBlank(path)) {
                path = request.getPathInfo();
            }
            if (obj != null) {
                path = request.getPathInfo();
                logger.info("userId:"+ ((DataUser) obj).getUserId());
            }
            logger.info("url:"+ path);
            logger.info("request:"+ JSON.toJSONString(request.getParameterMap()));
            logger.info("response:"+body);
        }
        return body;
    }
}

沒了就這么簡單

生效可能情況

1.ApiResponseBodyAdvice bean沒有scan,沒有什么配置

2.如果Controller的注解為@Controller,生效的方法為@ResponseBody

3.supports()支持類型返回false,beforeBodyWrite()不調用

spring切面接口ResponseBodyAdvice的分析及使用

ResponseBodyAdvice接口屬于springMVC 和springBoot框架基礎的底層切面接口;實現這個接口的類,可以修改直接作為 ResponseBody類型處理器的返回值,即進行功能增強。

1、有兩種類型的處理器會將返回值作為ResponseBody:

返回值為HpptEntity

加了@ResponseBody或@RestController注解,

實現了這個接口的類,處理返回的json值在傳遞給 HttpMessageConverter之前;應用場景在spring項目開發(fā)過程中,對controller層返回值進行修改增強處理。比如返回值5,需要封裝成

{"code":"0","data":5,,"msg":"success"}格式返回前端

接口源碼如下:

public interface ResponseBodyAdvice<T> { 
    / * *
    *該組件是否支持給定的控制器方法返回類型
    *和選擇的{@code HttpMessageConverter}類型。
    返回類型
    * @param converterType選擇的轉換器類型
    * @return {@code true}如果{@link #beforeBodyWrite}應該被調用;
    * {@code false}否則
    * /
	boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType);
    / * *
    *在{@code HttpMessageConverter}被選中之后和之前調用
    *它的write方法被調用。
    * @param body要寫入的主體
    控制器方法的返回類型:
    * @param selectedContentType通過內容協(xié)商選擇的內容類型
    * @param selectedConverterType選擇寫入響應的轉換器類型
    * @param request當前請求
    * @param response當前響應
    * @return傳入的主體或修改過的(可能是新的)實例
   * /
	@Nullable
	T beforeBodyWrite(@Nullable T body, MethodParameter returnType, MediaType selectedContentType,
			Class<? extends HttpMessageConverter<?>> selectedConverterType,
			ServerHttpRequest request, ServerHttpResponse response);
}

2、應用場景在spring項目開發(fā)過程中

對controller層返回值進行修改增強處理。比如返回值5,需要封裝成

{"code":"0","data":5,,"msg":"success"} 格式返回前端

controller層業(yè)務代碼:

@RestController //此注解包含@ResponseBody注解
@RequestMapping("/nandao")
public class ResponseBodyAdviceController {
 
    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public int hello() {
         //業(yè)務代碼省略
        return 5;
    } 
}

實現ResponseBodyAdvice接口的切面類:

/**
*此注解針對controller層的類做增強功能,即對加了@RestController注解的類進行處理
*/
@ControllerAdvice(annotations = RestController.class)
public class RestResultWrapper implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }
 
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
                                  ServerHttpResponse response) {
 
            //定義一個統(tǒng)一的返回類
            RestResult responseResult = new RestResult( "0", body, "success");
             //如果handler處理類的返回類型是String(即控制層的返回值類型),為了保證一致性,這里需要將ResponseResult轉回去
            if(body instanceof String) {
                return JSON.toJSONString(responseResult);
            }
           //封裝后的數據返回到前端頁面
            return JSONObject.toJSON(responseResult);       
    } 
}

返回公共類的創(chuàng)建:

/**
 * @author nandao
 * Created on 2021/1/12-21:47.
 * 統(tǒng)一返回Rest風格的數據結構
 */
public class RestResult<T>  implements Serializable {
 
    /**
     * 成功的code碼
     */
    private String code = "2000";
    /**
     * 成功時返回的數據,失敗時返回具體的異常信息
     */
    private T data;
    /**
     * 請求失敗返回的提示信息,給前端進行頁面展示的信息
     */
    private String message ; 
    public RestResult() {
    }
 
    @Override
    public String toString() {
 
        return "RestResult{" +
                "code='" + code + '\'' +
                ", data=" + data +
                ", message=" + message +
                '}';
    }
 
    public RestResult(String code, T data, String message) {
        this.code = code;
        this.data = data;
        this.message = message;
    }
 
    public String getCode() {
        return code;
    }
 
    public void setCode(String code) {
        this.code = code;
    }
 
    public T getData() {
        return data;
    }
 
    public void setData(T data) {
        this.data = data;
    }
 
    public String getMessage() {
        return message;
    }
 
    public void setMessage(String message) {
        this.message = message;
    }
}

到此切面增強功能就實現了,可以直接在實戰(zhàn)項目中使用。

感謝各位的閱讀,以上就是“ResponseBodyAdvice常見問題及解決方法”的內容了,經過本文的學習后,相信大家對ResponseBodyAdvice常見問題及解決方法這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI