在Spring 3.2中,新增了@ControllerAdvice、@RestControllerAdvice 注解,都是对Controller进行增强,@RestControllerAdvice = @ControllerAdvice + @ResponseBody
@ControllerAdvice主要用来处理全局数据,一般搭配@ExceptionHandler、@ModelAttribute以及@InitBinder使用。
@ControllerAdvice主要解决多Contrller中的共性问题,如公共的数据,全局异常处理,全局入参出参转换等。
平时的编码过程中,可以使用try-catch来捕获异常,通常添加try-catch是因为不添加,通过不了编译检查
如果存在运行时异常,有没有加try-catch,就出现异常抛出至浏览器,如下图,体验非常不好

并且,从错误信息可以分析出系统信息,非常的不安全,存在安全漏洞
虽然可以通过加try-catch对异常进行捕捉,但无法保证所有的人,所有的方法,都正确的添加
此时,可以使用 @ControllerAdvice结合@ExceptionHandler 用来实现全局异常处理(注意不能自己try和catch异常,否则就不会被全局异常处理捕获到)
@ControllerAdvice:用来开启全局的异常捕获
@ExceptionHandler:说明捕获哪些异常,对哪些异常进行处理。
在该类中,可以在一个方法中处理所有的异常信息。
- @Slf4j
- @ControllerAdvice
- public class GlobalExceptionHandle {
-
- @ExceptionHandler
- public DataResp
handlerException(Exception e){ - log.error("handlerException()-", e);
-
- DataResp
resp = DataResp.fail(ErrorCodeEnum.E000009, "系统异常,请稍后重试"); -
- return resp;
- }
- }
也可以定义多个方法,不同的方法处理不同的异常,返回不同的响应码与错误提示,例如专门处理空指针的方法、专门处理数组越界的方法...。
相比与HandlerExceptionResolver接口而言,使用@ExceptionHandler更能灵活地对不同的异常进行分别的处理。并且,当抛出的异常是指定异常的子类,那么照样能够被捕获和处理。
- @ControllerAdvice
- public class ExceptionConfigController
- {
- // 专门用来捕获和处理Controller层的空指针异常
- @ExceptionHandler(NullPointerException.class)
- public ModelAndView nullPointerExceptionHandler(NullPointerException e){
- ModelAndView mv = new ModelAndView(new MappingJackson2JsonView());
- mv.addObject("success",false);
- mv.addObject("mesg","请求发生了空指针异常,请稍后再试");
- return mv;
- }
-
- // 专门用来捕获和处理Controller层的运行时异常
- @ExceptionHandler(RuntimeException.class)
- public ModelAndView runtimeExceptionHandler(RuntimeException e){
- ModelAndView mv = new ModelAndView(new MappingJackson2JsonView());
- mv.addObject("success",false);
- mv.addObject("mesg","请求发生了运行时异常,请稍后再试");
- return mv;
- }
-
- // 专门用来捕获和处理Controller层的异常
- @ExceptionHandler(Exception.class)
- public ModelAndView exceptionHandler(Exception e){
- ModelAndView mv = new ModelAndView(new MappingJackson2JsonView());
- mv.addObject("success",false);
- mv.addObject("mesg","请求发生了异常,请稍后再试");
- return mv;
- }
- }
可以用来预设全局数据
方式一:
- @ControllerAdvice
- public class MyGlobalHandler {
- @ModelAttribute
- public void presetParam(Model model){
- model.addAttribute("globalAttr","this is a global attribute");
- }
- }
方式二:
- @ControllerAdvice
- public class MyGlobalHandler {
-
- @ModelAttribute()
- public Map
presetParam(){ - Map
map = new HashMap(); - map.put("key1", "value1");
- map.put("key2", "value2");
- map.put("key3", "value3");
- return map;
- }
-
- }
当 @ModelAttribute() 不传任何参数的时候,默认会把返回值的字符串值作为key,如上例的 key 则是 ”map"(值得注意的是,不支持字符串的返回值作为key)。
当 @ModelAttribute("myMap") 传参数的时候,则以参数值作为key,这里 key 则是 ”myMap“。
取值:
- @RestController
- public class AdviceController {
-
- @GetMapping("methodOne")
- public String methodOne(Model model){
- Map
modelMap = model.asMap(); - return (String)modelMap.get("globalAttr");
- }
-
-
- @GetMapping("methodTwo")
- public String methodTwo(@ModelAttribute("globalAttr") String globalAttr){
- return globalAttr;
- }
-
-
- @GetMapping("methodThree")
- public String methodThree(ModelMap modelMap) {
- return (String) modelMap.get("globalAttr");
- }
-
- }
实现对请求参数的预处理