SpringMVC執(zhí)行過程詳細(xì)講解
SpringMVC常用組件
DispatcherServlet:前端控制器,不需要工程師開發(fā),由框架提供
作用:統(tǒng)一處理請求和響應(yīng),整個流程控制的中心,由它調(diào)用其它組件處理用戶的請求
HandlerMapping:處理器映射器,不需要工程師開發(fā),由框架提供
作用:根據(jù)請求的url、method等信息查找Handler,即控制器方法
Handler:處理器,需要工程師開發(fā)
作用:在DispatcherServlet的控制下Handler對具體的用戶請求進(jìn)行處理
HandlerAdapter:處理器適配器,不需要工程師開發(fā),由框架提供
作用:通過HandlerAdapter對處理器(控制器方法)進(jìn)行執(zhí)行
ViewResolver:視圖解析器,不需要工程師開發(fā),由框架提供
作用:進(jìn)行視圖解析,得到相應(yīng)的視圖,例如:ThymeleafView、InternalResourceView、
RedirectView
View:視圖
作用:將模型數(shù)據(jù)通過頁面展示給用戶
DispatcherServlet初始化過程
DispatcherServlet 本質(zhì)上是一個 Servlet,所以天然的遵循 Servlet 的生命周期。所以宏觀上是 Servlet生命周期來進(jìn)行調(diào)度。


初始化WebApplicationContext
所在類:org.springframework.web.servlet.FrameworkServle
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
if (this.webApplicationContext != null) {
// A context instance was injected at construction time -> use it
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac =
(ConfigurableWebApplicationContext) wac;
if (!cwac.isActive()) {
// The context has not yet been refreshed -> provide services
such as
// setting the parent context, setting the application context
id, etc
if (cwac.getParent() == null) {
// The context instance was injected without an explicit
parent -> set
// the root application context (if any; may be null) as the
parent
cwac.setParent(rootContext);
}
configureAndRefreshWebApplicationContext(cwac);
}
}
}
if (wac == null) {
// No context instance was injected at construction time -> see if one
// has been registered in the servlet context. If one exists, it is
assumed
// that the parent context (if any) has already been set and that the
// user has performed any initialization such as setting the context id
wac = findWebApplicationContext();
}
if (wac == null) {
// No context instance is defined for this servlet -> create a local one
// 創(chuàng)建WebApplicationContext
wac = createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
// Either the context is not a ConfigurableApplicationContext with
refresh
// support or the context injected at construction time had already been
// refreshed -> trigger initial onRefresh manually here.
synchronized (this.onRefreshMonitor) {
// 刷新WebApplicationContext
onRefresh(wac);
}
}
if (this.publishContext) {
// Publish the context as a servlet context attribute.
// 將IOC容器在應(yīng)用域共享
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
}
return wac;
}②創(chuàng)建WebApplicationContext
所在類:org.springframework.web.servlet.FrameworkServlet
protected WebApplicationContext createWebApplicationContext(@Nullable
ApplicationContext parent) {
Class<?> contextClass = getContextClass();
if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass))
{
throw new ApplicationContextException(
"Fatal initialization error in servlet with name '" +
getServletName() +
"': custom WebApplicationContext class [" + contextClass.getName() +
"] is not of type ConfigurableWebApplicationContext");
}
// 通過反射創(chuàng)建 IOC 容器對象
ConfigurableWebApplicationContext wac =
(ConfigurableWebApplicationContext)
BeanUtils.instantiateClass(contextClass);
wac.setEnvironment(getEnvironment());
// 設(shè)置父容器
wac.setParent(parent);
String configLocation = getContextConfigLocation();
if (configLocation != null) {
wac.setConfigLocation(configLocation);
}
configureAndRefreshWebApplicationContext(wac);
return wac;
}③DispatcherServlet初始化策略
FrameworkServlet創(chuàng)建WebApplicationContext后,刷新容器,調(diào)用onRefresh(wac),此方法在DispatcherServlet中進(jìn)行了重寫,調(diào)用了initStrategies(context)方法,初始化策略,即初始化
DispatcherServlet的各個組件
所在類:org.springframework.web.servlet.DispatcherServlet
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}SpringMVC的執(zhí)行流程
用戶向服務(wù)器發(fā)送請求,請求被SpringMVC 前端控制器 DispatcherServlet捕獲。
2) DispatcherServlet對請求URL進(jìn)行解析,得到請求資源標(biāo)識符(URI),判斷請求URI對應(yīng)的映射:
a) 不存在
i. 再判斷是否配置了mvc:default-servlet-handler
ii. 如果沒配置,則控制臺報映射查找不到,客戶端展示404錯誤

iii. 如果有配置,則訪問目標(biāo)資源(一般為靜態(tài)資源,如:JS,CSS,HTML),找不到客戶端也會展示404錯誤

