spring mvc DispatcherServlet解读
spring mvc DispatcherServlet解讀
DispatcherServlet的繼承和實現
IDEA按快捷鍵:ctrl+alt+u,就可以查看DispatcherServlet的繼承的類和實現的接口。
從繼承圖可以得知:
- DispatcherServlet本質是一個HttpServlet
- HttpServletBean,FrameworkServlet,DispatcherServlet是屬于SpringMVC的類
DispatcherServlet初始化
DispatcherServlet
DispatcherServlet看initStrategies(),該方法用于初始化各類解析器。
onRefresh(ApplicationContext context),該方法用于刷新策略
/*** This implementation calls {@link #initStrategies}. */ //刷新策略 @Override protected void onRefresh(ApplicationContext context) {initStrategies(context); }/*** Initialize the strategy objects that this servlet uses.* <p>May be overridden in subclasses in order to initialize further strategy objects. */ //初始化各類解析器 protected void initStrategies(ApplicationContext context) {initMultipartResolver(context); //初始化分段上傳解析器initLocaleResolver(context); //初始化地域解析器initThemeResolver(context); //初始化主題解析器initHandlerMappings(context); //初始化處理器映射initHandlerAdapters(context); //初始化處理器適配器initHandlerExceptionResolvers(context); //初始化處理器異常解析器initRequestToViewNameTranslator(context); //初始化請求到視圖名解析器initViewResolvers(context); //初始化視圖解析器initFlashMapManager(context); //初始化快閃映射 }FrameworkServlet
onRefresh(ApplicationContext context)重寫于父類FrameworkServlet,點開FrameworkServlet,我們主要看看它initServletBean()方法,FrameworkServlet的onRefresh(ApplicationContext context)是個空實現,因為在DispatcherServlet實現了。
initServletBean()是重寫HttpServletBean的initServletBean(),先看看initServletBean()干了什么:
- 調用了initWebApplicationContext(),初始化了WebApplicationContext,而WebApplicationContext是繼承于ApplicationContext接口的,所以我們知道了initWebApplicationContext是初始化了一個上下文。
- 調用了initFrameworkServlet(),點開發現是個空實現。
點開initWebApplicationContext(),因為太長了,所以放圖片。
上半段:
- 通過servlet上下文中創建了一個rootcontext
- 中間的if代碼塊在上下文刷新時才會運行,初始化狀態時,webapplicationcontext是null,所以初始化時是不進入的。該段代碼主要用于刷新上下文
下半段:
- 查找已經存在的注冊的上下文,如果沒有就用rootContex去創建一樣上下文。
- refreshEventReceived默認是false
- onRefresh()方法被重寫了,所以我們知道在Dispatchservlet中,會初始化各種解析器(如:視圖解析器等)
HttpServletBean
假設WEB-INF 目錄下查找配置文件信息如下:
<!-- 部署 DispatcherServlet --> <servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet </servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc-servlet.xml</param-value></init-param><!-- 表示容器再啟動時立即加載servlet --><load-on-startup>1</load-on-startup> </servlet> <servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern> </servlet-mapping>HttpServletBean是抽象類,ctrl+F12查看方法。
找到init()方法,這個是我們要找到的重要方法
- init()方法是重寫了GenericServlet的init()方法,所以這個是最根本的初始化方法。
讓我們看看init()干了什么:
ServletConfigPropertyValues是用來加載Servlet配置,ServletConfigPropertyValues是HttpServletBean的內部靜態類,它負責取到web.xml中init-param(如:contextConfigLocation)
@Overridepublic final void init() throws ServletException {//加載web.xml中init-param(如:contextConfigLocation)// Set bean properties from init parameters.PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);if (!pvs.isEmpty()) {try {//BeanWrapper將HttpServletBean進行包裝BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);//ServletContext的資源加載器ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());//注冊資源編輯器bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));//為HttpServletBean初始化包裝,默認實現是空的initBeanWrapper(bw);//給包裝類傳遞web.xml中init-parambw.setPropertyValues(pvs, true);}catch (BeansException ex) {if (logger.isErrorEnabled()) {logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);}throw ex;}}// Let subclasses do whatever initialization they like.//initServletBean()是交給子類實現的,FrameworkServlet實現了這個方法initServletBean();}初始化總結
各類的初始化工作:
- HttpServletBean 主要初始化web.xml資源
- FrameworkServlet 獲取servlet上下文創建WebApplicationContext
- DispatcherServlet 初始化各類解析器
調用過程
DispatcherServlet處理請求
核心成員變量
DispatcherServlet的核心成員變量就是上面DispatcherServlet初始化中initStrategies(ApplicationContext context)初始化的各類處理器。
/** MultipartResolver used by this servlet. */@Nullableprivate MultipartResolver multipartResolver;/** LocaleResolver used by this servlet. */@Nullableprivate LocaleResolver localeResolver;/** ThemeResolver used by this servlet. */@Nullableprivate ThemeResolver themeResolver;/** List of HandlerMappings used by this servlet. */@Nullableprivate List<HandlerMapping> handlerMappings;/** List of HandlerAdapters used by this servlet. */@Nullableprivate List<HandlerAdapter> handlerAdapters;/** List of HandlerExceptionResolvers used by this servlet. */@Nullableprivate List<HandlerExceptionResolver> handlerExceptionResolvers;/** RequestToViewNameTranslator used by this servlet. */@Nullableprivate RequestToViewNameTranslator viewNameTranslator;/** FlashMapManager used by this servlet. */@Nullableprivate FlashMapManager flashMapManager;/** List of ViewResolvers used by this servlet. */@Nullableprivate List<ViewResolver> viewResolvers;doService()
在瀏覽器輸入位置時,會觸發DispatcherServlet的doService(HttpServletRequest request, HttpServletResponse response)去處理請求。
doService(HttpServletRequest request, HttpServletResponse response)又會去調用doDispatch(HttpServletRequest request, HttpServletResponse response)去處理請求
doDispatch()
doDispatch比較多代碼分成兩段截圖
上半段代碼
下半段代碼
還有
getHandler()
getHandler()會遍歷所有的handlerMapping,并找出匹配的handler。
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {if (this.handlerMappings != null) {for (HandlerMapping mapping : this.handlerMappings) {HandlerExecutionChain handler = mapping.getHandler(request);if (handler != null) {return handler;}}}return null;}關于handlerMapping接口的實現類
handlerMapping接口的實現類有許多,RequestMappingHandlerMapping,該類用于創建@RequestMapping和@Controller注解的實例
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的spring mvc DispatcherServlet解读的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringMVC获取Request,R
- 下一篇: s3c2440移植MQTT