文章目录

  • Spring全局异常处理
  • @ControllerAdvice和@ExceptionHandler
  • 定义
  • Order


Spring全局异常处理

Spring全局异常处理(一).

@ControllerAdvice和@ExceptionHandler

从源码的介绍里可以大概的总结如下:

  • 一个注解了ControllerAdvice的类。可以定义@ExceptionHandler、@InitBinder、@ModelAttribute的方法。这样的类可以处理@Controller抛出来的异常
  • 可以通过注解@Order、@Priority或者实现Ordered接口定义优先级
  • 对于@ExceptionHandler的方法,处理异常的顺序是:优先级更高的类>异常的父类的处理方法>异常本身的处理方法
  • 默认地,@ControllerAdvice的方法适用于所有的controllers.可以通过annotations、basePackageClasses、basePackages、value、assignableTypes指定相应的controllers。如果多个同时指定,只要满足其中一个即可

定义

使用@ControllerAdvice@ExceptionHandler组合可以处理controller抛出来的异常。例子实践一下。

异常处理

@ControllerAdvice
public class ControllerAdviceExample {
    
    @ExceptionHandler(value = { ClassNotFoundException.class })
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    @ResponseBody
    public Map<String, Object> controllerAdvice(HttpServletRequest request, HttpServletResponse response, Exception ex) {
      Map<String, Object> resultMap = new HashMap<>();
      resultMap.put("message", "@ControllerAdvice & @ExceptionHandler handle exception!!!!!!!!!!!");
      return resultMap;
    }
}

控制器

@RestController
@RequestMapping("controllerAdvice")
public class ControllerAdviceController {
    @GetMapping
    public String handleException() throws Exception {
        throw new ClassNotFoundException("--------handleException----------");
    }
}

运行起来后访问/controllerAdvice得到如下结果:

spring定义全局变量 spring全局异常处理_开发语言

证明我们定义的全局异常处理起作用了。

Order

可以通过注解@link org.springframework.core.annotation.Order @Order@link javax.annotation.Priority @Priority或者实现@link org.springframework.core.Ordered Ordered接口定义优先级

我们定义两个ControllerAdvice类,分别用@Order定义优先顺序。

@Order(1)

@ControllerAdvice
// 定义优先级
@Order(1)
public class ControllerAdviceOrder1 {
  
    @ExceptionHandler(value = { ClassNotFoundException.class })
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    @ResponseBody
    public Map<String, Object> controllerAdvice(HttpServletRequest request, HttpServletResponse response, Exception ex) {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("message", getClass().getName() + " handles exception!!!!!!!!!!!");
        return resultMap;
    }
}

@Order(2)

@ControllerAdvice
// 定义优先级
@Order(2)
public class ControllerAdviceOrder2 {
    
    @ExceptionHandler(value = { ClassNotFoundException.class })
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    @ResponseBody
    public Map<String, Object> controllerAdvice(HttpServletRequest request, HttpServletResponse response, Exception ex) {
      Map<String, Object> resultMap = new HashMap<>();
      resultMap.put("message", getClass().getName() + " handles exception!!!!!!!!!!!");
      return resultMap;
    }
}

重新启动程序后访问/controllerAdvice得到如下结果:

spring定义全局变量 spring全局异常处理_java_02

@Order的值越小优先级越高,@Priority的使用方法和@Order是一样的,接下来我们看看如何实现Ordered接口定义优先级

优先级为1的实现

@ControllerAdvice
public class ControllerAdviceOrdered1 implements Ordered{
  
    @ExceptionHandler(value = { ClassNotFoundException.class })
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    @ResponseBody
    public Map<String, Object> controllerAdvice(HttpServletRequest request, HttpServletResponse response, Exception ex) {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("message", getClass().getName() + " handles exception!!!!!!!!!!!");
        return resultMap;
    }

    // 实现该函数,返回优先级的数值
    @Override
    public int getOrder() {
        return 1;
    }
}

优先级为2的实现

@ControllerAdvice
public class ControllerAdviceOrdered2 implements Ordered {
    
    @ExceptionHandler(value = { ClassNotFoundException.class })
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    @ResponseBody
    public Map<String, Object> controllerAdvice(HttpServletRequest request, HttpServletResponse response,
            Exception ex) {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("message", getClass().getName() + " handles exception!!!!!!!!!!!");
        return resultMap;
    }
    
    // 实现该函数,返回优先级的数值
    @Override
    public int getOrder() {
        return 2;
    }
}

启动程序后访问/controllerAdvice得到如下结果:

spring定义全局变量 spring全局异常处理_spring_03

接口Ordered通过实现getOrder函数实现优先级的赋值。

实现接口PriorityOrdered的类优先级低于实现了接口Ordered的类

Ordered定义优先级为1的ControllerAdvice

@ControllerAdvice
public class ControllerAdviceOrdered1 implements Ordered {
    
    @ExceptionHandler(value = { ClassNotFoundException.class })
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    @ResponseBody
    public Map<String, Object> controllerAdvice(HttpServletRequest request, HttpServletResponse response,
            Exception ex) {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("message", getClass().getName() + " handles exception!!!!!!!!!!!");
        return resultMap;
    }
    
    // 实现该函数,返回优先级的数值
    @Override
    public int getOrder() {
        return 1;
    }
}

ControllerAdvicePriorityOrdered定义优先级为2的ControllerAdvice

@ControllerAdvice
public class ControllerAdvicePriorityOrdered implements PriorityOrdered{
    @ExceptionHandler(value = { ClassNotFoundException.class })
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    @ResponseBody
    public Map<String, Object> controllerAdvice(HttpServletRequest request, HttpServletResponse response,
            Exception ex) {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("message", getClass().getName() + " handles exception!!!!!!!!!!!");
        return resultMap;
    }
    
    // 实现该函数,返回优先级的数值
    @Override
    public int getOrder() {
        return 1;
    }
}

启动程序后访问/controllerAdvice得到如下结果:

spring定义全局变量 spring全局异常处理_开发语言_04

虽然都定义了优先级为1,但是会先调用Ordered的实现。