您的位置:首頁技術文章
文章詳情頁

SpringBoot2.3定制錯誤頁面的方法示例

瀏覽:3日期:2023-05-02 18:18:26

一. 問題背景

后臺: SpringBoot 2.3.1(官方2.3版本修改了很多,拋棄了很多以前能用的方法)前端: Layui(前端用哪個框架問題不大)

技術: SpringBoot+Thymeleaf+Layui

情況:我想將Layui提供好的錯誤頁面作為SpringBoot默認的錯誤頁面,而且Layui提供的錯誤頁面位置并不是放在/靜態資源文件夾/error,而是在如下:

SpringBoot2.3定制錯誤頁面的方法示例

二. SpringBoot的錯誤頁面機制

錯誤頁面機制的原理詳情可以看Day41——錯誤處理原理&定制錯誤頁面以及Day42——定制錯誤數據。

首先要知道SpringBoot的錯誤頁面機制原理自動配置是由ErrorMvcAutoConfiguration配置的。所以定制錯誤頁面的解決方案都可以參考ErrorMvcAutoConfiguration類以及參考他人博客。

這里只做簡單的回顧,如下:

SpringBoot2.3定制錯誤頁面的方法示例

三. 定制錯誤頁面

首先我項目里面在application.properties配置了靜態資源路徑為classpath:/templates/layuimini/,如下:

#自定義靜態資源路徑spring.resources.static-locations=classpath:/templates/layuimini/

大家根據需要自行調整自己項目里面的靜態資源路徑,后面的定制錯誤頁面的路徑會根據這個配置好的路徑去尋找,或者拼串。

3.1 方案一(最簡單的,但是不推薦)

3.1.1 步驟

最簡單是 在靜態資源文件夾下面創建一個error文件夾,在里面放置自己的錯誤頁面,如下:

SpringBoot2.3定制錯誤頁面的方法示例

不推薦的原因是,我當前的目錄結構是所有的頁面都是放在/templates/layuimini/page/文件夾下面的,如果按照上面做法,會破壞我的目錄結構,后期維護很困難。

3.1.2 原理

在BasicErrorController中,封裝視圖的時候,當前項目如果有模板引擎,會先用模板引擎解析,找不到再去靜態資源文件夾尋找視圖(視圖名是error/狀態碼.html,這是指error文件夾下的狀態碼.html文件,這是由私有方法實現的,所以外部無法修改)。因此上面的步驟就是SpringBoot先去templates文件夾下找,找不到,再去/templates/layuimini/這個靜態資源文件夾找(前提是你設置了靜態資源文件夾;否則默認按SpringBoot的默認靜態資源文件夾找,比如resources、public、static、resource)

3.2 方案二(不能實現自適應定制錯誤頁面,不推薦)

3.2.1 步驟

首先放置好自定義的錯誤頁面,是在/templates/layuimini/page/error/,如下:

SpringBoot2.3定制錯誤頁面的方法示例

然后再創建一個MyErrorPageConfig類,最最最關鍵的是new ErrorPage()中第二個入參,如果是加了.html,那么就會直接找頁面,如果沒有加,那么將它當作請求去找controller,如下:

@Configurationpublic class MyErrorPageConfig { @Bean public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer(){ return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() { @Override public void customize(ConfigurableWebServerFactory factory) {ErrorPage errorPage1 = new ErrorPage(HttpStatus.NOT_FOUND, '/page/error/4xx.html');ErrorPage errorPage2 = new ErrorPage(HttpStatus.NOT_FOUND, '/page/error/5xx.html');factory.addErrorPages(errorPage1, errorPage2); } }; }}

3.2.2 原理

詳情可以參考Day46——SpringBoot2.x版本的嵌入式Servlet容器自動配置原理以及Day47——嵌入式Servlet容器啟動原理

首先要知道SpringBoot2.x版本的嵌入式Servlet容器是由ServletWebServerFactoryAutoConfiguration類配置的。一切的配置信息以及解決方案都可以參考這個類。

這里只做簡單解釋,如下:

