spring boot 异常处理

来源:互联网 发布:快递怎么发掘淘宝客户 编辑:程序博客网 时间:2024/04/28 14:33

spring boot在异常的处理中,默认实现了一个EmbeddedServletContainerCustomizer并定义了一个错误页面到”/error”中,在ErrorMvcAutoConfiguration源码中可以看到

/** * {@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的错误页面

@Beanpublic 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"));    }}
0 0
原创粉丝点击