前言
实现ResponseBodyAdvice<T>
接口是对controller的返回值后,返回浏览器等客户端前,对返回结果进行的处理操作。接口有两个方法可实现:
- boolean supports
- Object beforeBodyWrite
使用@ControllerAdvice
是@Component注解的一个延伸注解,Spring会自动扫描并检测被@ControllerAdvice所标注的类。这里我们自动检测路径下的Controller类,对指定的controller进行统一增强
处理。同理的,我们也可以用它进行统一异常处理。具体可查看@ControllerAdvice
详情。
@ControllerAdvice(basePackages = "com.cbry.controller")
@Component
public class InterceptResponse implements ResponseBodyAdvice<Object> {
public boolean supports...
public Object beforeBodyWrite...
}
supports和beforeBodyWrite
supports:根据类和方法来判断是否需要执行beforeBodyWrite方法进行response处理;
beforeBodyWrite:对response结果进行的逻辑处理操作;
@Override
//判断是否要执行beforeBodyWrite方法,true为执行,false不执行
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
@Override
//对response处理的执行方法
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
return null;
}
supports
controller返回的方法类型(MethodParameter
)和HttpMessageConverter 类型(HttpMessageConverter
),决定了下面的beforeBodyWrite业务逻辑处理是否生效。
在supports方法里面我们编写是否生效的逻辑代码。
@Override
public boolean supports(MethodParameter methodParameter,
Class<? extends HttpMessageConverter<?>> aClass) {
return methodParameter.hasMethodAnnotation(ResponseBody.class);
}
beforeBodyWrite
对于controller返回的结果值:Object o 参数, 我们进行统一的格式返回结果处理。 并且可以使用request参数来获取对应域的相关信息,比如说用户信息。返回信息统一封装到一个data里面。
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
ServletServerHttpRequest request = (ServletServerHttpRequest) serverHttpRequest;
HttpServletRequest servletRequest = request.getServletRequest();
String role = servletRequest.getAttribute(Constants.USERROLE).toString();
Map<String,Object> res = new HashMap<>();
res.put("role",role);
res.put("data",o);
return res;
}
如果有编写统一的实体类,比如说DataResult
,controller统一返回该类,其实可以:
DataResult dataResult = (DataResult)o;
//do something
return o;
统一返回体效果
{“message”:“OK”,“data”:{“pageNo”:1,“pageSize”:10},“role”:“admin”,“curAccount”:“cbry”,“status”:200}