SpringBoot2.3定制錯誤頁面的方法示例

這樣它就會執行上面步驟中的customize()方法中的方法

3.3 方案三(實現自適應)

自適應就是根據發送的/error請求是瀏覽器還是客戶端,使用不同的controller方法進行處理,并返回不同類型的數據

3.3.1 步驟

創建一個實現了ErrorController接口的MyBasicErrorController類,如下:

/** * 定制ErrorController,目的是能使SpringBoot找到自己定制的錯誤頁面 * 大部分的代碼BasicController一致,關鍵點是修改錯誤頁面的路徑 */@Controller@RequestMapping(value = '/error')public class MyBasicErrorController implements ErrorController { @RequestMapping(produces = {'text/html'})//返回給瀏覽器 public String handlerError(HttpServletRequest request, Model model){ WebRequest webRequest = new ServletWebRequest(request);//對request進行包裝,目的是能操作更多的方法 HttpStatus status = this.getStatus(request);//獲取status String path = (String) webRequest.getAttribute('javax.servlet.error.request_uri', 0); String message = (String) webRequest.getAttribute('javax.servlet.error.message', 0); if(message.equals('')){ message = 'No Available Message'; } //攜帶錯誤數據信息 model.addAttribute('timestamp', new Date()); model.addAttribute('statusCode', status.value()); model.addAttribute('error', status.getReasonPhrase()); model.addAttribute('message', message); model.addAttribute('path', path); int i = status.value() / 100;//判斷是4xx還是5xx錯誤 if(i == 4){ return 'layuimini/page/error/4xx';//使用自己定制的錯誤頁面 }else if(i == 5){ return 'layuimini/page/error/5xx';//使用自己定制的錯誤頁面 } return null; } @RequestMapping//返回給客戶端 public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { WebRequest webRequest = new ServletWebRequest(request);//對request進行包裝,目的是能操作更多的方法 HttpStatus status = this.getStatus(request);//獲取status Map<String, Object> map = new HashMap<>(); if (status == HttpStatus.NO_CONTENT) { return new ResponseEntity(status); } else { String path = (String) webRequest.getAttribute('javax.servlet.error.request_uri', 0); String message = (String) webRequest.getAttribute('javax.servlet.error.message', 0); map.put('timestamp', new Date()); map.put('statusCode', status.value()); map.put('error', status.getReasonPhrase()); map.put('message', message); map.put('path', path); return new ResponseEntity(map, status); } } protected HttpStatus getStatus(HttpServletRequest request) { Integer statusCode = (Integer)request.getAttribute('javax.servlet.error.status_code'); if (statusCode == null) { return HttpStatus.INTERNAL_SERVER_ERROR; } else { try {return HttpStatus.valueOf(statusCode); } catch (Exception var4) {return HttpStatus.INTERNAL_SERVER_ERROR; } } } @Override public String getErrorPath() { return 'null'; }}

3.3.2 原理

SpringBoot的錯誤頁面機制的自適應,是由BasicErrorController實現的,而這個BasicErrorController只有在容器中沒有ErrorController的情況下,才會被注冊進容器,因此我們創建一個實現了ErrorController接口的類,這個BasicErrorController就失效,然后我們仿照BasicErrorController里面的方法來實現自己的controller就可以了。如下:

@Bean @ConditionalOnMissingBean( value = {ErrorController.class},//沒有ErrorController才會去注冊BasicErrorController search = SearchStrategy.CURRENT ) public BasicErrorController basicErrorController(ErrorAttributes errorAttributes, ObjectProvider<ErrorViewResolver> errorViewResolvers) { return new BasicErrorController(errorAttributes, this.serverProperties.getError(), (List)errorViewResolvers.orderedStream().collect(Collectors.toList())); }

上面實現步驟中的一些錯誤數據是參照DefaultErrorAttributes中的方法實現的

到此這篇關于SpringBoot2.3定制錯誤頁面的方法示例的文章就介紹到這了,更多相關SpringBoot2.3定制錯誤頁面內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Spring
相關文章:
国产综合久久一区二区三区