ResponseBodyAdvice常见问题及解决方法

发布时间:2021-06-29 12:00:42 作者:chen
来源:亿速云 阅读:1722

这篇文章主要讲解了“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()不调用

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

ResponseBodyAdvice接口属于springMVC 和springBoot框架基础的底层切面接口;实现这个接口的类,可以修改直接作为 ResponseBody类型处理器的返回值,即进行功能增强。

1、有两种类型的处理器会将返回值作为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);
}

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

对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常见问题及解决方法这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

推荐阅读:
  1. MySQL MHA配置的常见问题及解决方法
  2. FusionCharts常见问题及解决方法(二)

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

responsebodyadvice

上一篇:用Python代码实现一键批量扣图

下一篇:如何使用CSS3按钮鼠标悬浮实现光圈效果

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》