springboot ErrorPageFilter的实际应用

Spring框架错误页过滤器

springboot提供了一个ErrorPageFilter,用来处理当程序发生错误时如何展现错误,话不多说请看代码

private void doFilter(HttpServletRequest request, HttpServletResponse response,
            FilterChain chain) throws IOException, ServletException {
    ErrorWrapperResponse wrapped = new ErrorWrapperResponse(response);
    try {
        chain.doFilter(request, wrapped);
        if (wrapped.hasErrorToSend()) {
            // 重点关注此方法
            handleErrorStatus(request, response, wrapped.getStatus(),
                    wrapped.getMessage());
            response.flushBuffer();
        }
        else if (!request.isAsyncStarted() && !response.isCommitted()) {
            response.flushBuffer();
        }
    }
    catch (Throwable ex) {
        Throwable exceptionToHandle = ex;
        if (ex instanceof NestedServletException) {
            exceptionToHandle = ((NestedServletException) ex).getRootCause();
        }
        handleException(request, response, wrapped, exceptionToHandle);
        response.flushBuffer();
    }
}
private void handleErrorStatus(HttpServletRequest request,
            HttpServletResponse response, int status, String message)
                    throws ServletException, IOException {
    if (response.isCommitted()) {
        handleCommittedResponse(request, null);
        return;
    }
    // 获取错误页,来关注下这个属性this.statuses,就是一个map,而错误页就是从这属性中获取,那此属性的内容是什么时候添加进去的呢
    String errorPath = getErrorPath(this.statuses, status);
    if (errorPath == null) {
        response.sendError(status, message);
        return;
    }
    response.setStatus(status);
    setErrorAttributes(request, status, message);

    // 拿到错误页地址后,通过服务器重定向的方式跳转到错误页面
    request.getRequestDispatcher(errorPath).forward(request, response);
}

ErrorPageFilter implements Filter, ErrorPageRegistry,此类实现了ErrorPageRegistry接口,接口内方法如下,我们可以看到这个入参errorPages便是错误页集合,然后把所有错误页put到statuses属性内,但是此方法入参从何而来呢?

@Override
public void addErrorPages(ErrorPage... errorPages) {
    for (ErrorPage errorPage : errorPages) {
        if (errorPage.isGlobal()) {
            this.global = errorPage.getPath();
        }
        else if (errorPage.getStatus() != null) {
            this.statuses.put(errorPage.getStatus().value(), errorPage.getPath());
        }
        else {
            this.exceptions.put(errorPage.getException(), errorPage.getPath());
        }
    }
}

通过源码分析,发现此接口,只要实现此接口并生成bean交给spring,便可以往ErrorPageRegistry添加你自己的错误页了。

public interface ErrorPageRegistrar {

    /**
     * Register pages as required with the given registry.
     * @param registry the error page registry
     */
    void registerErrorPages(ErrorPageRegistry registry);

}

看个例子吧,这样就可以了,是不是很简单。

@Component
public class MyErrorPage implements ErrorPageRegistrar {

    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {
        ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/WEB-INF/errorpage/404.html");
        ErrorPage error405Page = new ErrorPage(HttpStatus.METHOD_NOT_ALLOWED, "/WEB-INF/errorpage/405.html");
        ErrorPage error500Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/WEB-INF/errorpage/500.html");
        registry.addErrorPages(error404Page, error405Page, error500Page);
    }
}

版权声明:本文为lynn349x原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。