uniapp开发app框架在提升开发效率中的独特优势与应用探索
2023
2023-01-03
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
/**
* 成功的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小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~