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