學習java的人都知道spring,springmvc,mybatis等框架,像structs2這樣的框架是基于servlet以外實現的,而springmvc是基于servlet容器實現的,
本文將分析springmvc的核心分發器dispatcherservlet的初始化過程以及處理請求的過程,讓讀者了解這個入口servlet的作用。
在分析dispatcherservlet之前,我們先看下dispatcherservlet的繼承關系,
httpserlvetbean繼承自httpservlet。
httpservletbean覆寫了init方法,對初始化過程做了一些處理。 以下是初始化的代碼:
首先,servletconfigpropertyvalues是httpservletbean的靜態類,構造過程會使用servletconfig對象找出web.xml文件中配置參數,并設置到servletconfigpropertyvalue,使用beanwrapper來構造dispatcherservlet, 獲取servletcontextresourceloader的資源加載器,然后注冊資源編輯器,初始化beanwrapper對象,設置dispatcherservlet屬性,默認初始化servletbean不做任何處理,子類覆蓋該方法可以做任何事情,
以下是web.xml文件配置:
這段配置初始化參數為contextconfiglocation,后來構造的是beanwrapper對象, 由于contextconfiglocation在frameworkservlet中定義,但是沒有在httpservletbean中定義,利用spring的注入特性,只需要調用setcontextconfiglocation方法,就可以將contextconfiglocation設置到對應的實例當中,然后設置dispatcherservlet中contextconfiglocation(frameworkservlet中定義)的屬性,為web.xml讀取contextconfiglocation參數,該資源文件用構造springmvc的容器的上下文。
下面看下frameworkservlet這個類,frameworkservlet繼承自httpservletbean。
以下是initservletbean的代碼:
首先第一步是初始化webapplicationcontext,它是繼承于applcationcontext的接口,applcationcontext是spring容器的上下文,servlet和spring容器關聯的作用,然后初始化frameworkservlet,其實它空的,什么也做,子類重寫這個方法,可以做任何處理,不過dispatcherservlet并重寫這個方法。
下面是初始化initwebapplicationcontext的具體實現邏輯:
首先,得到根路徑,distpatcherservlet有個webapplication為參數的構造函數,如果注入了webapplication 這個對象,就會執行上圖代碼。
frameworkservlet中有個string類型的contextattribute的變量名,以它為key在servletcontextwebapplicationcontext,一般不會設置,contextattribute屬性,也就說,wac開始是null;接下來就是創建webapplicationcontext,并設置根上下文為父上下文,然后配置servletconfig,servletcontext等到這個上下文,這個類中有個函數onrefresh是一個模版方法,在webapplication成功創建后就會調用,frameworkservlet的實現類,就會重寫這個方法,并將創建的容器上下文設置到servletcontext中,這里的根上下文是web.xml中配置的contextloaderlistener監聽器中根據contextconfiglocation路徑生成的上下文。
比如這段配置文件中根據classpath:context-*.xml下的xml文件生成的根上下文。
接著看一下dispatcherservlet重寫了frameworkservlet中onrefresh方法,
可以看到initstrategies方法中,在初始化各種各種策略接口的實現類, 后面再一一分析各個策略接口的實現的詳細介紹。
總結一個三個類的作用:
httpservletbean 主要做一些初始化的工作,將web.xml中配置的參數設置到servlet中。比如servlet標簽的子標簽init-param標簽中配置的參數。
frameworkservlet 將servlet與spring容器上下文關聯。其實也就是初始化frameworkservlet的屬性webapplicationcontext,這個屬性代表springmvc上下文,它有個父類上下文,web.xml中配置的contextloaderlistener監聽器初始化的容器上下文。
dispatcherservlet 主要是初始化一些各個策略接口的實現。比如請求處理,試圖處理。處理的適配等。
dispatcherservlet請求處理過程:
先看下httpservlet提供的方法用于處理請求,service使用了模版模式,對于httpservlet的get請求,調用doget方法,post請 求,調用dopost方法........
在看下處理processrequest函數
首先,獲取于當前線程綁定的localecontext和servletrequestattributes對象,initcontexthoers函數就是讓新構造的localecontex和requestattributes進行關聯,這個關聯使用threadlocal完成,doservice方法是抽象方法,具體由dispatcherservlet實現。
最后調用resetcontextholders函數重置localecontext和requestattribute對象,解除localecontext和requestattribute對象的綁定。執行成功后,發布servletrequesthandlerevent事件,可以通過注冊監聽器來監聽該事件的發布。注冊的監聽器類型為applicationlistener接口類型。
接下來是dispatcherservlet的doservice方法.
如果該請求是include的請求,那么保留一份快照版本的request域中的數據,dodispatch方法之后,這個快照版本的數據將會覆蓋新的requet域的數據。
然后在request中設置一些屬性,最后dodispatcher進行請求分發處理。
dodispatch方法功能大致過程如下:
首先根據請求的路徑,通過requestmapping的注解映射,找到handlermethod(也就是對應controller中的方法),然后匹配路徑對應的攔截器,有了handlermethod和攔截器構造個handlerexecutionchain對象。handlerexecutionchain對象的獲取是通過handlermapping接口提供的方法中得到。
有了handlerexecutionchain之后,通過handleradapter對象進行適配處理,得到modelandview對象,handlermethod內部handle的時候,使用各種handlermethodargumentresolver實現類處理handlermethod的參數,使用各種handlermethodreturnvaluehandler實現類處理返回值,最終返回值被處理成一個modelandview對象,這期間發生的異常會被handlerexceptionresolver接口實現類進行處理.
總結: 本文主要分析dispatcherservlet及其父類frameworkservlet和httpservletbean它們的作用。以及一個請求到處理返回,大致過程的分析。
以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持服務器之家!
原文鏈接:http://www.cnblogs.com/xjz1842/p/6377732.html