spring boot 异常处理
2016-05-02 16:31
302 查看
spring boot在异常的处理中,默认实现了一个EmbeddedServletContainerCustomizer并定义了一个错误页面到”/error”中,在ErrorMvcAutoConfiguration源码中可以看到
还配置了一个默认的白板页面,在源码可以看到
在路径的处理上,定义了一个BasicErrorController来处理异常,ErrorAttributes来装载错误异常到前端
默认只要你请求的content-type是”text/html”则返回一个白版页面给你,如果是其他的content-type,则返回一个json的数据给你。
若你想自定义异常,可以通过以下方式来处理
1.你可以默认在classpath:templates下定义一个error.ftl的freemarker模版来定义异常页面
2.可以利用@ExceptionHandler来为某个特定的controller拦截异常,并返回一个json数据,当然你也可以定义全部的controller来拦截异常
3.还可以自定义server的错误页面
/** * {@link EmbeddedServletContainerCustomizer} that configures the container's error * pages. */ private static class ErrorPageCustomizer implements EmbeddedServletContainerCustomizer, Ordered { private final ServerProperties properties; protected ErrorPageCustomizer(ServerProperties properties) { this.properties = properties; } @Override public void customize(ConfigurableEmbeddedServletContainer container) { container.addErrorPages(new ErrorPage(this.properties.getServletPrefix() + this.properties.getError().getPath())); } @Override public int getOrder() { return 0; } }
还配置了一个默认的白板页面,在源码可以看到
@Configuration @ConditionalOnProperty(prefix = "server.error.whitelabel", name = "enabled", matchIfMissing = true) @Conditional(ErrorTemplateMissingCondition.class) protected static class WhitelabelErrorViewConfiguration { private final SpelView defaultErrorView = new SpelView( "<html><body><h1>Whitelabel Error Page</h1>" + "<p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p>" + "<div id='created'>${timestamp}</div>" + "<div>There was an unexpected error (type=${error}, status=${status}).</div>" + "<div>${message}</div></body></html>"); @Bean(name = "error") @ConditionalOnMissingBean(name = "error") public View defaultErrorView() { return this.defaultErrorView; } // If the user adds @EnableWebMvc then the bean name view resolver from // WebMvcAutoConfiguration disappears, so add it back in to avoid disappointment. @Bean @ConditionalOnMissingBean(BeanNameViewResolver.class) public BeanNameViewResolver beanNameViewResolver() { BeanNameViewResolver resolver = new BeanNameViewResolver(); resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10); return resolver; } }
在路径的处理上,定义了一个BasicErrorController来处理异常,ErrorAttributes来装载错误异常到前端
@Controller @RequestMapping("${server.error.path:${error.path:/error}}") public class BasicErrorController extends AbstractErrorController { private final ErrorProperties errorProperties; //... @RequestMapping(produces = "text/html") public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { response.setStatus(getStatus(request).value()); Map<String, Object> model = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML)); return new ModelAndView("error", model); } @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); } //... }
默认只要你请求的content-type是”text/html”则返回一个白版页面给你,如果是其他的content-type,则返回一个json的数据给你。
若你想自定义异常,可以通过以下方式来处理
1.你可以默认在classpath:templates下定义一个error.ftl的freemarker模版来定义异常页面
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h1> error page !! </h1> ${timestamp?string('yyyy-MM-dd HH:mm:ss')}<br/><br/> ${status} <br/><br/> ${error} <br/><br/> ${message} <br/><br/> ${path} <br/><br/> </body> </html>
2.可以利用@ExceptionHandler来为某个特定的controller拦截异常,并返回一个json数据,当然你也可以定义全部的controller来拦截异常
@ControllerAdvice(basePackageClasses = FooController.class) public class FooControllerAdvice extends ResponseEntityExceptionHandler { @ExceptionHandler(YourException.class) @ResponseBody ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) { HttpStatus status = getStatus(request); return new ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status); } private HttpStatus getStatus(HttpServletRequest request) { Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code"); if (statusCode == null) { return HttpStatus.INTERNAL_SERVER_ERROR; } return HttpStatus.valueOf(statusCode); } }
3.还可以自定义server的错误页面
@Bean public EmbeddedServletContainerCustomizer containerCustomizer(){ return new MyCustomizer(); } // ... private static class MyCustomizer implements EmbeddedServletContainerCustomizer { @Override public void customize(ConfigurableEmbeddedServletContainer container) { container.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/500")); } }