天天看點

Struts的Action通路spring的ApplicationContext的問題

一.在spring與struts整合過程中,如何引入并初始化ApplicationContext??

有幾種方式??

1. 使用web.xml的<listener>方式引入并初始化ApplicationContext:

<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>

2. 使用web.xml的<servlet>方式引入并初始化ApplicationContext:

<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>

3. 在struts-config.xml中以<plug-in>引入并初始化ApplicationContext:

<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">

 <set-property

  property="contextConfigLocation"

  value="/WEB-INF/applicationContext.xml,/WEB-INF/action-servlet.xml" />

</plug-in>

二.struts引入spring的ApplicationContext後,如何在struts的Action中使用ApplicationContext??

1. 如果使用web.xml的<servlet>或者<listener>方式引入并初始化ApplicationContext的,

因配置檔案的位置就寫在web.xml的參數contextConfigLocation中,是以擷取了servletContext就行了,

在struts的action中擷取ApplicationContext的方法如下:

WebApplicationContext wac

 = WebApplicationContextUtils.getWebApplicationContext(

          request.getSession().getContext()

   );

2. 但如果是在struts-config.xml中以<plug-in>引入并初始化ApplicationContext的,

其實質是spring為struts提供的一個ContextLoaderPlugIn類,此類也可以加載context的xml檔案。

因為配置檔案的位置不是寫在web.xml中,而在struts-config.xml中,引而不能直接使用上面的方法,但是也需要擷取了servletContext,

那麼,在struts的action中擷取ApplicationContext的方法如下:

WebApplicationContext context

 = (WebApplicationContext)this.getServlet().getServletContext()

 .getAttribute("org.springframework.web.struts.ContextLoaderPlugIn.CONTEXT.");

3.在以上三種方式下都适用的方法:

applicationContext app

 =new classpathXmlApplicationContext("applicationContext.xml")  

 三.比較和小結:

1. 第一,二種方法的差別在于,兩種方式加載的WebApplicationContext,以不同的Key存放在ServletContext中。而如果你定義了HibernateFilter的話,spring會利用WebApplicationContextUtils來擷取WebApplicationContext,而此類并不識别ContextLoaderPlugIn類所加載的上下文,此時便會抛出異常: No WebApplicationContext found: no ContextLoaderListener registered?利用ContextLoaderListenter來加載dao、service級别的context,而對于struts的action,用ContextLoaderPlugIn加載。

2. 第三種方法的缺點很明顯, 指明配置檔案所在,耦合性增強了.

3. 有人可能會懷疑第三種情況效率是否會低,因為第三種方法以配置檔案為參數,是否意味着每次都會重新從XML檔案中加載所有的bean,但事實上不是這樣.spring的設計就是要在啟動的時候加載配置檔案,當web中再無論是用applicationContext或者是WebApplicationContext獲得beans時都不會重新加載配置檔案.

 4.

雖然上述實作了在action中使用ApplicationContext,但是這樣做,和繼承spring提供的ActionSupport類沒什麼差別,因為這樣做,同樣是引入了spring的類,至少也引入了ApplicationContext類,同樣是使得Struts與Spring緊密耦合,而且action中引入ApplicationContext目的是擷取Spring管理的bean,這樣子,action類也負責了查找Spring管理的bean,這違背了控制反轉(IOC)的原則。是以一般情況下,不要在Action中引入ApplicationContext。

建議采用另一種Struts-Spring內建方式,即使用Spring的DelegatingActionProxy代理類,利用IOC将你想使用的bean以注入到Action中,而不是在Action中使用ApplicationContext擷取你想要的bean。