找回密码
 立即注册
首页 业界区 安全 ResponseBodyAdvice与@RestControllerAdvice

ResponseBodyAdvice与@RestControllerAdvice

套缈 2025-5-30 10:54:58
ResponseBodyAdvice与@RestControllerAdvice

1.png

1. @RestControllerAdivce

@RestControllerAdvice是什么?
@RestControllerAdvice是一个组合注解,由@ControllerAdvice、@ResponseBody组成,而@ControllerAdvice继承了@Component,因此@RestControllerAdvice本质上是个Component,用于定义@ExceptionHandler,@InitBinder和@ModelAttribute方法,适用于所有使用@RequestMapping方法。
@RestControllerAdvice的特点:

  • 通过@ControllerAdvice注解可以将对于控制器的全局配置放在同一个位置。
  • 注解了@RestControllerAdvice的类的方法可以使用@ExceptionHandler、@InitBinder、@ModelAttribute注解到方法上。
  • @RestControllerAdvice注解将作用在所有注解了@RequestMapping的控制器的方法上。
  • @ExceptionHandler:用于指定异常处理方法。当与@RestControllerAdvice配合使用时,用于全局处理控制器里的异常。
  • @InitBinder:用来设置WebDataBinder,用于自动绑定前台请求参数到Model中。
  • @ModelAttribute:本来作用是绑定键值对到Model中,当与@ControllerAdvice配合使用时,可以让全局的@RequestMapping都能获得在此处设置的键值对
@ControllerAdvice可以指定Controller范围

  • 省略时,默认全局生效
  • basePackages:指定一个或多个包,这些包及其子包下的所有Controller都被该 @ControllerAdvice 管理。
  • basePackageClasses:是basePackages的一种变形,指定一个或多个Controller类,这些类所属的包及其子包下的所有Controller 都被该@ControllerAdvice管理。
  • assignableTypes:指定一个或多个Controller类,这些类被该@ControllerAdvice管理。
  • annotations:指定一个或多个注解,被这些注解所标记的Controller会被该@ControllerAdvice管理。
@RestControllerAdivce可以让我们处理异常时,返回结果按自己定义的类型进行返回。
一般用于全局异常的处理,如下
  1. @RestControllerAdvice(basePackages = "cn.codewei.aopstudy.controller")
  2. public class ControllerExceptionHandler {
  3.     @ExceptionHandler(value = RuntimeException.class)
  4.     public String runtimeExceptionHandler(RuntimeException e) {
  5.         return "runtimeExceptionHandler: " + e.getMessage();
  6.     }
  7. }
复制代码
2. ResponseBodyAdvice

ResponseBodyAdvice接口是在 Controller执行return之后,在response返回给客户端之前,执行的对response的一些处理,可以实现对response数据的一些统一封装或者加密等操作。
该接口一共有两个方法:

  • supports:判断是否要执行beforeBodyWrite方法,true为执行,false不执行。通过supports方法,我们可以选择哪些类或哪些方法要对response进行处理,其余的则不处理。
  • beforeBodyWrite:对 response 处理的具体执行方法。
如:
  1. @RestControllerAdvice(basePackages = "cn.codewei.aopstudy.controller")
  2. public class RewriteHandler implements ResponseBodyAdvice {
  3.     @Override
  4.     public boolean supports(MethodParameter returnType, Class converterType) {
  5.         // 如果标记了RewriteResponse注解(自定义的注解),则通过(需要进行处理)
  6.         boolean b = returnType.hasMethodAnnotation(RewriteResponse.class);
  7.         if (b){
  8.             return true;
  9.         }
  10.         return false;
  11.     }
  12.     @Override
  13.     public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
  14.         String s = String.valueOf(body);
  15.         return s + " - RewriteHandler";  // 修改返回结果
  16.     }
  17. }
复制代码
3. RequestBodyAdvice

在实际项目中,往往需要对请求参数做一些统一的操作,例如参数的过滤,字符的编码,第三方的解密等等,Spring提供了RequestBodyAdvice一个全局的解决方案,免去了我们在Controller处理的繁琐。
RequestBodyAdvice仅对使用了@RequestBody注解的生效 , 因为它原理上还是AOP,所以GET方法是不会操作的。
  1. @ControllerAdvice(basePackages = "cn.codewei.controller")//此处设置需要当前Advice执行的域 , 省略默认全局生效
  2. public class GlobalRequestBodyAdvice implements RequestBodyAdvice {
  3.     /** 此处如果返回false , 则不执行当前Advice的业务 */
  4.     @Override
  5.     public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
  6. //        return methodParameter.getMethod().isAnnotationPresent(XXApiReq.class);
  7.         return false;
  8.     }
  9.   
  10.     /**
  11.      * @title 读取参数前执行
  12.      * @description 在此做些编码 / 解密 / 封装参数为对象的操作
  13.      *
  14.      *  */
  15.     @Override
  16.     public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
  17.         return new XHttpInputMessage(inputMessage, "UTF-8");
  18.     }
  19.     /**
  20.      * @title 读取参数后执行
  21.      * @author Xingbz
  22.      */
  23.     @Override
  24.     public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
  25.         return inputMessage;
  26.     }
  27.     /**
  28.      * @title 无请求体时的处理
  29.      */
  30.     @Override
  31.     public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
  32.         return body;
  33.     }
  34. }
  35. //这里实现了HttpInputMessage 封装一个自己的HttpInputMessage
  36. class XHttpInputMessage implements HttpInputMessage {
  37.     private HttpHeaders headers;
  38.     private InputStream body;
  39.     public XHttpInputMessage(HttpInputMessage httpInputMessage, String encode) throws IOException {
  40.         this.headers = httpInputMessage.getHeaders();
  41.         this.body = encode(httpInputMessage.getBody(), encode);
  42.     }
  43.     private InputStream encode(InputStream body, String encode) {
  44.         //省略对流进行编码的操作
  45.         return body;
  46.     }
  47.     @Override
  48.     public InputStream getBody() {
  49.         return body;
  50.     }
  51.     @Override
  52.     public HttpHeaders getHeaders() {
  53.         return null;
  54.     }
  55. }
复制代码
Spring默认提供了接口的抽象实现类RequestBodyAdviceAdapter , 我们可以继承这个类按需实现 , 让代码更简洁一点
  1. public abstract class RequestBodyAdviceAdapter implements RequestBodyAdvice {
  2.         @Override
  3.         public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter,
  4.                         Type targetType, Class<? extends HttpMessageConverter<?>> converterType)
  5.                         throws IOException {
  6.                 return inputMessage;
  7.         }
  8.         @Override
  9.         public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
  10.                         Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
  11.                 return body;
  12.         }
  13.         @Override
  14.         @Nullable
  15.         public Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage,
  16.                         MethodParameter parameter, Type targetType,
  17.                         Class<? extends HttpMessageConverter<?>> converterType) {
  18.                 return body;
  19.         }
  20. }
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册