Spring Framework中applicationContext.xml和spring-servlet.xml之间的区别

use*_*070 361 java spring

  • applicationContext.xmlspring-servlet.xml在Spring框架无论如何有关系吗?
  • 声明的属性文件applicationContext.xml是否可用DispatcherServlet
  • 在相关的说明中,为什么我需要一个*-servlet.xml?为什么applicationContext.xml单独不足?

ska*_*man 422

Spring允许您在父子层次结构中定义多个上下文.

applicationContext.xml定义了豆的"根web应用上下文",即与该web应用程序相关联的上下文.

spring-servlet.xml(你怎么称呼它或任何其他)定义了一个servlet的应用程序上下文中的豆.在webapp中可以有很多这样的,每个Spring servlet一个(例如spring1-servlet.xml对于servlet spring1,spring2-servlet.xml对于servlet spring2).

豆类spring-servlet.xml可以引用豆类applicationContext.xml,但反之亦然.

所有Spring MVC控制器都必须在spring-servlet.xml上下文中.

在大多数简单的情况下,applicationContext.xml上下文是不必要的.它通常用于包含在webapp中的所有servlet之间共享的bean.如果你只有一个servlet,那么除非你有特定的用途,否则没什么意义.

  • @NimChimpsky有时候将应用程序中可能会在同一上下文中发生冲突的部分分开是有用的.例如,您可能拥有ReST服务和标准视图,然后您可以针对视图使用不同的视图解析器或服务的安全性问题. (35认同)
  • 为什么你会有多个弹簧servlet? (30认同)
  • 在许多教程中,contextConfigLocation包含dispatcher-servlet.xml以及DispatcherServlet.这导致bean被初始化两次! (24认同)
  • 人们在阅读文档和开发应用程序之前应该看到这个答案 在正常情况下,根本不需要ContextLoaderListener和contextConfigLocation,只需要DispatcherServlet! (12认同)
  • 强大的答案(因为简洁) (5认同)
  • @NimChimpsky我喜欢你的问题,我赞成它.*为什么你会有多个弹簧servlet?*我花了一段时间来弄清楚这个上下文结构并且已经这样做了我想知道是否有人真正使用它.对于我自己,如果我有两个服务,我会将它们放在不同的.war文件中,以便我可以单独部署它们.似乎有人在创建这个servlet/mvc"功能"时遇到了很多麻烦.但对我来说,这是一个过于复杂的实用程序. (2认同)

abi*_*rai 101

场景1

在客户端应用程序中(应用程序不是Web应用程序,例如可能是swing app)

private static ApplicationContext context = new  ClassPathXmlApplicationContext("test-client.xml");

context.getBean(name);
Run Code Online (Sandbox Code Playgroud)

不需要web.xml.ApplicationContext作为获取bean服务的容器.不需要Web服务器容器.在test-client.xml中可以有Simple bean,没有远程处理,bean有远程处理.

结论:在场景1中,applicationContext DispatcherServlet与之无关.

情景2

在服务器应用程序(部署在服务器中的应用程序,例如Tomcat).通过客户端程序远程访问服务(例如Swing应用程序)

web.xml中定义侦听器

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Run Code Online (Sandbox Code Playgroud)

在服务器启动时,ContextLoaderListener实例化applicationContext.xml中定义的bean .

假设您已在applicationContext.xml中定义了以下内容:

<import resource="test1.xml" />
<import resource="test2.xml" />
<import resource="test3.xml" />
<import resource="test4.xml" />
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

当Tomcat启动时,将实例化springweb-servlet.xml中定义的bean . DispatcherServlet延伸FrameworkServlet.在FrameworkServletbean实例化中发生springweb.在我们的例子中,springweb是FrameworkServlet.

结论:在场景3中,applicationContext DispatcherServlet与之无关.

场景4

在带有Spring MVC的Web应用程序中.用于servlet和applicationContext.xml的springweb-servlet.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>
Run Code Online (Sandbox Code Playgroud)

在服务器启动时,ContextLoaderListener实例化applicationContext.xml中定义的bean ; 假设您在此声明:

<import resource="test1.xml" />
<import resource="test2.xml" />
<import resource="test3.xml" />
<import resource="test4.xml" />
Run Code Online (Sandbox Code Playgroud)

bean都是从所有四个test1.xml,test2.xml,test3.xml,test4.xml中实例化的.在applicationContext.xml中定义的bean实例化完成之后,将实例化springweb-servlet.xml中定义的bean .

所以实例化顺序是root是应用程序上下文,然后是FrameworkServlet.

现在它清楚地说明了为什么它们在哪种情况下很重要.

  • +1.非常好.我正在寻找这种类型的比较,但从未找到. (8认同)

Raj*_*aje 53

还有一点我想补充一点.在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>
Run Code Online (Sandbox Code Playgroud)

applicationcontext.xml我们为剩余套餐不包括控制器添加过滤器.

<context:component-scan base-package="org.test">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
Run Code Online (Sandbox Code Playgroud)

  • 为什么?为什么不一次只扫描整件事? (9认同)
  • 还应该在spring-servlet.xml中添加use-default-filters ="false"属性 (8认同)
  • Rakesh Waghela指出.没有该属性,Controller bean将被创建两次.首先在appContext中,其次在servletContext中 (4认同)
  • @NimChimpsky你必须在servlet上下文中扫描`@Controller` bean(Spring MVC需要). (3认同)
  • 为什么不能整整两次?为什么要包含/排除? (3认同)
  • @MikeRylander这会产生混乱,因为豆子将被扫描并创建两次.例如,如果您有DAO/Repository bean,它们将被复制,而servlet上下文中的那些bean将在没有事务的情况下运行(因为事务AOP通常仅在根上下文中声明)或Spring方法安全性(如果未在servlet上下文显式) (2认同)

Kri*_*hna 10

简单来说,

applicationContext.xml定义在所有servlet之间共享的bean.如果您的应用程序有多个servlet,那么定义中的公共资源applicationContext.xml会更有意义.

spring-servlet.xml定义仅与该servlet相关的bean.这是调度程序servlet.因此,必须在此文件中定义Spring MVC控制器.

spring-servlet.xml如果在Web应用程序中只运行一个servlet,则定义所有bean中没有任何错误.

  • 我可以在spring-servlet.xml中定义所有bean,但在这种情况下也应该有applicationContext.xml,它可能是空的(没有bean).正确? (3认同)

Raj*_*han 5

在Servlet技术中,如果要将任何输入传递给特定的servlet,则需要传递init param,如下面的代码.

 <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>
Run Code Online (Sandbox Code Playgroud)

如果你想传递一些对于所有servlet都很常见的put,那么你需要配置上下文参数.例

 <context-param>
    <param-name>email</param-name>
    <param-value>admin@example.com</param-value>
</context-param>
Run Code Online (Sandbox Code Playgroud)

因此,当我们使用Spring MVC时,我们需要向Spring提供的一些信息,即DispatcherServlet通过init param提供一些信息.所以配置就像休闲一样,这里我们提供spring-servlet.xml作为DispatcherServlet的init参数.

 <?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>
Run Code Online (Sandbox Code Playgroud)

我们再次需要一些上下文参数.这适用于整个应用.所以我们可以提供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>
Run Code Online (Sandbox Code Playgroud)