在SpringMVC中可以使用ControllerAdvice来做controller内部的全局异常处理,但对于未进入controller前的异常,该处理方法是无法进行捕获处理的,SpringBoot提供了ErrorController的处理类来处理所有的异常。
20190530补充:
springboot提供了/error的错误管理端点和默认的BasicErrorController实现类,但这个Controller实现类其实不一定符合我们的需求,所以我们才需要来覆盖这个默认实现。
其中:BasicErrorController extend AbstractErrorController ,AbstractErrorController 又 implements ErrorController。
下面的类是直接实现了ErrorController,其实我们也可以仿照BasicErrorController来继承AbstractErrorController减少一些代码的编写。
1 import java.util.Map;
2
3 import javax.servlet.http.HttpServletRequest;
4
5 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.boot.autoconfigure.web.ErrorAttributes;
7 import org.springframework.boot.autoconfigure.web.ErrorController;
8 import org.springframework.http.HttpStatus;
9 import org.springframework.web.bind.annotation.RequestMapping;
10 import org.springframework.web.bind.annotation.ResponseStatus;
11 import org.springframework.web.bind.annotation.RestController;
12 import org.springframework.web.context.request.RequestAttributes;
13 import org.springframework.web.context.request.ServletRequestAttributes;
14
15 import com.tomato.boss.common.base.ResponseResult;
16
17 import lombok.extern.slf4j.Slf4j;
18 import springfox.documentation.annotations.ApiIgnore;
19
20 /**
21 * 全局异常处理,当异常被@ControllerAdvice时不会走到这个处理类,没被处理时会走到这里
22 * 例如 @valid入参校验失败的是不会走ControllerAdvice的,但会走这个处理器
23 * @author yangzhilong
24 *
25 */
26 @RestController
27 @ApiIgnore
28 @Slf4j
29 public class GolablExceptionEndpoint implements ErrorController{
30
31 private static final String PATH = "/error";
32
33 @Autowired
34 private ErrorAttributes errorAttributes;
35
36 @Override
37 public String getErrorPath() {
38 return PATH;
39 }
40
41 /**
42 * 全局异常处理
43 * 增加@ResponseStatus注解将非200的http状态码转成200
44 * @return
45 */
46 @RequestMapping(value = PATH)
47 @ResponseStatus(code=HttpStatus.OK)
48 public ResponseResult<Object> error(HttpServletRequest request) {
49 return handlerError(request, false);
50 }
51
52 /**
53 * 具体的处理
54 * @param request
55 * @param includeStackTrace
56 * @return
57 */
58 private ResponseResult<Object> handlerError(HttpServletRequest request, boolean includeStackTrace) {
59 RequestAttributes requestAttributes = new ServletRequestAttributes(request);
60 Throwable e = errorAttributes.getError(requestAttributes);
61
62 Map<String, Object> data = errorAttributes.getErrorAttributes(requestAttributes, includeStackTrace);
63
64 String message = null;
65 StringBuilder detailMessage = new StringBuilder("");
66
67 HttpStatus status = getStatus(request);
68 if(status == HttpStatus.BAD_REQUEST) {
69 log.error("参数校验失败", e);
70 message = "请检查数据填写是否合法";
71 } else if(status == HttpStatus.INTERNAL_SERVER_ERROR) {
72 log.error("系统错误", e);
73 message = "系统繁忙";
74 } else if(status == HttpStatus.NOT_FOUND) {
75 log.error("404错误");
76 message = "服务或者页面不存在";
77 } else {
78 log.error("系统错误", e);
79 message = "系统出错,未知错误";
80 }
81 if(null != data.get("error")) {
82 detailMessage.append(String.valueOf(data.get("error"))).append(":");
83 }
84 if(null == e || null == e.getMessage()) {
85 if(null != data.get("message")) {
86 detailMessage.append(String.valueOf(data.get("message")));
87 }
88 } else {
89 detailMessage.append(e.getMessage());
90 }
91
92 return ResponseResult.buildFailResponse(String.valueOf(data.get("status")), message, detailMessage.toString());
93 }
94
95 /**
96 * 获取错误编码
97 * @param request
98 * @return
99 */
100 private HttpStatus getStatus(HttpServletRequest request) {
101 Integer statusCode = (Integer) request
102 .getAttribute("javax.servlet.error.status_code");
103 if (statusCode == null) {
104 return HttpStatus.INTERNAL_SERVER_ERROR;
105 }
106 try {
107 return HttpStatus.valueOf(statusCode);
108 }
109 catch (Exception ex) {
110 return HttpStatus.INTERNAL_SERVER_ERROR;
111 }
112 }
113 }
来源:https://www.cnblogs.com/yangzhilong/p/7904665.html