springboot ErrorPageFilter的实际应用详解

作者:零零落落。 时间:2023-11-24 01:02:59 

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);
    }
}

springboot项目出现ErrorPageFilter异常

今天用springboot(2.2.12.RELEASE)+beetl模板的时候,由于某个模板找不到,

系统一直出现报错日子

[http-nio-8080-exec-1] ERROR o.s.b.w.s.s.ErrorPageFilter - [handleCommittedResponse,219] - Cannot forward to error page for request [/yuantuannews/list/index_1.html] as the response has already been committed. As a result, the response may have the wrong status code. If your application is running on WebSphere Application Server you may be able to resolve this problem by setting com.ibm.ws.webcontainer.invokeFlushAfterService to false

看了网上的一些解决方法,大体上都是重写ErrorPageFilter,然后在FilterRegistrationBean中设置 filterRegistrationBean.setEnabled(false);

代码如下

    @Bean
    public ErrorPageFilter errorPageFilter() {
        return new ErrorPageFilter();
    }
 
    @Bean
    public FilterRegistrationBean disableSpringBootErrorFilter(ErrorPageFilter filter) {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(filter);
        filterRegistrationBean.setEnabled(false);
        return filterRegistrationBean;
    }

按照这个方法,我做了多次尝试,系统直接报错说errorPageFilter冲突了,原来是

ErrorPageFilterConfiguration.java中已经定义了这么一个bean:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.boot.web.servlet.support;
import javax.servlet.DispatcherType;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(
   proxyBeanMethods = false
)
class ErrorPageFilterConfiguration {
   ErrorPageFilterConfiguration() {
   }
   @Bean
   ErrorPageFilter errorPageFilter() {
       return new ErrorPageFilter();
   }
   @Bean
   FilterRegistrationBean<ErrorPageFilter> errorPageFilterRegistration(ErrorPageFilter filter) {
       FilterRegistrationBean<ErrorPageFilter> registration = new FilterRegistrationBean(filter, new ServletRegistrationBean[0]);
       registration.setOrder(filter.getOrder());
       registration.setDispatcherTypes(DispatcherType.REQUEST, new DispatcherType[]{DispatcherType.ASYNC});
       return registration;
   }
}

最后我的解决方式是在启动类中设置:

@SpringBootApplication
public class App extends SpringBootServletInitializer {
public App() {
    super();
    //下面设置为false
    setRegisterErrorPageFilter(false); 
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    return application.sources(App.class);
}
public static void main(String[] args) {
    SpringApplication.run(App.class, args);
}

问题解决。 

来源:https://blog.csdn.net/lynn349x/article/details/81537956

标签:springboot,ErrorPageFilter
0
投稿

猜你喜欢

  • Spring Boot 实现图片上传并回显功能

    2021-10-11 17:45:20
  • Unity3D UI Text得分数字增加的实例代码

    2021-11-13 21:03:10
  • java过滤特殊字符操作(xss攻击解决方案)

    2022-09-27 13:48:59
  • Android 自定义输入支付密码的软键盘实例代码

    2021-08-09 11:41:43
  • Unity登录注册时限制发送验证码次数功能的解决方法

    2021-12-28 00:27:12
  • Java中的内部类使用详情

    2022-07-24 05:09:38
  • 详解java模板和回调机制

    2023-08-13 15:33:46
  • 深入理解C#中foreach遍历的使用方法

    2023-11-02 08:51:04
  • springboot框架阿里开源低代码工具LowCodeEngine

    2022-09-01 09:40:41
  • Java启用Azure Linux虚拟机诊断设置

    2022-06-28 05:42:51
  • java之swing下拉菜单实现方法

    2023-07-12 04:55:30
  • 使用java + selenium + OpenCV破解腾讯防水墙滑动验证码功能

    2023-07-23 14:32:47
  • C# 实现颜色的梯度渐变案例

    2023-11-20 22:01:06
  • 一文精通Java 多线程之全方位解读

    2022-10-23 19:15:51
  • Java JNDI案例详解

    2022-06-09 07:56:35
  • Java实现控制台输出两点间距离

    2023-05-18 11:49:11
  • Java实现设计模式之责任链模式

    2023-12-09 21:02:12
  • Android 全局Dialog的简单实现方法

    2021-06-28 10:14:40
  • Android StickListView实现悬停效果

    2022-06-06 15:54:35
  • Android编程获取GPS数据的方法详解

    2023-09-20 16:37:34
  • asp之家 软件编程 m.aspxhome.com