詳細SpringBoot教程之(zhī)Web開發(三)
發表時(shí)間:2020-2-26
發布人(rén):融晨科技
浏覽次數:54
寫在(zài)前面
鑒于(yú)有人(rén)留言說(shuō)想要(yào / yāo)學習SpringBoot相關的(de)知識,我這(zhè)裏打算寫一個(gè)SpringBoot系列的(de)相關博文,目标呢是(shì)想讓看了(le/liǎo)這(zhè)一系列博文的(de)同學呢,能夠對SpringBoot略窺門徑,這(zhè)一系列的(de)博文初步都定下來(lái)包括SpringBoot介紹、入門、配置、日志相關、web開發、數據訪問、結合docker、緩存、消息隊列、檢索、任務安全、分布式等等一系列的(de)博文,工作量很大(dà),是(shì)個(gè)漫長的(de)過程,每一步我都盡量詳細,配上(shàng)截圖說(shuō)明,也(yě)希望對看的(de)同學真的(de)有用。
單純就(jiù)是(shì)想分享技術博文,還想說(shuō)一句就(jiù)是(shì),如果覺得有用,請點個(gè)關注、給個(gè)贊吧,也(yě)算對我來(lái)說(shuō)是(shì)個(gè)寬慰,畢竟也(yě)得掉不(bù)少頭發,嘿嘿嘿
系列文章傳送條
詳細SpringBoot教程之(zhī)入門(一)
詳細SpringBoot教程之(zhī)入門(二)
詳細SpringBoot教程之(zhī)配置文件(一)
詳細SpringBoot教程之(zhī)配置文件(二)
詳細SpringBoot教程之(zhī)日志框架
詳細SpringBoot教程之(zhī)Web開發(一)
詳細SpringBoot教程之(zhī)Web開發(二)
詳細SpringBoot教程之(zhī)Web開發(三)
詳細SpringBoot教程之(zhī)數據訪問
詳細SpringBoot教程之(zhī)啓動配置原理
詳細SpringBoot教程之(zhī)緩存開發
錯誤處理機制
SpringBoot默認的(de)錯誤處理機制
我們接上(shàng)一篇博文的(de)項目,我們現在(zài)把攔截器關掉,直接在(zài)主配置文件注釋掉注入就(jiù)可以(yǐ)直接關掉了(le/liǎo),像這(zhè)樣
然後我們現在(zài)通過浏覽器随便訪問一個(gè)不(bù)存在(zài)的(de)連接,會出(chū)現下面這(zhè)樣的(de)錯誤提示,應該不(bù)陌生吧,之(zhī)前肯定是(shì)遇到(dào)過的(de)。
我們可以(yǐ)查看一下浏覽器發送請求的(de)請求頭,如下:
當然SpringBoot還另外規定了(le/liǎo)客戶端訪問無效鏈接的(de)錯誤機制,如果我們通過客戶端訪問會返回一個(gè)默認的(de)json數據,像下面這(zhè)樣
{
"timestamp": 1519637719324,
"status": 404,
"error": "Not Found",
"message": "No message avaliable",
"path": "/dbc/aaa",
}
默認錯誤處理機制原理
老樣子(zǐ),我們想要(yào / yāo)錯誤處理機制也(yě)有自己的(de)自動配置類(之(zhī)前說(shuō)過,SpringBoot功能是(shì)通過配置文件來(lái)進行控制的(de),而(ér)配置文件一般是(shì)通過xxxAutoConfiguration這(zhè)樣的(de)自動配置類來(lái)實現的(de)),所以(yǐ)SpringBoot的(de)默認的(de)錯誤處理機制可以(yǐ)參照自動配置類,也(yě)就(jiù)是(shì)ErrorMvcAutoConfiguration。
ErrorMvcAutoConfiguration通過給給容器中添加了(le/liǎo)以(yǐ)下組件,來(lái)控制錯誤處理機制
- DefaultErrorAttributes:幫我們在(zài)頁面共享信息;
- BasicErrorController:處理默認/error請求
- ErrorPageCustomizer:系統出(chū)現錯誤以(yǐ)後來(lái)到(dào)error請求進行處理;
- DefaultErrorViewResolver:用來(lái)控制錯誤時(shí),啓用模闆引擎視圖,還是(shì)默認;
也(yě)就(jiù)是(shì)默認的(de)錯誤處理流程是(shì),一但系統出(chū)現4xx或者5xx之(zhī)類的(de)錯誤,ErrorPageCustomizer就(jiù)會生效(定制錯誤的(de)響應規則),接着就(jiù)會來(lái)到(dào)/error請求,然後就(jiù)可以(yǐ)通過BasicErrorController來(lái)進行處理,進行相應時(shí),響應頁面去哪個(gè)頁面是(shì)由DefaultErrorViewResolver解析得到(dào)的(de);
如何定制錯誤響應
如何定制錯誤頁面
如果有模闆引擎的(de)情況下(我們項目中使用的(de)是(shì)Thymeleaf模闆引擎),可以(yǐ)通過error/狀态碼的(de)形式來(lái)進行控制,也(yě)就(jiù)是(shì)說(shuō),我們可以(yǐ)将錯誤頁面命名爲(wéi / wèi)“錯誤狀态碼.html”,然後放在(zài)模闆引擎文件夾(即templates目錄下)裏面的(de)error文件夾下,沒有error文件夾就(jiù)創建一個(gè),發生此狀态碼的(de)錯誤就(jiù)會來(lái)到(dào) 對應的(de)頁面,因爲(wéi / wèi)SpringBoot規則中已經默認規定好了(le/liǎo)。
更準确的(de)将我們可以(yǐ)使用4xx和(hé / huò)5xx作爲(wéi / wèi)錯誤頁面的(de)文件名,進而(ér)來(lái)匹配該種類型的(de)所有錯誤,匹配的(de)時(shí)候遵循精确優先(優先尋找精确的(de)狀态碼.html),像下面這(zhè)樣
我們在(zài)默認的(de)錯誤頁面中可以(yǐ)獲得如下信息:、
- timestamp:時(shí)間戳
- tstatus:狀态碼
- terror:錯誤提示
- texception:異常對象
- tmessage:異常消息
- terrors:JSR303數據校驗的(de)錯誤都在(zài)這(zhè)裏
這(zhè)裏要(yào / yāo)說(shuō)明一下的(de)是(shì),如果我們項目中沒有使用模闆引擎(或者模闆引擎找不(bù)到(dào)這(zhè)個(gè)錯誤頁面),就(jiù)會去靜态資源文件夾下找。如果靜态資源文件夾中也(yě)沒有錯誤頁面,就(jiù)是(shì)默認來(lái)到(dào)SpringBoot默認的(de)錯誤提示頁面。
如何定制錯誤的(de)json
可以(yǐ)自定義異常處理和(hé / huò)返回定制json數據,像下面這(zhè)樣,我們可以(yǐ)專門定義一個(gè)配置類用來(lái)解決錯誤定制的(de),我這(zhè)裏命名爲(wéi / wèi)MyExceptionHandler,然後通過@ExceptionHandler來(lái)定制響應的(de)相關錯誤,進而(ér)返回定制數據
不(bù)過這(zhè)樣處理會有個(gè)問題,就(jiù)是(shì)我們确實是(shì)定制了(le/liǎo)返回的(de)json數據,但是(shì)本來(lái)SpringBoot會根據我們用什麽訪問請求,然後響應什麽,比如我們用浏覽器訪問,響應html頁面,客戶端響應json數據,現在(zài)這(zhè)樣寫,返回的(de)都是(shì)接送數據了(le/liǎo),所以(yǐ)我們需要(yào / yāo)換種方式,通過将相應轉發到(dào)/error進行自适應響應效果處理,像下面這(zhè)樣
攜帶定制數據
前面我們講過,出(chū)現錯誤以(yǐ)後,會來(lái)到(dào)/error請求,會被BasicErrorController處理,響應出(chū)去可以(yǐ)獲取的(de)數據是(shì)由getErrorAttributes得到(dào)的(de)(是(shì)AbstractErrorController(ErrorController)規定的(de)方法)
所以(yǐ),我們可以(yǐ)通過編寫一個(gè)ErrorController的(de)實現類或者是(shì)編寫AbstractErrorController的(de)子(zǐ)類,然後放在(zài)容器中,我們要(yào / yāo)知道(dào),頁面上(shàng)能用的(de)數據,或者是(shì)json返回能用的(de)數據都是(shì)通過errorAttributes.getErrorAttributes得到(dào),也(yě)就(jiù)是(shì)說(shuō)容器中DefaultErrorAttributes.getErrorAttributes()來(lái)默認進行數據處理的(de),我們定制自定義ErrorAttributes,如下
這(zhè)樣,我們的(de)錯誤響應是(shì)自适應的(de),可以(yǐ)通過定制ErrorAttributes改變需要(yào / yāo)返回的(de)内容,就(jiù)不(bù)在(zài)隻有原先的(de)默認屬性了(le/liǎo),形象的(de)将,我們返回的(de)信息就(jiù)會是(shì)如下
- timestamp:時(shí)間戳
- tstatus:狀态碼
- terror:錯誤提示
- texception:異常對象
- tmessage:異常消息
- terrors:JSR303數據校驗的(de)錯誤都在(zài)這(zhè)裏
- author: dbc
配置嵌入式Servlet容器
SpringBoot默認使用Tomcat作爲(wéi / wèi)嵌入式的(de)Servlet容器,這(zhè)我們都是(shì)知道(dào)的(de)
那麽這(zhè)個(gè)時(shí)候我們如果想要(yào / yāo)換成其他(tā)的(de)Servlet容器,我們應該怎麽做呢?那麽接下來(lái)我們就(jiù)來(lái)講解怎麽搞
如何定制和(hé / huò)修改Servlet容器的(de)相關配置
修改和(hé / huò)server有關的(de)配置(ServerProperties即也(yě)是(shì)使用WebServerFactoryCustomizer),在(zài)主配置文件中可以(yǐ)通過這(zhè)樣的(de)形式來(lái)設置
除了(le/liǎo)在(zài)主配置文件中進行相關的(de)設置之(zhī)外,我們還可以(yǐ)通過注冊WebServerFactoryCustomizer組件來(lái)在(zài)類中自定義配置,也(yě)就(jiù)是(shì)嵌入式的(de)Servlet容器的(de)定制器,來(lái)修改Servlet容器的(de)配置
注冊Servlet三大(dà)組件
Servlet三大(dà)組件分别是(shì)Servlet、Filter、Listener,如果我們原先熟悉SpringMVC開發的(de)應該知道(dào),我們在(zài)Webapp下面的(de)web.xml中,經常需要(yào / yāo)配置這(zhè)三大(dà)組件用來(lái)過濾監聽相關的(de)請求,而(ér)在(zài)SpringBoot中,由于(yú)SpringBoot默認是(shì)以(yǐ)jar包的(de)方式啓動嵌入式的(de)Servlet容器來(lái)啓動SpringBoot的(de)web應用,所以(yǐ)并沒有沒有web.xml文件。但是(shì)我們依舊可以(yǐ)通過SpringBoot特有的(de)相關注冊Bean進行注冊,分别是(shì)
- ServletRegistrationBean
//注冊三大(dà)組件
@Bean
public ServletRegistrationBean myServlet(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new MyServlet(),"/myServlet");
return registrationBean;
}
- FilterRegistrationBean
@Bean
public FilterRegistrationBean myFilter(){
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new MyFilter());
registrationBean.setUrlPatterns(Arrays.asList("/hello","/myServlet"));
return registrationBean;
}
- ServletListenerRegistrationBean
@Bean
public ServletListenerRegistrationBean myListener(){
ServletListenerRegistrationBean<MyListener> registrationBean = new ServletListenerRegistrationBean<>(new MyListener());
return registrationBean;
}
SpringBoot幫我們自動配置SpringMVC的(de)時(shí)候,會自動的(de)注冊SpringMVC的(de)前端控制器,即DIspatcherServlet,我們通過查閱DispatcherServletAutoConfiguration發現,會默認攔截,“/”的(de)所有請求,包括靜态資源,但是(shì)不(bù)攔截jsp請求,/*會攔截jsp,可以(yǐ)通過server.servletPath來(lái)修改SpringMVC前端控制器默認攔截的(de)請求路徑
更換其他(tā)嵌入式Servlet容器
我們知道(dào),SpringBoot是(shì)默認支持Tomcat的(de),也(yě)就(jiù)是(shì)在(zài)pom.xml中通過如下依賴引入的(de)
所以(yǐ),我們不(bù)能整個(gè)去除web依賴,因爲(wéi / wèi)裏面還有其他(tā)除了(le/liǎo)Tomcat的(de)依賴,所以(yǐ)我們在(zài)web下直接排除Tomcat的(de)依賴就(jiù)可以(yǐ)了(le/liǎo),然後添加其他(tā)的(de)嵌入式Servlet容器的(de)依賴,不(bù)同的(de)嵌入式Servlet依賴如下
Jetty
Undertow
使用外置的(de)Servlet容器
在(zài)我們之(zhī)前學習的(de)SpringBoot應用,是(shì)通過嵌入式Servlet容器,應用打成可執行的(de)jar,這(zhè)樣做的(de)優點顯而(ér)易見,就(jiù)是(shì)簡單、便攜,但是(shì)缺點就(jiù)是(shì)默認不(bù)支持JSP、優化定制比較複雜(使用定制器ServerProperties、自定義WebServerFactoryCustomizer,自己編寫嵌入式Servlet容器的(de)創建工廠ConfigurableWebServerFactory);
但是(shì)不(bù)着急,我們可以(yǐ)使用外置的(de)Servlet容器,也(yě)就(jiù)是(shì)外面安裝Tomcat,然後應用war包的(de)方式打包。
步驟
-
必須創建一個(gè)war項目,利用idea創建好目錄結構
-
将嵌入式的(de)Tomcat指定爲(wéi / wèi)provided;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
- 必須編寫一個(gè)SpringBootServletInitializer的(de)子(zǐ)類,并調用configure方法
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
//傳入SpringBoot應用的(de)主程序
return application.sources(SpringBoot04WebJspApplication.class);
}
}
- 啓動服務器就(jiù)可以(yǐ)使用;
我這(zhè)裏說(shuō)一下jar包和(hé / huò)war包啓動的(de)區别
- jar包:執行SpringBoot主類的(de)main方法,啓動ioc容器,創建嵌入式的(de)Servlet容器;
- war包:啓動服務器,服務器啓動SpringBoot應用通過SpringBootServletInitializer,啓動ioc容器;