gpt4 book ai didi

ResponseBodyAdvice踩坑及解决

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 26 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章ResponseBodyAdvice踩坑及解决由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

场景

通过ResponseBodyAdvice实现Rest接口的日志统一管理 。

正文

ResponseBodyAdvice原理自己百度,代码比较少但是我实践的时候发现有几个坑需要注意一下 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@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项目开发过程中,对controller层返回值进行修改增强处理。比如返回值5,需要封装成 。

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

接口源码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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);
}

2、应用场景在spring项目开发过程中

对controller层返回值进行修改增强处理。比如返回值5,需要封装成 。

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

controller层业务代码:

?
1
2
3
4
5
6
7
8
9
10
@RestController //此注解包含@ResponseBody注解
@RequestMapping ( "/nandao" )
public class ResponseBodyAdviceController {
 
     @RequestMapping (value = "/hello" , method = RequestMethod.GET)
     public int hello() {
          //业务代码省略
         return 5 ;
     }
}

实现ResponseBodyAdvice接口的切面类:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
*此注解针对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);      
     }
}

返回公共类的创建:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**
  * @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;
     }
}

到此切面增强功能就实现了,可以直接在实战项目中使用.

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我.

原文链接:https://blog.csdn.net/zuo_xiaosi/article/details/103520172 。

最后此篇关于ResponseBodyAdvice踩坑及解决的文章就讲到这里了,如果你想了解更多关于ResponseBodyAdvice踩坑及解决的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com