不灭的焱

革命尚未成功,同志仍须努力

作者:php-note.com  发布于:2021-03-28 00:36  分类:Java框架/系统  编辑

通过前面的教程( IDEA用Maven创建Spring MVC项目 示例 )得知,Spring MVC 默认情况下,会有2个 xml 配置文件,分别为:

  1. /WEB-INF/applicationContext.xml
  2. /WEB-INF/<servlet-name>-servlet.xml

web.xml 内容如下:

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>

    <display-name>Archetype Created Web Application</display-name>

    <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>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

1、/WEB-INF/applicationContext.xml

在系统启动时,通过监听器,加载配置文件 applicationContext.xml ,web.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>

2、/WEB-INF/<servlet-name>-servlet.xml

注意:上面的 <servlet-name>DispatcherServlet 类实例的名称,如下名称为:dispatcher

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

在系统启动时,该 DispatcherServlet 会 加载名为  dispatcher-servlet.xml 的配置文件。

当然,我们也可以手动指定其他不同名的(如:first-servlet.xml) 配置文件,如:

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/first-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

 


web.xml 配置中 ContextLoaderListener 和 DispatcherServlet 的区别

  • ContextLoaderListener:是在我们的web容器启动的时候启动的,默认会加载/WEB-INF/下面的applicationContext.xml文件。并创建一个WebApplicationContext容器。
  • DispatcherServlet:是在我们第一次访问我们的应用的时候创建的(注意:通常情况下是,配置为系统启动时创建)。这时候它默认加载在/WEB-INF下面的<servlet-name>-servlet.xml配置文件,然后也创建一个WebApplicationContext。这个WebApplicationContext将之前ContextLoaderListener创建的容器作为父容器,因此在父容器中配置的所有Bean都能够被注入到子容器中。

 

摘自:https://blog.csdn.net/sinat_36710456/article/details/78741209

 


applicationContext.xml 与 dispatch-servlet.xml 的作用及区别

dispatcher-servlet.xml(在你的项目中也可能写作springmvc-serlvet.xml、spring-serlvet.xml等等)和 applicationContext.xml 中的根元素都是<beans>,两者也同样都可以托管Java Bean,那么两者的区别何在呢?

1.两者的区别:

Spring允许你使用树形的结构定义多个上下文,而applicationContext.xml定义的是“root webapp context”,直译过来就是根应用上下文。而dispatcher-servlet.xml定义一个servlet的应用上下文,是applicationContext.xml上下文的子类。在初始化时,applicationContext.xml首先初始化,而dispatcher-servlet.xml在对应的servlet实例化时启动,因此applicationContext.xml初始化在前,而dispatcher-servlet.xml初始化在后。即使将spring servlet设置为<load-on-startup>1</load-on-startup>,即servlet在应用启动时初始化,dispatcher-servlet.xml的初始化也会在根上下文之后。在一个应用中,可以有多个像dispatcher-servlet.xml一样的上下文,每一个各自服务于一个spring的servlet,比如spring1-servlet.xml用于名字为spring1的servlet,spring2-servlet.xml用于名字为spring2的servlet,并通过在web.xml中的配置进行绑定,如下:

web.xml:

<!--++++++++++++++++++++++++++++++++++++++++++++++++++++-->
<!-- spring1 servlet -->
<!--++++++++++++++++++++++++++++++++++++++++++++++++++++-->
<servlet>
    <servlet-name>spring1</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>   
        <param-name>contextConfigLocation</param-name>
        <!-- 指定spring1-servlet.xml为spring1这个servlet的配置文件 -->
        <param-value>/WEB-INF/spring1-servlet.xml</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>spring1</servlet-name>              
    <url-pattern>/spring1/</url-pattern>
</servlet-mapping>

<!--++++++++++++++++++++++++++++++++++++++++++++++++++++-->
<!-- spring2 servlet -->
<!--++++++++++++++++++++++++++++++++++++++++++++++++++++-->
<servlet>
    <servlet-name>spring2</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>          
    <init-param>   
        <param-name>contextConfigLocation</param-name>
        <!-- 指定spring2-servlet.xml为spring2这个servlet的配置文件 -->
        <param-value>/WEB-INF/spring2-servlet.xml</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>spring2</servlet-name> 
    <url-pattern>/spring2/</url-pattern>
</servlet-mapping>

从示例中可以看出,我们分别定义了两个spring servlet,第一个叫spring1,其配置文件为spring1-servlet.xml,其上下文也就是spring1-servlet.xml;第二个叫spring2,其上下文为spring2-servlet.xml。

2.依赖注入:

spring-servlet.xml中的bean可以引用父类applicationContext.xml上下文中的bean,例如在spring-servlet.xml中定义了一个bean,类名叫A,A类中有一个成员变量是B类的对象,而B类又是applicationContext.xml中的Bean,那么通过@resouce @autowired等注解或者在配置文件中声明都可以引用到B类的这个bean,但是反之则不行。比如B类中有一个A类的成员变量,通过@resource等方式来引用spring-servlet.xml中的A类的bean,在运行时会报错,提示要注入的bean不存在。其实很容易理解,前面说过,applicationContext.xml初始化在先,因此applicationContext.xml中的bean实例化在先,无法获得spring-servlet.xml的bean。不仅如此,也可能由于spring的servlet对应的上下文是子类,可能有多个,因此在spring1-servlet.xml和spring2-servlet.xml中可能有相同的bean类(比如类型相同、id、name都相同),如果作为父类的applicationContext.xml需要子类的bean,那么Spring框架应该从哪个子类中获得bean呢?有可能Spring的开发者出于这种考虑,设计了父类上下文中的bean不能引用子类上下文中的bean。

3.applicationContext.xml与dispatch-servlet.xml写成一个文件

 可以把这两个文件写成一个,比如spring-servlet.xml,然后在web.xml声明根应用上下文为spring-servlet.xml,如下:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-servlet.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

 
<servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>       
</servlet>
<servlet-mapping>
    <servlet-name>spring</servlet-name>              
    <url-pattern>/</url-pattern>
</servlet-mapping>

这样spring-servlet.xml同时也具有原来的applicationContext.xml的作用。

但是根据上文,我们知道根上下文是在应用启动时初始化,而servlet对应的上下文随servlet初始化,他们是两个上下文,因此即便是写成同一个文件,也只是使用spring-servlet.xml同时充当根上下文对象,省去了一个xml文件,但是spring-servlet.xml仍会初始化两遍:第一遍是作为根上下文随应用启动时初始化,第二遍是作为spirng servlet对应的上下文随名称为spring的servlet初始化。即如果在spring-servlet.xml声明了一个bean,这个bean会在应用启动时,spring-servlet.xml作为根上下文初始化时,创建一个;然后在servlet启动时,spring-servlet.xml又作为servlet的上下文初始化时,再创建一个。当然,简单的springMVC应用一般只有一个spring servlet,因此applicationContext.xml也可以不用,而把所有的bean都注册到spring servlet对应的上下文,即把web.xml中的

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-servlet.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

这段代码删除掉,只保留spring-servlet.xml文件。这种情况下,如果有些bean需要在应用启动时初始化,那么设置spring servlet为<load-on-startup>1</load-on-startup>即可。

 

特别注意: DispatcherServlet 一定回去加载一个 Spring XML 配置文件,如果没有配置 或 默认文件也不存在,则报错!

 

摘自:https://blog.csdn.net/mr_orange_klj/article/details/78633626