ResponseBodyAdvice踩坑及解决

网友投稿 1897 2023-01-03

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.getContainihttp://ngClass(), 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 {

/ * *

*该组件是否支持给定的控制器方法返回类型

*和选择的{@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 selectedConcMjyMGFwbtentType,

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 {

@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 implements Serializable {

/**

* 成功的code码

*/

private String code = "2000";

/**

* 成功时返回的数据,失败时返回具体的异常信息

*/

private T data;

/**

* 请求失败返回的提示信息,给前端进行页面展示的信息

*/

private String message ;

public RestResult() {

}

@Override

public String toString() {

rehttp://turn "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;

}

}

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

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:西安企业app开发(西安app开发公司)
下一篇:专业移动应用开发怎么样(移动应用开发专业前景分析)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~