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