1.介紹
在日常開發中發生了異常,往往是需要通過一個統一的異常處理處理所有異常,來保證客戶端能夠收到友好的提示。SpringBoot在頁面發生異常的時候會自動把請求轉到/error,SpringBoot內置了一個BasicErrorController
對異常進行統一的處理,當然也可以自定義這個路徑
application.yaml
1
2
3
4
|
server: port: 8080 error: path: /custom/error |
BasicErrorController提供兩種返回錯誤一種是頁面返回、當你是頁面請求的時候就會返回頁面,另外一種是json請求的時候就會返回json錯誤
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
@RequestMapping (produces = "text/html" ) public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes( request, isIncludeStackTrace(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); ModelAndView modelAndView = resolveErrorView(request, response, status, model); return (modelAndView == null ? new ModelAndView( "error" , model) : modelAndView); } @RequestMapping @ResponseBody public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL)); HttpStatus status = getStatus(request); return new ResponseEntity<Map<String, Object>>(body, status); } |
分別會有如下兩種返回
1
2
3
4
5
6
7
|
{ "timestamp" : 1478571808052, "status" : 404, "error" : "Not Found" , "message" : "No message available" , "path" : "/rpc" } |
2.通用Exception處理
通過使用@ControllerAdvice來進行統一異常處理,@ExceptionHandler(value = Exception.class)來指定捕獲的異常
下面針對兩種異常進行了特殊處理分別返回頁面和json數據,使用這種方式有個局限,無法根據不同的頭部返回不同的數據格式,而且無法針對404、403等多種狀態進行處理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@ControllerAdvice public class GlobalExceptionHandler { public static final String DEFAULT_ERROR_VIEW = "error" ; @ExceptionHandler (value = CustomException. class ) @ResponseBody public ResponseEntity defaultErrorHandler(HttpServletRequest req, CustomException e) throws Exception { return ResponseEntity.ok( "ok" ); } @ExceptionHandler (value = Exception. class ) public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception { ModelAndView mav = new ModelAndView(); mav.addObject( "exception" , e); mav.addObject( "url" , req.getRequestURL()); mav.setViewName(DEFAULT_ERROR_VIEW); return mav; } } |
3.自定義BasicErrorController 錯誤處理
在初始介紹哪里提到了BasicErrorController,這個是SpringBoot的默認錯誤處理,也是一種全局處理方式。咱們可以模仿這種處理方式自定義自己的全局錯誤處理
下面定義了一個自己的BasicErrorController,可以根據自己的需求自定義errorHtml()和error()的返回值。
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
@Controller @RequestMapping ( "${server.error.path:${error.path:/error}}" ) public class BasicErrorController extends AbstractErrorController { private final ErrorProperties errorProperties; private static final Logger LOGGER = LoggerFactory.getLogger(BasicErrorController. class ); @Autowired private ApplicationContext applicationContext; /** * Create a new {@link org.springframework.boot.autoconfigure.web.BasicErrorController} instance. * * @param errorAttributes the error attributes * @param errorProperties configuration properties */ public BasicErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties) { this (errorAttributes, errorProperties, Collections.<ErrorViewResolver>emptyList()); } /** * Create a new {@link org.springframework.boot.autoconfigure.web.BasicErrorController} instance. * * @param errorAttributes the error attributes * @param errorProperties configuration properties * @param errorViewResolvers error view resolvers */ public BasicErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties, List<ErrorViewResolver> errorViewResolvers) { super (errorAttributes, errorViewResolvers); Assert.notNull(errorProperties, "ErrorProperties must not be null" ); this .errorProperties = errorProperties; } @Override public String getErrorPath() { return this .errorProperties.getPath(); } @RequestMapping (produces = "text/html" ) public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes( request, isIncludeStackTrace(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); ModelAndView modelAndView = resolveErrorView(request, response, status, model); insertError(request); return modelAndView == null ? new ModelAndView( "error" , model) : modelAndView; } @RequestMapping @ResponseBody public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL)); HttpStatus status = getStatus(request); insertError(request); return new ResponseEntity(body, status); } /** * Determine if the stacktrace attribute should be included. * * @param request the source request * @param produces the media type produced (or {@code MediaType.ALL}) * @return if the stacktrace attribute should be included */ protected boolean isIncludeStackTrace(HttpServletRequest request, MediaType produces) { ErrorProperties.IncludeStacktrace include = getErrorProperties().getIncludeStacktrace(); if (include == ErrorProperties.IncludeStacktrace.ALWAYS) { return true ; } if (include == ErrorProperties.IncludeStacktrace.ON_TRACE_PARAM) { return getTraceParameter(request); } return false ; } /** * Provide access to the error properties. * * @return the error properties */ protected ErrorProperties getErrorProperties() { return this .errorProperties; } } |
SpringBoot提供了一種特殊的Bean定義方式,可以讓我們容易的覆蓋已經定義好的Controller,原生的BasicErrorController是定義在ErrorMvcAutoConfiguration中的
具體代碼如下:
1
2
3
4
5
6
|
@Bean @ConditionalOnMissingBean (value = ErrorController. class , search = SearchStrategy.CURRENT) public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) { return new BasicErrorController(errorAttributes, this .serverProperties.getError(), this .errorViewResolvers); } |
可以看到這個注解@ConditionalOnMissingBean 意思就是定義這個bean 當 ErrorController.class 這個沒有定義的時候, 意思就是說只要我們在代碼里面定義了自己的ErrorController.class時,這段代碼就不生效了,具體自定義如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
@Configuration @ConditionalOnWebApplication @ConditionalOnClass ({Servlet. class , DispatcherServlet. class }) @AutoConfigureBefore (WebMvcAutoConfiguration. class ) @EnableConfigurationProperties (ResourceProperties. class ) public class ConfigSpringboot { @Autowired (required = false ) private List<ErrorViewResolver> errorViewResolvers; private final ServerProperties serverProperties; public ConfigSpringboot( ServerProperties serverProperties) { this .serverProperties = serverProperties; } @Bean public MyBasicErrorController basicErrorController(ErrorAttributes errorAttributes) { return new MyBasicErrorController(errorAttributes, this .serverProperties.getError(), this .errorViewResolvers); } } |
在使用的時候需要注意MyBasicErrorController不能被自定義掃描Controller掃描到,否則無法啟動。
3.總結
一般來說自定義BasicErrorController這種方式比較實用,因為可以通過不同的頭部返回不同的數據格式,在配置上稍微復雜一些,但是從實用的角度來說比較方便而且可以定義通用組件
本文代碼:SpringBoot-Learn.rar
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://blog.csdn.net/king_is_everyone/article/details/53080851