您好,登錄后才能下訂單哦!
這篇文章主要講解了“ResponseBodyAdvice常見問題及解決方法”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“ResponseBodyAdvice常見問題及解決方法”吧!
通過ResponseBodyAdvice實現Rest接口的日志統一管理
ResponseBodyAdvice原理自己百度,代碼比較少但是我實踐的時候發現有幾個坑需要注意一下
@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()不調用
ResponseBodyAdvice接口屬于springMVC 和springBoot框架基礎的底層切面接口;實現這個接口的類,可以修改直接作為 ResponseBody類型處理器的返回值,即進行功能增強。
返回值為HpptEntity
加了@ResponseBody或@RestController注解,
實現了這個接口的類,處理返回的json值在傳遞給 HttpMessageConverter之前;應用場景在spring項目開發過程中,對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通過內容協商選擇的內容類型 * @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); }
對controller層返回值進行修改增強處理。比如返回值5,需要封裝成
{"code":"0","data":5,,"msg":"success"} 格式返回前端
controller層業務代碼:
@RestController //此注解包含@ResponseBody注解 @RequestMapping("/nandao") public class ResponseBodyAdviceController { @RequestMapping(value = "/hello", method = RequestMethod.GET) public int hello() { //業務代碼省略 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) { //定義一個統一的返回類 RestResult responseResult = new RestResult( "0", body, "success"); //如果handler處理類的返回類型是String(即控制層的返回值類型),為了保證一致性,這里需要將ResponseResult轉回去 if(body instanceof String) { return JSON.toJSONString(responseResult); } //封裝后的數據返回到前端頁面 return JSONObject.toJSON(responseResult); } }
返回公共類的創建:
/** * @author nandao * Created on 2021/1/12-21:47. * 統一返回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; } }
到此切面增強功能就實現了,可以直接在實戰項目中使用。
感謝各位的閱讀,以上就是“ResponseBodyAdvice常見問題及解決方法”的內容了,經過本文的學習后,相信大家對ResponseBodyAdvice常見問題及解決方法這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。