错误处理

Spring Boot默认提供一个/error映射用来以合适的方式处理所有的错误,并且它在servlet容器中注册了一个全局的 错误页面。对于机器客户端(相对于浏览器而言,浏览器偏重于人的行为),它会产生一个具有详细错误,HTTP状态,异常信息的JSON响应。对于浏览器客户端,它会产生一个白色标签样式(whitelabel)的错误视图,该视图将以HTML格式显示同样的数据(可以添加一个解析为erro的View来自定义它)。为了完全替换默认的行为,你可以实现ErrorController,并注册一个该类型的bean定义,或简单地添加一个ErrorAttributes类型的bean以使用现存的机制,只是替换显示的内容。


这一点取决于错误视图解析时的视图解析器
1. 实现了Spring的view接口的bean,器ID为error(由spring的BeanNameViewResolver所解析)
2. 如果配置了Thymeleaf,则有名为error.html的Thymeleaf魔板。
3. 如果配置了FreeMarker,则有名为error.ftl魔板
4. 如果配置了Velocity则有名为error.vm的模板
5.如果使用jsp,则有error.jsp的模板

这意味着error.html文件,放在src/main/resources/templates中,SpringBoot会为实体配置如下属性。

  • timestamp:错误发生的时间
  • status:http状态码
  • error:错误原因
  • exception:错误的原因
  • message:异常信息
  • errors:异常里的各种错误
  • trace:异常跟踪信息
  • path:发生错误的URL路径

Spring Boot中跟MVC异常处理相关的类。

这里写图片描述
Spring Boot在启动过程中会根据当前环境进行AutoConfiguration,其中跟MVC错误处理相关的配置内容,在ErrorMvcAutoConfiguration这个类中。以下会分块介绍这个类里面的配置。
在Servlet容器中添加了一个默认的错误页面

因为ErrorMvcAutoConfiguration类实现了EmbeddedServletContainerCustomizer接口,所以可以通过override customize方法来定制Servlet容器。以下代码摘自ErrorMvcAutoConfiguration:

    @Bean
    public ErrorPageCustomizer errorPageCustomizer() {
        return new ErrorPageCustomizer(this.serverProperties);
    }

private static class ErrorPageCustomizer implements ErrorPageRegistrar, Ordered {

        private final ServerProperties properties;

        protected ErrorPageCustomizer(ServerProperties properties) {
            this.properties = properties;
        }

        @Override
        public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
            ErrorPage errorPage = new ErrorPage(this.properties.getServletPrefix()
                    + this.properties.getError().getPath());
            errorPageRegistry.addErrorPages(errorPage);
        }

        @Override
        public int getOrder() {
            return 0;
        }

    }

自定义错误页面

可以看到ErrorMvcAutoConfiguration在容器中,添加了一个错误页面/error。因为这项配置的存在,如果Spring MVC在处理过程抛出异常到Servlet容器,容器会定向到这个错误页面/error。

那么我们有什么可以配置的呢?
1. 我们可以配置错误页面的url,/error是默认值,我们可以再application.properties中通过设置error.path的值来配置该页面的url;
2. 我们可以提供一个自定义的EmbeddedServletContainerCustomizer,添加更多的错误页面,比如对不同的http status code,使用不同的错误处理页面。就像下面这段代码一样:

package com.lf.config;

import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.web.servlet.ErrorPage;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;

/**
 * Created by LF on 2017/4/16.
 */
@Configuration
public class MyCustomizer {

@Bean
    public EmbeddedServletContainerCustomizer add() {
        return container -> {
            container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404"));
            container.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500"));
        };

    }
}

新增一个controller,主要目的在于针对响应码为500,404的错误:

package com.lf.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by LF on 2017/4/16.
 */
@Controller
public class ExceptionController {

    @RequestMapping("/404")
    public String catchException() {
        return "404";
    }

    @RequestMapping("/500")
    public String showServerError() {
        return "500";
    }
}

在templates文件夹下面添加404.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8"/>
    <title>404</title>
</head>
<body>
<h1>Error Handler</h1>
404
</body>
</html>

那么发生404的错误的时候
那么浏览器中结果如下:
这里写图片描述
也可以用如下的方式:

package com.lf.config;

import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.web.servlet.ErrorPage;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;

/**
 * Created by LF on 2017/4/16.
 */
@Configuration
public class MyCustomizer {

    @Bean
    public EmbeddedServletContainerCustomizer add() {
        return container -> {
            container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404.html"));
            container.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500.html"));
        };

    }
}

错误页面需要放在Spring Boot web应用的static内容目录下,它的默认位置是:src/main/resources/static,如下图所示:
这里写图片描述
这两种方法基本上类上

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