b) 存在則執(zhí)行下面的流程
3) 根據(jù)該URI,調(diào)用HandlerMapping獲得該Handler配置的所有相關(guān)的對象(包括Handler對象以及Handler對象對應(yīng)的攔截器),最后以HandlerExecutionChain執(zhí)行鏈對象的形式返回。
4) DispatcherServlet 根據(jù)獲得的Handler,選擇一個合適的HandlerAdapter。
5) 如果成功獲得HandlerAdapter,此時將開始執(zhí)行攔截器的preHandler(...)方法【正向】
6) 提取Request中的模型數(shù)據(jù),填充Handler入?yún)?,開始執(zhí)行Handler(Controller)方法,處理請求。在填充Handler的入?yún)⑦^程中,根據(jù)你的配置,Spring將幫你做一些額外的工作:
a) HttpMessageConveter: 將請求消息(如Json、xml等數(shù)據(jù))轉(zhuǎn)換成一個對象,將對象轉(zhuǎn)換為指定的響應(yīng)信息
b) 數(shù)據(jù)轉(zhuǎn)換:對請求消息進(jìn)行數(shù)據(jù)轉(zhuǎn)換。如String轉(zhuǎn)換成Integer、Double等
c) 數(shù)據(jù)格式化:對請求消息進(jìn)行數(shù)據(jù)格式化。 如將字符串轉(zhuǎn)換成格式化數(shù)字或格式化日期等
d) 數(shù)據(jù)驗(yàn)證: 驗(yàn)證數(shù)據(jù)的有效性(長度、格式等),驗(yàn)證結(jié)果存儲到BindingResult或Error中
7) Handler執(zhí)行完成后,向DispatcherServlet 返回一個ModelAndView對象。
8) 此時將開始執(zhí)行攔截器的postHandle(...)方法【逆向】。
9) 根據(jù)返回的ModelAndView(此時會判斷是否存在異常:如果存在異常,則執(zhí)行
HandlerExceptionResolver進(jìn)行異常處理)選擇一個適合的ViewResolver進(jìn)行視圖解析,根據(jù)Model
和View,來渲染視圖。
10) 渲染視圖完畢執(zhí)行攔截器的afterCompletion(...)方法【逆向】。
11) 將渲染結(jié)果返回給客戶端。
到此這篇關(guān)于SpringMVC執(zhí)行過程詳細(xì)講解的文章就介紹到這了,更多相關(guān)SpringMVC執(zhí)行過程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何基于mybatis框架查詢數(shù)據(jù)庫表數(shù)據(jù)并打印
這篇文章主要介紹了如何基于mybatis框架查詢數(shù)據(jù)庫表數(shù)據(jù)并打印,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-11-11
java實(shí)現(xiàn)代碼統(tǒng)計小程序
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)代碼統(tǒng)計小程序,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-09-09
Maven中optional和scope元素的使用弄明白了嗎
這篇文章主要介紹了Maven中optional和scope元素的使用弄明白了嗎,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
Matplotlib可視化之自定義顏色繪制精美統(tǒng)計圖
matplotlib提供的所有繪圖都帶有默認(rèn)樣式.雖然這可以進(jìn)行快速繪圖,但有時可能需要自定義繪圖的顏色和樣式,以對繪制更加精美、符合審美要求的圖像.matplotlib的設(shè)計考慮到了此需求靈活性,很容易調(diào)整matplotlib圖形的樣式,需要的朋友可以參考下2021-06-06
java基于包結(jié)構(gòu)的請求路由實(shí)現(xiàn)實(shí)例分享
基于包結(jié)構(gòu)的請求路由簡單實(shí)現(xiàn)實(shí)例分享,大家參考使用吧2013-12-12
詳解Java的文件與目錄管理以及輸入輸出相關(guān)操作
這篇文章主要介紹了詳解Java的文件與目錄管理以及輸入輸出相關(guān)操作,是Java入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-09-09
Java中List集合去除重復(fù)數(shù)據(jù)的方法匯總
這篇文章主要給大家介紹了關(guān)于Java中List集合去除重復(fù)數(shù)據(jù)的方法,文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02
SpringBoot整合canal實(shí)現(xiàn)數(shù)據(jù)緩存一致性解決方案
canal主要用途是基于?MySQL?數(shù)據(jù)庫增量日志解析,提供增量數(shù)據(jù)訂閱和消費(fèi),canal是借助于MySQL主從復(fù)制原理實(shí)現(xiàn),本文將給大家介紹SpringBoot整合canal實(shí)現(xiàn)數(shù)據(jù)緩存一致性解決方案,需要的朋友可以參考下2024-03-03
深入解析System.load 與 System.loadLibrary
以下是對System.load與System.loadLibrary進(jìn)行了詳細(xì)的分析介紹。需要的朋友可以過來參考下2013-08-08

