web應用中spring提供了幾種加載方式:
1.在web.xml中配置:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
2.在web.xml中配置:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
1和2兩種方式,實質是一樣的,因爲在他們各自的初始化方法中,調用的是一樣的創建spring容器的方法
這是1中的:
public void init() throws ServletException {
contextLoader = createContextLoader();
contextLoader.initWebApplicationContext(getServletContext());
}
這是2中的:
public void contextInitialized(ServletContextEvent event) {
contextLoader = createContextLoader();
contextLoader.initWebApplicationContext(event.getServletContext());
}
所以這兩種加載spring容器的方法本質上一樣,spring容器初始化完後,就放到servletContext中。
其key值爲:WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
我們如果要使用WebApplicationContext則需要從ServletContext取出,Spring提供了一個WebApplicationContextUtils類,可以方便的取出
WebApplicationContext,只要把ServletContext傳入就可以了。
獲得applicationContext 方法:
ServletContext context = getServletContext();
WebApplicationContext applicationContext = WebApplicationContextUtils
.getWebApplicationContext(context);
DataSource dataSource=(DataSource)applicationContext.getBean("dataSource");
這個方便的類是針對以上面的方式創建的spring容器而用的。
3.在struts.xml中配置加載spring的插件:
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml,/WEB-INF/action-servlet.xml" />
</plug-in>
這種方法初始化的spring容器,也放在servletContext中,
其key值爲:
ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX+ModuleConfig.getPrefix()(具體請查看源代碼)。
4.在web.xml中配置:
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext</param-value>
</init-param>
</servlet>
獲得applicationContext 方法:
ServletContext context = getServletContext();
XmlWebApplicationContext applicationContext = (XmlWebApplicationContext) context.getAttribute
("org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcherServlet");
DataSource dataSource=(DataSource)applicationContext.getBean("dataSource");
************************************************************************************
spring和struts的結合方式。
兩者的結合可以有以下三種方式:
1.使用 Spring 的 ActionSupport 類整合 Structs
2.使用 Spring 的 DelegatingRequestProcessor 覆蓋 Struts 的 RequestProcessor
3.將 Struts Action 管理委託給 Spring 框架
第1種方式用我們自己的Action繼承ActionSupport。這種方式只是方便了我們在action中獲得spring容器對象,在ActionSupport中提供了getWebApplicationContext()方法。獲得了spring容器後,就可以享用spring容器中的bean了。
第2種方式和第3種方式,都是把Struts Action 管理委託給 Spring 框架 ,只是委託方式不一樣。
第2種方式使用 Spring 的 DelegatingRequestProcessor 覆蓋 Struts 的 RequestProcessor。而DelegatingRequestProcessor 所做的工作,也就是,獲得spring容器,獲得被spring容器管理的真正action。
第3種方式在struts.xml中的action配置中配置:
<action path="/searchSubmit" type="org.springframework.web.struts.DelegatingActionProxy"> ...
而這個代理action:DelegatingActionProxy所做的工作也是,獲得spring容器,獲得被spring容器管理的真正action。
這3種結合方式,都需要獲得spring容器,而上面也說到,spring容器的創建也有三種方式(本質上是三種,目前爲止我知道的)。
三種創建spring容器的方式,都在他們創建完spring容器後,將spring容器,放到servletContext對象中,但key值不一樣。這也就決定了獲得spring容器的方法是不同的。
在這三種spring和struts的結合方式中都通過以下方式獲得spring容器:
DelegatingActionUtils.findRequiredWebApplicationContext(ActionServlet actionServlet, ModuleConfig moduleConfig)
而這種方法會先去尋找以struts插件形式,創建的spring容器。也就是以上面spring加載方式3中的key值到servletContext中找。
如果找不到,再調用WebApplicationContextUtils.getWebApplicationContext(ServletContext context)方法獲得spring容器。
由WebApplicationContextUtils類獲得的spring容器和由DelegatingActionUtils類獲得的spring容器是不同的。這兩種獲得方法是針對不同的spring容器創建方法的。前者對應的創建方法是上面spring創建方法的第1,2兩種。後者對應的創建方法是上面spring創建方法的第3種。
結論:spring和struts的三種結合方式中,會先去尋找以struts插件形式,創建的spring容器。所以我們在struts中配置spring的加載插件,可以滿足這三種結合方式。在找不到以struts插件形式,創建的spring容器後,會去找以ContextLoaderListener或ContextLoaderServlet創建的spring容器,所以,不管以那種方式創建的spring容器都能滿足spring和struts的三種結合方式。(第4種創建spring容器方式除外)。
這只是自己的分析,還沒實踐,需要研究。