ResponseBodyAdvice与@RestControllerAdvice
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可以让我们处理异常时,返回结果按自己定义的类型进行返回。
一般用于全局异常的处理,如下- @RestControllerAdvice(basePackages = "cn.codewei.aopstudy.controller")
- public class ControllerExceptionHandler {
- @ExceptionHandler(value = RuntimeException.class)
- public String runtimeExceptionHandler(RuntimeException e) {
- return "runtimeExceptionHandler: " + e.getMessage();
- }
- }
复制代码 2. ResponseBodyAdvice
ResponseBodyAdvice接口是在 Controller执行return之后,在response返回给客户端之前,执行的对response的一些处理,可以实现对response数据的一些统一封装或者加密等操作。
该接口一共有两个方法:
- supports:判断是否要执行beforeBodyWrite方法,true为执行,false不执行。通过supports方法,我们可以选择哪些类或哪些方法要对response进行处理,其余的则不处理。
- beforeBodyWrite:对 response 处理的具体执行方法。
如:- @RestControllerAdvice(basePackages = "cn.codewei.aopstudy.controller")
- public class RewriteHandler implements ResponseBodyAdvice {
- @Override
- public boolean supports(MethodParameter returnType, Class converterType) {
- // 如果标记了RewriteResponse注解(自定义的注解),则通过(需要进行处理)
- boolean b = returnType.hasMethodAnnotation(RewriteResponse.class);
- if (b){
- return true;
- }
- return false;
- }
- @Override
- public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
- String s = String.valueOf(body);
- return s + " - RewriteHandler"; // 修改返回结果
- }
- }
复制代码 3. RequestBodyAdvice
在实际项目中,往往需要对请求参数做一些统一的操作,例如参数的过滤,字符的编码,第三方的解密等等,Spring提供了RequestBodyAdvice一个全局的解决方案,免去了我们在Controller处理的繁琐。
RequestBodyAdvice仅对使用了@RequestBody注解的生效 , 因为它原理上还是AOP,所以GET方法是不会操作的。- @ControllerAdvice(basePackages = "cn.codewei.controller")//此处设置需要当前Advice执行的域 , 省略默认全局生效
- public class GlobalRequestBodyAdvice implements RequestBodyAdvice {
-
- /** 此处如果返回false , 则不执行当前Advice的业务 */
- @Override
- public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
- // return methodParameter.getMethod().isAnnotationPresent(XXApiReq.class);
- return false;
- }
-
- /**
- * @title 读取参数前执行
- * @description 在此做些编码 / 解密 / 封装参数为对象的操作
- *
- * */
- @Override
- public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
- return new XHttpInputMessage(inputMessage, "UTF-8");
- }
-
- /**
- * @title 读取参数后执行
- * @author Xingbz
- */
- @Override
- public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
- return inputMessage;
- }
-
- /**
- * @title 无请求体时的处理
- */
- @Override
- public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
- return body;
- }
- }
-
- //这里实现了HttpInputMessage 封装一个自己的HttpInputMessage
- class XHttpInputMessage implements HttpInputMessage {
- private HttpHeaders headers;
- private InputStream body;
-
- public XHttpInputMessage(HttpInputMessage httpInputMessage, String encode) throws IOException {
- this.headers = httpInputMessage.getHeaders();
- this.body = encode(httpInputMessage.getBody(), encode);
- }
-
- private InputStream encode(InputStream body, String encode) {
- //省略对流进行编码的操作
- return body;
- }
-
- @Override
- public InputStream getBody() {
- return body;
- }
-
- @Override
- public HttpHeaders getHeaders() {
- return null;
- }
- }
复制代码Spring默认提供了接口的抽象实现类RequestBodyAdviceAdapter , 我们可以继承这个类按需实现 , 让代码更简洁一点
- public abstract class RequestBodyAdviceAdapter implements RequestBodyAdvice {
-
- @Override
- public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter,
- Type targetType, Class<? extends HttpMessageConverter<?>> converterType)
- throws IOException {
-
- return inputMessage;
- }
-
- @Override
- public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
- Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
-
- return body;
- }
-
- @Override
- @Nullable
- public Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage,
- MethodParameter parameter, Type targetType,
- Class<? extends HttpMessageConverter<?>> converterType) {
-
- return body;
- }
- }
复制代码 来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |