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


猜你喜欢
- 目录一、泛型类型二、为什么需要泛型三、类型擦除四、类型擦除的后遗症五、Kotlin 泛型六、上界约束七、类型通配符 & 星号投影八、
- 本文实例为大家分享了人脸认证源码faceIdentify的具体代码,供大家参考,具体内容如下人脸认证:using AForge.Video.
- 本文实例为大家分享了Android屏幕适配工具类的具体代码,供大家参考,具体内容如下DimenToolgithub地址Android 屏幕适
- 1、导入资源2、JSP代码<div class="page-container">  
- 老规矩,先上图看效果。说明TextView的跑马灯效果也就是指当你只想让TextView单行显示,可是文本内容却又超过一行时,自动从左往右慢
- 首先,通过代码定义一个委托和下面三个示例将要调用的方法:public delegate int AddHandler(int a,int b
- 如题。3.6 版本的AS,对于活动布局文件的显示有text和view模式,但是切换的按钮位置与之前版本的不同。如下图在右上角的三个按钮点击1
- 1.导入 maven依赖 <dependency> <groupId>org.spring
- 本文研究的主要是java中的null“类型”的相关实例,具体介绍如下。先给出一道简单的null相关的题目,引发我们对null的探讨,后面会根
- 1. 传统方式:在内存中读取文件内容读取文件行的标准方式是在内存中读取,Guava 和Apache Commons IO都提供了如下所示快速
- 这篇文章主要介绍了Java连接Linux服务器过程分析(附代码),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值
- 一、WIndow和windowManagerWindow是一个抽象类,它的具体实现是PhoneWindow,创建一个window很简单,只需
- 1 spring-retry是什么?以往我们在进行网络请求的时候,需要考虑网络异常的情况,本文就介绍了利用spring-retry,是spr
- 在后台工程师开发完新代码交给QA进行测试时,软件测试人员一般都会要求后台开发对单元测试的覆盖率达到一定的标准;例如我们的标准是分支覆盖率达到
- 本文介绍了eclipse下搭建hibernate5.0环境的步骤,分享给大家,具体如下:hibernate引入的jar包:hibernate
- 本文为大家分享了Android TextSwitcher文本切换器的使用,供大家参考,具体内容如下1.TextSwitcher 使
- JPA主键@Id,@IdClass,@Embeddable,@EmbeddedId1、自动主键默认情况下,主键是一个连续的64位数字(lon
- 最近经常有人问Spring Cloud Feign如何上传文件。有团队的新成员,也有其他公司的兄弟。本文简单做个总结——早期的Spring
- 本文实例讲述了C#键盘鼠标钩子的实现方法。分享给大家供大家参考。具体实现方法如下:using System;using System.Col
- 本文实例讲述了Java实现分解任意输入数的质因数算法。分享给大家供大家参考,具体如下:分解任意输入数的质因数:质因数概念:任何一个合数都可以