springboot?ErrorPageFilter的實(shí)際應(yīng)用詳解
ErrorPageFilter的實(shí)際應(yīng)用
Spring框架錯(cuò)誤頁(yè)過(guò)濾器
springboot提供了一個(gè)ErrorPageFilter,用來(lái)處理當(dāng)程序發(fā)生錯(cuò)誤時(shí)如何展現(xiàn)錯(cuò)誤,話不多說(shuō)請(qǐng)看代碼
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()) { ? ? ? ? ? ? // 重點(diǎn)關(guān)注此方法 ? ? ? ? ? ? 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; ? ? } ? ? // 獲取錯(cuò)誤頁(yè),來(lái)關(guān)注下這個(gè)屬性this.statuses,就是一個(gè)map,而錯(cuò)誤頁(yè)就是從這屬性中獲取,那此屬性的內(nèi)容是什么時(shí)候添加進(jìn)去的呢 ? ? String errorPath = getErrorPath(this.statuses, status); ? ? if (errorPath == null) { ? ? ? ? response.sendError(status, message); ? ? ? ? return; ? ? } ? ? response.setStatus(status); ? ? setErrorAttributes(request, status, message); ? ? // 拿到錯(cuò)誤頁(yè)地址后,通過(guò)服務(wù)器重定向的方式跳轉(zhuǎn)到錯(cuò)誤頁(yè)面 ? ? request.getRequestDispatcher(errorPath).forward(request, response); }
ErrorPageFilter implements Filter, ErrorPageRegistry,此類實(shí)現(xiàn)了ErrorPageRegistry接口,接口內(nèi)方法如下,我們可以看到這個(gè)入?yún)rrorPages便是錯(cuò)誤頁(yè)集合,然后把所有錯(cuò)誤頁(yè)put到statuses屬性內(nèi),但是此方法入?yún)暮味鴣?lái)呢?
@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()); ? ? ? ? } ? ? } }
通過(guò)源碼分析,發(fā)現(xiàn)此接口,只要實(shí)現(xiàn)此接口并生成bean交給spring,便可以往ErrorPageRegistry添加你自己的錯(cuò)誤頁(yè)了。
public interface ErrorPageRegistrar { ? ? /** ? ? ?* Register pages as required with the given registry. ? ? ?* @param registry the error page registry ? ? ?*/ ? ? void registerErrorPages(ErrorPageRegistry registry); }
看個(gè)例子吧,這樣就可以了,是不是很簡(jiǎn)單。
@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項(xiàng)目出現(xiàn)ErrorPageFilter異常
今天用springboot(2.2.12.RELEASE)+beetl模板的時(shí)候,由于某個(gè)模板找不到,
系統(tǒng)一直出現(xiàn)報(bào)錯(cuò)日子
[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
看了網(wǎng)上的一些解決方法,大體上都是重寫(xiě)ErrorPageFilter,然后在FilterRegistrationBean中設(shè)置 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; ? ? }
按照這個(gè)方法,我做了多次嘗試,系統(tǒng)直接報(bào)錯(cuò)說(shuō)errorPageFilter沖突了,原來(lái)是
ErrorPageFilterConfiguration.java中已經(jīng)定義了這么一個(gè)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; } }
最后我的解決方式是在啟動(dòng)類中設(shè)置:
@SpringBootApplication public class App extends SpringBootServletInitializer { public App() { ? ? super(); ? ? //下面設(shè)置為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); }
問(wèn)題解決。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
@Valid 無(wú)法校驗(yàn)List<E>的問(wèn)題
這篇文章主要介紹了@Valid 無(wú)法校驗(yàn)List<E>的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10Java線程中sleep和wait的區(qū)別詳細(xì)介紹
Java中的多線程是一種搶占式的機(jī)制,而不是分時(shí)機(jī)制。搶占式的機(jī)制是有多個(gè)線程處于可運(yùn)行狀態(tài),但是只有一個(gè)線程在運(yùn)行2012-11-11java實(shí)現(xiàn)圖片文字識(shí)別ocr
這篇文章主要介紹了java實(shí)現(xiàn)圖片文字識(shí)別ocr ,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-08-08Java常用類庫(kù)Apache Commons工具類說(shuō)明及使用實(shí)例詳解
這篇文章主要介紹了Java常用類庫(kù)Apache Commons工具類說(shuō)明及使用實(shí)例詳解,需要的朋友可以參考下2020-02-02基于Java制作一個(gè)簡(jiǎn)易的遠(yuǎn)控終端
這篇文章主要為大家詳細(xì)介紹了如何基于Java制作一個(gè)簡(jiǎn)易的遠(yuǎn)控終端,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的可以了解一下2023-04-04解決mybatis一對(duì)多關(guān)聯(lián)查詢多條數(shù)據(jù)只顯示一條的問(wèn)題
這篇文章主要介紹了解決mybatis一對(duì)多關(guān)聯(lián)查詢多條數(shù)據(jù)只顯示一條的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12解答為什么 Java 線程沒(méi)有Running狀態(tài)
Java 線程沒(méi)有Running狀態(tài)指的是一個(gè)在 JVM 中執(zhí)行 的線程處于的狀態(tài),本文小編將為大家詳解一二,需要的朋友可以參考下面文章具體內(nèi)容2021-09-09