方法简介

这里介绍三种方法对 Spring Boot 框架的web项目进行统一的异常捕获和处理,按照优先级排序如下(这个优先级不是真正的优先级,而是我为这四个方法处理异常定的优先级):

  1. @ExceptionHandler
    • 这个注解是在 Spring 3.0 中新增的注解,他可以用来处理局部的一部分异常,这个范围大致是抛出到该类里面的异常,在其它类以内被内消化的异常则不在此列。
  2. @ControllerAdvice
    • 这个注解是在 Spring 3.2 中新增的注解,它可以用于定义 @ExceptionHandler@InitBinder@ModelAttribute ,并应用到所有 @RequestMapping 中。
  3. BasicErrorController
    • 直接在 controller 层继承该类,可以对指定的状态码的返回页面进行重定向或处理返回值信息,这种方式的优势在于可以处理为进入 controller 的请求,例如资源找不到 404 ,参数错误的 500 ,还可以对被过滤器过滤后的请求进行处理。

局部异常的捕获与处理

@ExceptionHandler 是用来处理局部变量的注解,该注解适合在定义完全局异常捕获之后,再对某部分特定的类再进行颗粒化的处理。
使用这个注解之后,异常会在抛出到该类之后被捕获并处理,如果不抛出到被 @RequestMapping 注解的controller 层接口,基本上就不会触发全局变量的捕获,所以可以做内消化。

代码

LocalController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
* 局部异常处理.
* <p>对该文件内抛出的异常进行拦截并处理<br>
* 包括其他文件抛到该文件内的异常,如service层</p>
*
* @author reasuon reasuon@gmail.com
*/

@Controller
@RequestMapping("/local")
class LocalController {

@Autowired
private TestService testService;

@RequestMapping("/error")
@ResponseBody
public Map<String, Object> getHandle() {
Map<String, Object> map = new HashMap<>();
String i = testService.getHandle();
map.put("i", i);
return map;
}

/**
* 局部异常统一处理.
* <p>只对当前Java文件内的方法有效,不过如果是server层或其他Java文件的异常抛出至这里,也生效<br>
* 这种方式适合除了少且特殊的异常,如果是需要通用且大范围的异常处理,应该使用全局的方式来处理</p>
*
* @param e
* @return
*/
@ExceptionHandler
@ResponseBody
public String exceptionHandle(Exception e){
if (e instanceof NullPointerException) {
return "空指针异常!<--局部异常处理结果";
} else {
return "异常类型未知!<--局部异常处理结果";
}
}
}

这种注解的方式,会将当前页面预备往外或往上抛出的异常集中捕获并处理,这样处理完之后,用户那倒的就不会是什么包什么类下的多少行往外抛出了一个空指针异常,而是收到我们处理之后的字符串。
未完待续…