Spring Framework中applicationContext.xml和spring-servlet.xml的区别
Posted
技术标签:
【中文标题】Spring Framework中applicationContext.xml和spring-servlet.xml的区别【英文标题】:Difference between applicationContext.xml and spring-servlet.xml in Spring Framework 【发布时间】:2011-04-08 19:14:27 【问题描述】:applicationContext.xml
和 spring-servlet.xml
在 Spring Framework 中是否相关?
applicationContext.xml
中声明的属性文件是否可用于DispatcherServlet
?
在相关说明中,我为什么需要*-servlet.xml
?为什么单独applicationContext.xml
不够?
【问题讨论】:
也可以看看这个。 ***.com/questions/11708967/… 【参考方案1】:Spring 允许您在父子层次结构中定义多个上下文。
applicationContext.xml
定义了“根 webapp 上下文”的 bean,即与 webapp 关联的上下文。
spring-servlet.xml
(或任何其他名称)为一个 servlet 的应用程序上下文定义了 bean。在一个 web 应用程序中可以有很多这些,每个 Spring servlet 一个(例如,spring1-servlet.xml
用于 servlet spring1
,spring2-servlet.xml
用于 servlet spring2
)。
spring-servlet.xml
中的 Bean 可以引用 applicationContext.xml
中的 bean,反之则不行。
所有 Spring MVC 控制器都必须进入 spring-servlet.xml
上下文。
在大多数简单的情况下,applicationContext.xml
上下文是不必要的。它通常用于包含在 webapp 中的所有 servlet 之间共享的 bean。如果您只有一个 servlet,那么没有什么意义,除非您有特定用途。
【讨论】:
为什么会有多个 spring servlet? 强大有力的答案(因为简洁) @NimChimpsky 有时分离应用程序中可能在同一上下文中发生冲突的部分很有用。例如,您可能有 ReST 服务和标准视图,然后您可能对视图有不同的视图解析器或服务的安全问题。 人们应该在阅读文档和开发应用程序之前看到这个答案!在正常情况下,根本不需要 ContextLoaderListener 和 contextConfigLocation,只需 DispatcherServlet! 在许多教程中,contextConfigLocation 包含 dispatcher-servlet.xml 以及 DispatcherServlet。这会导致 bean 被初始化两次!【参考方案2】:我还要补充一点。在spring-servlet.xml
中,我们包括对控制器包的组件扫描。
在下面的示例中,我们包含控制器包的过滤器注释。
<!-- Scans for annotated @Controllers in the classpath -->
<context:component-scan base-package="org.test.web" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
在applicationcontext.xml
中,我们为不包括控制器的剩余包添加过滤器。
<context:component-scan base-package="org.test">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
【讨论】:
为什么?为什么不一次扫描整个东西? @NimChimpsky 您必须在 servlet 上下文中扫描@Controller
bean(Spring MVC 需要)。
为什么不能整件事两次?为什么包含/排除?
还应该在 spring-servlet.xml 中添加 use-default-filters="false" 属性
Rakesh Waghela 有观点。如果没有该属性,Controller bean 将被创建两次。首先在 appContext 中,然后在 servletContext 中【参考方案3】:
场景 1
在客户端应用程序中(应用程序不是 Web 应用程序,例如可能是 Swing 应用程序)
private static ApplicationContext context = new ClassPathXmlApplicationContext("test-client.xml");
context.getBean(name);
不需要 web.xml。 ApplicationContext 作为获取 bean 服务的容器。不需要 Web 服务器容器。 在 test-client.xml 中可以有没有远程处理的简单 bean,有远程处理的 bean。
结论:在场景 1 中 applicationContext 和 DispatcherServlet
不相关。
场景 2
在服务器应用程序中(部署在服务器中的应用程序,例如 Tomcat)。通过客户端程序(例如 Swing 应用程序)远程访问服务
在web.xml中定义监听器
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
在服务器启动时ContextLoaderListener
实例化 applicationContext.xml 中定义的 bean。
假设您在 applicationContext.xml 中定义了以下内容:
<import resource="test1.xml" />
<import resource="test2.xml" />
<import resource="test3.xml" />
<import resource="test4.xml" />
bean 是从所有四个配置文件 test1.xml、test2.xml、test3.xml、test4 中实例化的。 xml.
结论:在场景2中applicationContext和DispatcherServlet
不相关。
场景 3
在带有 Spring MVC 的 Web 应用程序中。
在 web.xml 中定义:
<servlet>
<servlet-name>springweb</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springweb</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
当 Tomcat 启动时,springweb-servlet.xml 中定义的 bean 被实例化。
DispatcherServlet
扩展了 FrameworkServlet
。在 FrameworkServlet
bean 实例化发生在 springweb 中。在我们的例子中 springweb 是 FrameworkServlet。
结论:在场景3中applicationContext和DispatcherServlet
不相关。
场景 4
在带有 Spring MVC 的 Web 应用程序中。 springweb-servlet.xml 用于 servlet,applicationContext.xml 用于访问服务器程序中的业务服务或访问另一个服务器程序中的 DB 服务。
在 web.xml 中定义了以下内容:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>springweb</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springweb</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
在服务器启动时,ContextLoaderListener
实例化 applicationContext.xml 中定义的 bean;假设您已在此声明:
<import resource="test1.xml" />
<import resource="test2.xml" />
<import resource="test3.xml" />
<import resource="test4.xml" />
bean 都是从所有四个 test1.xml、test2.xml、test3.xml、test4.xml 实例化的。 applicationContext.xml中定义的bean实例化完成后,springweb-servlet.xml中定义的bean被实例化。
所以实例化顺序是:根(应用程序上下文),然后是 FrameworkServlet。
现在应该清楚为什么它们在哪种情况下很重要。
【讨论】:
+1。非常好。我一直在寻找这种类型的比较,但从未找到。 @abishkar bhattarai 很好,我的问题是:那么如果在“场景4”时使用@Component 和@Value 注解创建bean 会怎样 springwebDispatcherServlet
如果 url 不以 .action 结尾就不会被调用?
@lawrence 您仍然必须在 springweb-servlet.xml 中指定类路径,以便 Spring 可以在其扫描中找到该组件。【参考方案4】:
应用程序上下文提供了一种解析文本消息的方法,包括对这些消息的 i18n 的支持。 应用程序上下文提供了一种加载文件资源(例如图像)的通用方法。 应用程序上下文可以将事件发布到注册为侦听器的 bean。 容器或容器中的 bean 上的某些操作,必须通过 bean 工厂以编程方式处理,可以在应用程序上下文中以声明方式处理。 ResourceLoader 支持:Spring 的 Resource 接口使用灵活的通用抽象来处理低级资源。应用程序上下文本身是一个 ResourceLoader,因此为应用程序提供了对特定于部署的资源实例的访问权限。 MessageSource 支持:应用上下文实现 MessageSource,一个用于获取本地化消息的接口,实际实现是可插拔的
【讨论】:
【参考方案5】:简单来说,
applicationContext.xml
定义在所有 servlet 之间共享的 bean。如果您的应用程序有多个 servlet,那么在 applicationContext.xml
中定义公共资源会更有意义。
spring-servlet.xml
定义仅与该 servlet 相关的 bean。这里是调度程序 servlet。所以,你的 Spring MVC 控制器必须在这个文件中定义。
如果您在 Web 应用程序中只运行一个 servlet,那么在 spring-servlet.xml
中定义所有 bean 并没有错。
【讨论】:
我可以在 spring-servlet.xml 中定义所有的 bean,但在这种情况下也应该有可能是空的 applicationContext.xml(没有 bean)。对吗?【参考方案6】:在 Servlet 技术中,如果您想将任何输入传递给特定的 servlet,那么您需要像下面的代码一样传入 init 参数。
<servlet>
<servlet-name>DBController</servlet-name>
<servlet-class>com.test.controller.DBController</servlet-class>
<init-param>
<param-name>username</param-name>
<param-value>John</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DBController</servlet-name>
<url-pattern>/DBController</url-pattern>
</servlet-mapping>
如果你想传递一些对所有 servlet 通用的输入,那么你需要配置上下文参数。示例
<context-param>
<param-name>email</param-name>
<param-value>admin@example.com</param-value>
</context-param>
当我们使用 Spring MVC 时,就像这样,我们需要通过 init 参数向 Spring 提供的预定义 servlet 提供一些信息,即 DispatcherServlet。 所以配置是休闲的,这里我们将 spring-servlet.xml 作为 init 参数提供给 DispatcherServlet。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>Spring MVC App</display-name>
<servlet>
<servlet-name>SpringController</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringController</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
</web-app>
我们再次需要一些上下文参数。这适用于整个应用程序。 所以我们可以提供根上下文,即 applicationcontext.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>
<servlet>
<servlet-name>SpringController</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringController</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
【讨论】:
以上是关于Spring Framework中applicationContext.xml和spring-servlet.xml的区别的主要内容,如果未能解决你的问题,请参考以下文章
Spring Framework 组件注册 之 @Import
如何在 Eclipse 中查看 Spring Framework Javadoc?
Spring Framework,Spring Security - 可以在没有 Spring Framework 的情况下使用 Spring Security?
Spring Framework中applicationContext.xml和spring-servlet.xml的区别