Spring基礎–整合MVC配置 – JAVA編程語言程序開發技術文章

Spring 如何與第三方MVC框架結合?

其實就是討論如何加載ApplicationContext.xml的問題:

ApplicationContext是Spring的容器,負責管理所有的組件,從業務邏輯層組件,到持久層組件,都必須運行在Spring容器中。因此,必須在Web應用啟動時,創建Spring的ApplicationContext實例。事實上,Spring ApplictionContext作為IoC容器,總應該優先加載。

不管采用怎樣的方法,Spring容器都應該在應用啟動時,自動加載。為瞭讓Spring容器能自動加載,通常有如下做法:
一、采用ContextLoaderListener創建ApplicationContext
前提條件:必須服務器支持listener,下面這些服務器都是支持Listener:
1.Apache Tomcat 4.x+ 。
2.etty 4.x+ 。
3.Resin 2.1.8+ 。
4.Orion 2.0.2+ 。
5.BEA WebLogic 8.1 SP3。

Spring提供ServletContextListener的一個實現類ContextLoaderListener,該類可以作為listener使用,它會在創建時候自動查找WEB-INF/下的applicationContext.xml文件,因此,如果隻有一個配置文件,並且文件名為applicationContext.xml,隻需在web.xml文件中增加如下一段即可:
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
如果有多個配置文件需要載入,則考慮使用<context-param>元素來確定配置文件的文件名。ContextLoaderListener加載時,會查找名為contextConfigLocation的參數。因此,配置context-param時參數名字應該是contextConfigLocation。
帶多個配置文件的web.xml文件如下:
<context-param>
  <!–  參數名為contextConfigLocation –>
  <param-name>contextConfigLocation</param-name>
  <!–  多個配置文件之間以,隔開 –>
  <param-value>/WEB-INF/daoContext.xml,/WEB-INF/applicationContext.xml</param-value>
</context-param>
 <!–  采用listener創建ApplicationContext實例–>
<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

如果沒有contextConfigLocation制定配置文件,Spring自動查找applicationContext.xml配置文件。
如果有contextConfigLocation,則利用該參數確定的配置文件,該參數指定的一個字符串,Spring的ContextLoaderListener負責將該字符串分解成多個配置文件,逗號“,”、空格“ ”、分號“;”都可作為字符串的分割符。
如果既然沒有applicationContext.xml文件,也沒有使用contextConfigLocation參數確定配置文件,或者contextConfigLocation確定的配置文件不存在,都將導致:Spring無法加載配置文件,無法正常創建ApplicationContext實例。

Spring根據bean定義創建 WebApplicationContext對象,並將其保存在Web應用的ServletContext中。大部分情況下,應用中的bean無需感受到ApplicationContext的存在,隻要利用ApplicationContext的IoC即可。
如果需要在應用中獲取ApplicationContext實例,可以通過如下方法獲取:
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);

下面是采用Servlet獲取ApplicationContext的完整源代碼:
public class SpringTestServlet extends HttpServlet
{
 //Servlet的響應方法。
 public void service(HttpServletRequest request, HttpServletResponse response)
  throws ServletException,java.io.IOException
 {z
  //獲取Servlet的ServletContext對象
  ServletContext sc = getServletContext();
  //使用WebApplicationContextUtils類獲得ApplicationContext
  WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sc);
  //獲取Servlet的頁面輸出流
  PrintWriter out = response.getWriter();
  //將ApplicationContext對象輸出
  out.println(ctx);
 }
}
程序裡手動獲取ApplicationContext對象,然後直接輸出到Servlet的響應。結果看到,ApplicationContext加載瞭web.xml文件中指定的兩個配置文件。

二、采用ContextLoaderServlet創建ApplicationContext
如果容器不支持Listener,則隻能使用load-on-startup Servlet創建ApplicationContext實例,下面的容器都不支持Listener:
1.BEA WebLogic up to 8.1 SP2。
2.IBM WebSphere 5.x 。
3.Oracle OC4J 9.0.3。
Spring提供瞭一個特殊的Servlet類:ContextLoaderServlet。該Servlet在啟動時,會自動查找WEB-INF/下的applicationContext.xml文件。
當然,為瞭讓ContextLoaderServlet隨應用啟動而啟動,應將此Servlet配置成load-on-startup的Servlet,load-on-startup的值小一點比較合適,因為要保證ApplicationContext優先創建。如果隻有一個配置文件,並且文件名為:applicationContext.xml。在web.xml文件中增加如下一段即可:
<servlet>
 <servlet-name>context</servlet-name>
 <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
 <load-on-startup>1</load-on-startup>
</servlet>
該Servlet用於提供“後臺”服務,作為容器管理應用中的其他bean,不需要響應客戶請求,因此無需配置servlet-mapping。

如果有多個配置文件,一樣使用<context-param>元素來確定多個配置文件。

不管是ContextLoaderServlet,還是ContextLoaderListener,都依賴於ContextLoader創建ApplicationContext實例。在ContextLoader代碼的第240行,有如下代碼:
String configLocation = servletContext.getInitParameter(CONFIG_LOCATION_PARAM);
if (configLocation != null) {
 wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation,
 ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS));
}
其中CONFIG_LOCATION_PARAM是該類的常量,其值為contextConfigLocation。可看出:ContextLoader首先檢查servletContext中是否有contextConfigLocation的參數,如果有該參數,則加載該參數指定的配置文件。帶多參數的配置如下:
<context-param>
  <!–  參數名為contextConfigLocation –>
  <param-name>contextConfigLocation</param-name>
  <!–  多個配置文件之間以,隔開 –>
  <param-value>/WEB-INF/daoContext.xml,/WEB-INF/applicationContext.xml</param-value>
 </context-param>
 <!–  采用load-on-startup Servlet創建ApplicationContext實例–>
<servlet>
  <servlet-name>context</servlet-name>
  <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
  <!–  下面值小一點比較合適,會優先加載–>
  <load-on-startup>1</load-on-startup>
</servlet>

總結:
ContextLoaderServlet與ContextLoaderListener底層都依賴於ContextLoader。
因此,二者唯一的區別:是由於Servlet2.3的規范:listener比servlet優先加載。
因此,采用ContextLoaderListener創建ApplicationContext的時機更早。

當然,也可以通過ServletContext的getAttribute方法獲取ApplicationContext,使用WebApplicationContextUtils類更便捷,因為無需記住ServletContext屬性名。
即使ServletContext的WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE屬性沒有對應對象,WebApplicationContextUtils的getWebApplicationContext()方法將會返回空,而不會引起異常。

獲得瞭WebApplicationContext實例的引用後,可以通過bean的名字訪問容器中的bean實例。
大部分時候,無需通過這種方式訪問容器中的bean。因為Spring容器將bean置入容器的管理中,客戶端請求直接轉發給容器中的bean,然後由容器管理bean之間的依賴。

發佈留言