SpringBoot @ControllerAdvice

纵饮孤独 提交于 2020-02-07 03:24:10

顾名思义,@ControllerAdvice 就是 @Controller 的增强版。@ControllerAdvice 主要用来处理全局数据, 一般搭配 @ExceptionHandler@ModelAttribute 以及 @InitBinder 使用。

处理全局异常

@ControllerAdvice 最常见的使用场景就是全局异常处理。例如用户上传的文件超过了限制大小,就会抛出异常,此时可以通过 @ControllerAdvice 结合 @ExceptionHandler 定义全局异常捕获机制,只需在系统中定义 CustomExceptionHandler 类(名字不限),然后添加 @ControllerAdvice 注解即可。也可以通过 assignableTypes指定特定的 Controller类,让异常处理类只处理特定类抛出的异常:

@ControllerAdvice(assignableTypes = {ExceptionController.class})

当系统启动时,该类就会被扫描到 Spring 容器中,然后定义 uploadException 方法(名字不限),在该方法上添加了 @ExceptionHandler 注解,其中定义的 MaxUploadSizeExceededException.class 表明该方法用来处理 MaxUploadSizeExceededException 类型的异常。如果想让该方法处理所有类型的异常,只需将 MaxUploadSizeExceededException 改为 Exception 即可 。方法的参数可以有异常实例、 HttpServletResponse 以 及 HttpServletRequestModel 等 , 返回值可以是一段 JSON 、一 个ModelAndView、 一个逻辑视图名等。代码如下:

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@ControllerAdvice
public class CustomExceptionHandler {
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public void uploadException(MaxUploadSizeExceededException e, HttpServletResponse response) throws IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter printWriter = response.getWriter();
        printWriter.write("上传文件大小超出限制!");
        printWriter.flush();
        printWriter.close();
    }
}

注:

  • 以上代码只会捕获 spring.servlet.multipart.max-file-size,即单个文件超过规定值的情况,并不会捕获 spring.servlet.multipart.max-request-size 多文件超出的情况,此时若超过则页面会无响应。
  • 全局异常处理这种异常处理方式一般用来处理应用级别的异常,有一些容器级别的错误处理不了,例如从 Filter 中抛出异常,使用 @ControllerAdvice 定义的全局异常处理机制就无法处理。

添加全局数据

@ControllerAdvice 是一个全局数据处理组件, 因此也可以在 @ControllerAdvice 中配置全局数据,使用 @ModelAttribute 注解进行配置,代码如下:

@ControllerAdvice
public class GlobalConfig {
    @ModelAttribute(value = "info")
    public Map<String, String> userInfo() {
        HashMap<String, String> map = new HashMap<>();
        map.put("username", "罗贯中");
        map.put("gender", "男");
        return map;
    }
}
  • 在全局配置中添加 userlnfo 方法,返回一个 map。该方法有一个注解 @ModelAttribute,其中的 value 属性表示这条返回数据的 key,而方法的返回值是返回数据的 value。

  • 此时在任意请求的 Controller 中,通过方法参数中的 Model 都可以获取 info 的数据。

    @GetMapping("/config")
    @ResponseBody
    public void config(Model model) {
        Map<String, Object> map = model.asMap();
        Set<String> keySet = map.keySet();
        Iterator<String> iterator = keySet.iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            Object value = map.get(key);
            System.out.println(key + "-->" + value);
        }
    }
    

请求参数预处理

@ControllerAdvice 结合 @InitBinder 还能实现请求参数预处理,即将表单中的数据绑定到实体类上时进行一些额外处理。

WebDataBinder 对象中,还可以设置允许的字段、禁止的字段、必填字段以及验证器等。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!