ResponseBodyAdvice踩坑及解決
場(chǎng)景
通過(guò)ResponseBodyAdvice實(shí)現(xiàn)Rest接口的日志統(tǒng)一管理
正文
ResponseBodyAdvice原理自己百度,代碼比較少但是我實(shí)踐的時(shí)候發(fā)現(xiàn)有幾個(gè)坑需要注意一下
@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;
}
}
沒(méi)了就這么簡(jiǎn)單
生效可能情況
1.ApiResponseBodyAdvice bean沒(méi)有scan,沒(méi)有什么配置
2.如果Controller的注解為@Controller,生效的方法為@ResponseBody
3.supports()支持類型返回false,beforeBodyWrite()不調(diào)用
spring切面接口ResponseBodyAdvice的分析及使用
ResponseBodyAdvice接口屬于springMVC 和springBoot框架基礎(chǔ)的底層切面接口;實(shí)現(xiàn)這個(gè)接口的類,可以修改直接作為 ResponseBody類型處理器的返回值,即進(jìn)行功能增強(qiáng)。
1、有兩種類型的處理器會(huì)將返回值作為ResponseBody:
返回值為HpptEntity
加了@ResponseBody或@RestController注解,
實(shí)現(xiàn)了這個(gè)接口的類,處理返回的json值在傳遞給 HttpMessageConverter之前;應(yīng)用場(chǎng)景在spring項(xiàng)目開(kāi)發(fā)過(guò)程中,對(duì)controller層返回值進(jìn)行修改增強(qiáng)處理。比如返回值5,需要封裝成
{"code":"0","data":5,,"msg":"success"}格式返回前端
接口源碼如下:
public interface ResponseBodyAdvice<T> {
/ * *
*該組件是否支持給定的控制器方法返回類型
*和選擇的{@code HttpMessageConverter}類型。
返回類型
* @param converterType選擇的轉(zhuǎn)換器類型
* @return {@code true}如果{@link #beforeBodyWrite}應(yīng)該被調(diào)用;
* {@code false}否則
* /
boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType);
/ * *
*在{@code HttpMessageConverter}被選中之后和之前調(diào)用
*它的write方法被調(diào)用。
* @param body要寫入的主體
控制器方法的返回類型:
* @param selectedContentType通過(guò)內(nèi)容協(xié)商選擇的內(nèi)容類型
* @param selectedConverterType選擇寫入響應(yīng)的轉(zhuǎn)換器類型
* @param request當(dāng)前請(qǐng)求
* @param response當(dāng)前響應(yīng)
* @return傳入的主體或修改過(guò)的(可能是新的)實(shí)例
* /
@Nullable
T beforeBodyWrite(@Nullable T body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response);
}
2、應(yīng)用場(chǎng)景在spring項(xiàng)目開(kāi)發(fā)過(guò)程中
對(duì)controller層返回值進(jìn)行修改增強(qiáng)處理。比如返回值5,需要封裝成
{"code":"0","data":5,,"msg":"success"} 格式返回前端
controller層業(yè)務(wù)代碼:
@RestController //此注解包含@ResponseBody注解
@RequestMapping("/nandao")
public class ResponseBodyAdviceController {
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public int hello() {
//業(yè)務(wù)代碼省略
return 5;
}
}
實(shí)現(xiàn)ResponseBodyAdvice接口的切面類:
/**
*此注解針對(duì)controller層的類做增強(qiáng)功能,即對(duì)加了@RestController注解的類進(jìn)行處理
*/
@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) {
//定義一個(gè)統(tǒng)一的返回類
RestResult responseResult = new RestResult( "0", body, "success");
//如果handler處理類的返回類型是String(即控制層的返回值類型),為了保證一致性,這里需要將ResponseResult轉(zhuǎn)回去
if(body instanceof String) {
return JSON.toJSONString(responseResult);
}
//封裝后的數(shù)據(jù)返回到前端頁(yè)面
return JSONObject.toJSON(responseResult);
}
}
返回公共類的創(chuàng)建:
/**
* @author nandao
* Created on 2021/1/12-21:47.
* 統(tǒng)一返回Rest風(fēng)格的數(shù)據(jù)結(jié)構(gòu)
*/
public class RestResult<T> implements Serializable {
/**
* 成功的code碼
*/
private String code = "2000";
/**
* 成功時(shí)返回的數(shù)據(jù),失敗時(shí)返回具體的異常信息
*/
private T data;
/**
* 請(qǐng)求失敗返回的提示信息,給前端進(jìn)行頁(yè)面展示的信息
*/
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;
}
}
到此切面增強(qiáng)功能就實(shí)現(xiàn)了,可以直接在實(shí)戰(zhàn)項(xiàng)目中使用。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SparkSQL使用IDEA快速入門DataFrame與DataSet的完美教程
本文給大家介紹使用idea開(kāi)發(fā)Spark SQL 的詳細(xì)過(guò)程,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-08-08
Spring+SpringMVC+Hibernate整合實(shí)例講解
在本篇文章里小編給大家整理的是關(guān)于Spring+SpringMVC+Hibernate整合實(shí)例講解,需要的朋友們可以學(xué)習(xí)下。2020-03-03
java 讀取網(wǎng)頁(yè)內(nèi)容的實(shí)例詳解
這篇文章主要介紹了java 讀取網(wǎng)頁(yè)內(nèi)容的實(shí)例詳解的相關(guān)資料,希望通過(guò)本文能幫助到大家,讓大家學(xué)習(xí)理解這部分內(nèi)容,需要的朋友可以參考下2017-09-09
springboot異步@Async的使用及失效場(chǎng)景介紹
本文主要介紹了springboot異步@Async的使用及失效場(chǎng)景介紹,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-12-12
IDEA:Git stash 暫存分支修改的實(shí)現(xiàn)代碼
這篇文章主要介紹了IDEA:Git stash 暫存分支修改的實(shí)現(xiàn)代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03
Spark學(xué)習(xí)筆記之Spark SQL的具體使用
這篇文章主要介紹了Spark學(xué)習(xí)筆記之Spark SQL的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06

