﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-nexstone</title><link>http://www.blogjava.net/nexstone/</link><description /><language>zh-cn</language><lastBuildDate>Mon, 04 May 2026 22:33:05 GMT</lastBuildDate><pubDate>Mon, 04 May 2026 22:33:05 GMT</pubDate><ttl>60</ttl><item><title>Spring整合第三方MVC框架的通用配置</title><link>http://www.blogjava.net/nexstone/archive/2007/11/10/159632.html</link><dc:creator>nexstone</dc:creator><author>nexstone</author><pubDate>Sat, 10 Nov 2007 14:14:00 GMT</pubDate><guid>http://www.blogjava.net/nexstone/archive/2007/11/10/159632.html</guid><wfw:comment>http://www.blogjava.net/nexstone/comments/159632.html</wfw:comment><comments>http://www.blogjava.net/nexstone/archive/2007/11/10/159632.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/nexstone/comments/commentRss/159632.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/nexstone/services/trackbacks/159632.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最近在读李刚老师著的《轻量级J2EE企业应用实战》，写得非常不错，尤其是对于象我这样的初学者很有帮助。我在学习过程中，自己做了一些例子和总结。下面是关于Struts与Spring整合的知识。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Spring整合第三方MVC框架的通用配置</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果需要使用第三方MVC框架，则不能在web.xml文件中配置ApplicationContext的启动。但是，ApplicationContext是Spring的容器，负责管理所有的组件，从业务逻辑层组件，到持久层组件，都必须运行在Spring容器中。因此，必须在Web应用启动时，创建Spring的ApplicationContext实例。事实上，Spring ApplictionContext作为IoC容器，总应该优先加载。<br />
不管采用怎样的方法，Spring容器都应该在应用启动时，自动加载。为了让Spring容器能自动加载，通常有两个做法：<br />
1.让MVC框架负责创建ApplicationContext实例，MVC框架加载时自动创建Spring容器。Struts就是采用这种机制与Spring整合。<br />
2.采用load-on-startup Servlet实现。<br />
根据Servlet2.3标准，所有的ServletContextListener都会比Servlet优先加载——即使是load-on-startup Servlet。ApplicationContext实例是Spring容器，负责管理应用中所有的组件，包括业务逻辑层组件和持久层组件。因此，应该尽可能早的创建Spring容器。<br />
为此，应该优先采用listener创建ApplicationContext。只是，ServletContextListener是从Servlet 2.3才出现的规范。如果使用了不支持Servlet2.3以上的Web服务器，则只能放弃ServletContextListener，采用load-on-startup Servlet策略。<br />
Spring管理的组件相当多，如果将所有的组件部署在同一个配置文件里。不仅会降低配置文件的可读性，增大修改配置文件时引入错误的可能性，也不符合软件工程&#8220;分而治之&#8221;的规则。通常推荐服务层对象，业务逻辑对象，DAO对象都存在于互不相同的Context中，而表现层对象如Spring MVC控制器，则被配置在表现层Context中。甚至将某个特定模块的组件部署在单独的Context中。<br />
实际的应用中，Spring的配置文件通常不只一个，而是按功能被分成多个。好在，所有负责加载Spring容器的工具都可同时加载多个配置文件。</p>
<p>一. 采用ContextLoaderListener创建ApplicationContext<br />
使用ContextLoaderListener创建ApplicationContext必须服务器支持listener，下面这些服务器都是支持Listener的，如果使用这些服务器，则可以使用ContextLoaderListener创建ApplicationContext实例：<br />
1.Apache Tomcat 4.x+ 。<br />
2.etty 4.x+ 。<br />
3.Resin 2.1.8+ 。<br />
4.Orion 2.0.2+ 。<br />
5.BEA WebLogic 8.1 SP3。<br />
Spring提供ServletContextListener的一个实现类ContextLoaderListener，该类可以作为listener使用，它会在创建时候自动查找WEB-INF/下的applicationContext.xml文件，因此，如果只有一个配置文件，并且文件名为applicationContext.xml，只需在web.xml文件中增加如下一段即可：<br />
&lt;listener&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;<br />
&lt;/listener&gt;<br />
如果有多个配置文件需要载入，则考虑使用&lt;context-param&gt;元素来确定配置文件的文件名。ContextLoaderListener加载时，会查找名为contextConfigLocation的参数。因此，配置context-param时参数名字应该是contextConfigLocation。<br />
带多个配置文件的web.xml文件如下：<br />
&lt;!--&nbsp; XML文件的文件头--&gt;<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!--&nbsp; web.xml文件的DTD等信息--&gt;<br />
&lt;!DOCTYPE web-app<br />
&nbsp;&nbsp;&nbsp; PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
&nbsp;&nbsp;&nbsp; "http://java.sun.com/dtd/web-app_2_3.dtd"&gt;<br />
&lt;web-app&gt;<br />
&nbsp;&lt;!--&nbsp; 确定多个配置文件--&gt;<br />
在web.xml文件中加载Spring容器，这是最常见的做法。Spring自己的MVC框架就是采用这种策略。<br />
关于让MVC框架负责创建ApplicationContext实例的情况比较多，因为每个MVC框架的启动机制有区别，因此加载ApplicationContext的方式也各有不同。 <br />
对于在web.xml配置文件中配置ApplicationContext的自动创建有两种策略：<br />
1.利用ServletContextListener实现。<br />
&lt;context-param&gt;<br />
&nbsp;&nbsp;&lt;!--&nbsp; 参数名为contextConfigLocation --&gt;<br />
&nbsp;&nbsp;&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;<br />
&nbsp;&nbsp;&lt;!--&nbsp; 多个配置文件之间以,隔开 --&gt;<br />
&nbsp;&nbsp;&lt;param-value&gt;/WEB-INF/daoContext.xml,/WEB-INF/applicationContext.xml&lt;/param-value&gt;<br />
&nbsp;&lt;/context-param&gt;<br />
&nbsp;&lt;!--&nbsp; 采用listener创建ApplicationContext实例--&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;listener&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/listener&gt;<br />
&lt;/web-app&gt;<br />
如果没有contextConfigLocation制定配置文件，Spring自动查找applicationContext.xml配置文件。<br />
如果有contextConfigLocation，则利用该参数确定的配置文件，该参数指定的一个字符串，Spring的ContextLoaderListener负责将该字符串分解成多个配置文件，逗号&#8220;,&#8221;、空格&#8220; &#8221;、分号&#8220;;&#8221;都可作为字符串的分割符。<br />
如果既然没有applicationContext.xml文件，也没有使用contextConfigLocation参数确定配置文件，或者contextConfigLocation确定的配置文件不存在，都将导致：Spring无法加载配置文件，无法正常创建ApplicationContext实例。<br />
Spring根据bean定义创建 WebApplicationContext对象，并将其保存在Web应用的ServletContext中。大部分情况下，应用中的bean无需感受到ApplicationContext的存在，只要利用ApplicationContext的IoC即可。<br />
如果需要在应用中获取ApplicationContext实例，可以通过如下方法获取：<br />
WebApplicationContext ctx = <br />
WebApplicationContextUtils.getWebApplicationContext(servletContext);<br />
下面是采用Servlet获取ApplicationContext的完整源代码：<br />
public class SpringTestServlet extends HttpServlet <br />
{<br />
&nbsp;//Servlet的响应方法。<br />
&nbsp;public void service(HttpServletRequest request, HttpServletResponse response)<br />
&nbsp;&nbsp;throws ServletException,java.io.IOException<br />
&nbsp;{z<br />
&nbsp;&nbsp;//获取Servlet的ServletContext对象<br />
&nbsp;&nbsp;ServletContext sc = getServletContext();<br />
&nbsp;&nbsp;//使用WebApplicationContextUtils类获得ApplicationContext<br />
&nbsp;&nbsp;WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sc);<br />
&nbsp;&nbsp;//获取Servlet的页面输出流<br />
&nbsp;&nbsp;PrintWriter out = response.getWriter();<br />
&nbsp;&nbsp;//将ApplicationContext对象输出<br />
&nbsp;&nbsp;out.println(ctx);<br />
&nbsp;}<br />
}<br />
程序里手动获取ApplicationContext对象，然后直接输出到Servlet的响应。结果看到，ApplicationContext加载了web.xml文件中指定的两个配置文件。</p>
<p>二. 采用load-on-startup Servlet创建ApplicationContext<br />
如果容器不支持Listener，则只能使用load-on-startup Servlet创建ApplicationContext实例，下面的容器都不支持Listener：<br />
1.BEA WebLogic up to 8.1 SP2。 <br />
2.IBM WebSphere 5.x 。<br />
3.Oracle OC4J 9.0.3。<br />
Spring提供了一个特殊的Servlet类：ContextLoaderServlet。该Servlet在启动时，会自动查找WEB-INF/下的applicationContext.xml文件。<br />
当然，为了让ContextLoaderServlet随应用启动而启动，应将此Servlet配置成load-on-startup的Servlet，load-on-startup的值小一点比较合适，因为要保证ApplicationContext优先创建。如果只有一个配置文件，并且文件名为：applicationContext.xml。在web.xml文件中增加如下一段即可：<br />
&lt;servlet&gt;<br />
&nbsp;&lt;servlet-name&gt;context&lt;/servlet-name&gt;<br />
&nbsp;&lt;servlet-class&gt;org.springframework.web.context.ContextLoaderServlet&lt;/servlet-class&gt;<br />
&nbsp;&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />
&lt;/servlet&gt;<br />
该Servlet用于提供&#8220;后台&#8221;服务，作为容器管理应用中的其他bean，不需要响应客户请求，因此无需配置servlet-mapping。<br />
如果有多个配置文件，一样使用&lt;context-param&gt;元素来确定多个配置文件。事实上，不管是ContextLoaderServlet，还是ContextLoaderListener，都依赖于ContextLoader创建ApplicationContext实例。在ContextLoader代码的第240行，有如下代码：<br />
String configLocation = servletContext.getInitParameter(CONFIG_LOCATION_PARAM);<br />
if (configLocation != null) {<br />
&nbsp;wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation,<br />
&nbsp;ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS));<br />
}<br />
其中CONFIG_LOCATION_PARAM是该类的常量，其值为contextConfigLocation。可看出：ContextLoader首先检查servletContext中是否有contextConfigLocation的参数，如果有该参数，则加载该参数指定的配置文件。带多个配置文件的web.xml文件如下：<br />
&lt;!--&nbsp; XML文件的文件头--&gt;<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!--&nbsp; web.xml文件的DTD等信息--&gt;<br />
&lt;!DOCTYPE web-app<br />
&nbsp;&nbsp;&nbsp; PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
&nbsp;&nbsp;&nbsp; "http://java.sun.com/dtd/web-app_2_3.dtd"&gt;<br />
&lt;web-app&gt;<br />
&nbsp;&lt;!--&nbsp; 确定多个配置文件--&gt;<br />
&nbsp;&lt;context-param&gt;<br />
&nbsp;&nbsp;&lt;!--&nbsp; 参数名为contextConfigLocation --&gt;<br />
&nbsp;&nbsp;&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;<br />
&nbsp;&nbsp;&lt;!--&nbsp; 多个配置文件之间以,隔开 --&gt;<br />
&nbsp;&nbsp;&lt;param-value&gt;/WEB-INF/daoContext.xml,/WEB-INF/applicationContext.xml&lt;/param-value&gt;<br />
&nbsp;&lt;/context-param&gt;<br />
&nbsp;&lt;!--&nbsp; 采用load-on-startup Servlet创建ApplicationContext实例--&gt;<br />
&lt;servlet&gt;<br />
&nbsp;&nbsp;&lt;servlet-name&gt;context&lt;/servlet-name&gt;<br />
&nbsp;&nbsp;&lt;servlet-class&gt;org.springframework.web.context.ContextLoaderServlet&lt;/servlet-class&gt;<br />
&nbsp;&nbsp;&lt;!--&nbsp; 下面值小一点比较合适，会优先加载--&gt;<br />
&nbsp;&nbsp;&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />
&lt;/servlet&gt;<br />
&lt;/web-app&gt;<br />
测试所用的Servlet与前面所用的没有区别。ContextLoaderServlet与ContextLoaderListener底层都依赖于ContextLoader。因此，二者的效果几乎没有区别。之间区别不是它们本身引起的，而是由于Servlet2.3的规范：listener比servlet优先加载。因此，采用ContextLoaderListener创建ApplicationContext的时机更早。<br />
当然，也可以通过ServletContext的getAttribute方法获取ApplicationContext，使用WebApplicationContextUtils类更便捷，因为无需记住ServletContext属性名。即使ServletContext的WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE属性没有对应对象，WebApplicationContextUtils的getWebApplicationContext()方法将会返回空，而不会引起异常。<br />
获得了WebApplicationContext实例的引用后，可以通过bean的名字访问容器中的bean实例。大部分时候，无需通过这种方式访问容器中的bean。将表现层的控制器bean置入容器的管理中，客户端请求直接转发给容器中的bean，然后由容器管理bean之间的依赖，因此，无需手动获取ApplicationContext引用。当然，每个框架都会有自己特定的整合策略。</p>
<img src ="http://www.blogjava.net/nexstone/aggbug/159632.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nexstone/" target="_blank">nexstone</a> 2007-11-10 22:14 <a href="http://www.blogjava.net/nexstone/archive/2007/11/10/159632.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>