Spring:web.xml 中的命名空间与 contextConfigLocation 初始化参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15818047/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:51:05  来源:igfitidea点击:

Spring: namespace vs contextConfigLocation init parameters in web.xml

springspring-mvcdependency-injection

提问by LuckyLuke

I am reading the documentation for Spring MVC and I have a question regarding the init params. I am using Spring 3.2 if it matter. What is the difference between the contextConfigLocation and namespace? Is the contextConfigLocation meant only for specifying the folders where the context class can find a XML definition and the namespace attribute is meant for specifying the file name?

我正在阅读 Spring MVC 的文档,我有一个关于 init 参数的问题。如果重要的话,我正在使用 Spring 3.2。contextConfigLocation 和命名空间有什么区别?contextConfigLocation 是否仅用于指定上下文类可以在其中找到 XML 定义的文件夹,而 namespace 属性用于指定文件名?

<servlet>
        <servlet-name>AppServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>WEB-INF</param-value>
        </init-param>
        <init-param>
            <param-name>namespace</param-name>
            <param-value>application-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

Is this correct? Should it use /WEB-INF/application-context.xml? And should you specify paths?

这样对吗?它应该使用 /WEB-INF/application-context.xml 吗?你应该指定路径吗?

回答by informatik01

TL;DR

TL; 博士

Just set the value(s) for the contextConfigLocationwhenever you need to specify custom config files. This way you will be specifying both the config file names and their locations.

contextConfigLocation只要您需要指定自定义配置文件,只需设置值即可。通过这种方式,您将同时指定配置文件名及其位置。

The namespaceis essentially an alternative wayof telling Spring container context loader class what config file to use. I never bother with it, but just use contextConfigLocationwhenever I need to configure custom config files.

namespace本质上是告诉 Spring 容器上下文加载器类使用什么配置文件的另一种方式。我从不打扰它,只是contextConfigLocation在需要配置自定义配置文件时使用。

Here is an example from one of my previous Spring projects (some of the configurations omitted for the sake of brevity):

这是我之前的 Spring 项目之一的示例(为简洁起见,省略了一些配置):

web.xml

网页.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                            http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    <display-name>Spring Web Application example</display-name>

    <!-- Configurations for the root application context (parent context) -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/jdbc/spring-jdbc.xml
            /WEB-INF/spring/security/spring-security-context.xml
        </param-value>
    </context-param>

    <!-- Configurations for the DispatcherServlet application context (child context) -->
    <servlet>
        <servlet-name>spring-mvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                /WEB-INF/spring/mvc/spring-mvc-servlet.xml
            </param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring-mvc</servlet-name>
        <url-pattern>/admin/*</url-pattern>
    </servlet-mapping>

</web-app>


Long answer

长答案

OK, first let's get some important moments clear. There are two types of contexts we are dealing with:

好的,首先让我们弄清楚一些重要的时刻。我们正在处理两种类型的上下文:

  1. root context(parent)
  2. individual servlet context(child)
  1. 根上下文(父)
  2. 单独的 servlet 上下文(子)

Quote from the Spring Framework API (version 3.2.2 at the moment of writing this) for the WebApplicationContext(emphasis mine):

引用 Spring Framework API(在撰写本文时为 3.2.2 版)的WebApplicationContext(重点是我的):

Like generic application contexts, web application contexts are hierarchical. There is a single root context per application, while each servlet in the application (including a dispatcher servlet in the MVC framework) has its own child context.

与通用应用程序上下文一样,Web 应用程序上下文也是分层的。每个应用程序有一个根上下文,而应用程序中的每个 servlet(包括 MVC 框架中的调度程序 servlet)都有自己的子上下文

Also here: Context hierarchies:

也在这里:上下文层次结构

For example, if you are developing a Spring MVC web application you will typically have a root WebApplicationContext loaded via Spring's ContextLoaderListenerand a child WebApplicationContext loaded via Spring's DispatcherServlet. This results in a parent-child context hierarchy where shared components and infrastructure configuration are declared in the root context and consumed in the child context by web-specific components.

例如,如果您正在开发 Spring MVC Web 应用程序,您通常会通过 Spring 的 ContextLoaderListener 加载一个根 WebApplicationContext通过 Spring 的 DispatcherServlet 加载一个子 WebApplicationContext。这导致了父子上下文层次结构,其中共享组件和基础结构配置在根上下文中声明,并由特定于 Web 的组件在子上下文中使用。

And here: 17.2 The DispatcherServlet:

在这里:17.2 DispatcherServlet

ApplicationContext instances in Spring can be scoped. In the Web MVC framework, each DispatcherServlet has its own WebApplicationContext, which inherits all the beans already defined in the root WebApplicationContext. These inherited beans can be overridden in the servlet-specific scope, and you can define new scope-specific beans local to a given Servlet instance.

Spring 中的 ApplicationContext 实例可以限定范围。在 Web MVC 框架中,每个 DispatcherServlet 都有自己的 WebApplicationContext,它继承了根 WebApplicationContext 中已经定义的所有 bean。这些继承的 bean 可以在特定于 servlet 的范围内被覆盖,并且您可以定义新的特定于给定 Servlet 实例的范围特定的 bean。


Now let's see the root application contextconfiguration. Here is an example:
web.xml


现在让我们看看根应用程序上下文配置。这是一个例子:
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                            http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/daoContext.xml
            /WEB-INF/spring/applicationContext.xml
        </param-value>
    </context-param>
</web-app>


From the official Spring documentation (emphasis mine):
5.14.4 Convenient ApplicationContext instantiation for web applications:


来自官方 Spring 文档(重点是我的):
5.14.4 适用于 Web 应用程序的便捷 ApplicationContext 实例化

You can create ApplicationContext instances declarativelyby using, for example, a ContextLoader. Of course you can also create ApplicationContext instances programmatically by using one of the ApplicationContext implementations.

You can register an ApplicationContext using the ContextLoaderListener(see the example above)

The listener inspects the contextConfigLocation parameter. If the parameter does not exist, the listener uses /WEB-INF/applicationContext.xml as a default. When the parameter does exist, the listener separates the String by using predefined delimiters (comma, semicolon and whitespace) and uses the values as locations where application contexts will be searched. Ant-style path patterns are supported as well. Examples are /WEB-INF/*Context.xml for all files with names ending with "Context.xml", residing in the "WEB-INF" directory, and /WEB-INF/**/*Context.xml, for all such files in any subdirectory of "WEB-INF".

例如,您可以使用 ContextLoader 以声明方式创建 ApplicationContext 实例。当然,您也可以使用 ApplicationContext 实现之一以编程方式创建 ApplicationContext 实例。

您可以使用 ContextLoaderListener 注册 ApplicationContext(参见上面的示例)

侦听器检查 contextConfigLocation 参数。如果该参数不存在,则侦听器使用 /WEB-INF/applicationContext.xml 作为默认值。当参数确实存在时,侦听器使用预定义的分隔符(逗号、分号和空格)分隔字符串,并将这些值用作将搜索应用程序上下文的位置。也支持 Ant 风格的路径模式。示例是 /WEB-INF/*Context.xml 用于名称以“Context.xml”结尾的所有文件,位于“WEB-INF”目录中,以及 /WEB-INF/**/*Context.xml,用于所有此类文件位于“WEB-INF”的任何子目录中。


Quite often Spring configuration is split across multiple files. It's more logical and convenient, especially in the large-scale projects. In our example we explicitly defined two configuration XML files: daoContext.xmland applicationContext.xmlin the custom location: /WEB-INF/spring/. Again, had we not defined contextConfigLocation, the ContextLoaderListenerwould try to locate the default config file: /WEB-INF/applicationContext.xml.


Spring 配置经常被拆分到多个文件中。更合乎逻辑和方便,尤其是在大型项目中。在我们的示例中,我们在自定义位置明确定义了两个配置 XML 文件:daoContext.xmlapplicationContext.xml/WEB-INF/spring/. 同样,如果我们没有定义contextConfigLocationContextLoaderListener将尝试定位默认配置文件:/WEB-INF/applicationContext.xml.

NOTE:
The root context is optional. Also see this answer: https://stackoverflow.com/a/7451389/814702

注:
根上下文是可选的。另请参阅此答案:https: //stackoverflow.com/a/7451389/814702

So if the default /WEB-INF/applicationContext.xmlconfig file does not suit your needs, use ContextLoaderListeneralong with <context-param>contextConfigLocationwhere you can define custom config file(s) to define root application context.

因此,如果默认/WEB-INF/applicationContext.xml配置文件不适合您的需求,请使用ContextLoaderListener<context-param>contextConfigLocation,您可以在其中定义自定义配置文件来定义根应用程序上下文


Next let's see the individual (child) application context. From the official Spring documentation (emphasis mine):
17.2 The DispatcherServlet


接下来让我们看看单个(子)应用程序上下文。来自官方 Spring 文档(重点是我的):
17.2 DispatcherServlet

Upon initialization of a DispatcherServlet, Spring MVC looks for a file named
[servlet-name]-servlet.xml in the WEB-INF directory
of your web application and creates the beans defined there, overriding the definitions of any beans defined with the same name in the global scope.

Consider the following DispatcherServlet Servlet configuration (in the web.xml file):

在初始化 DispatcherServlet 时,Spring MVC
会在您的 Web 应用程序的 WEB-INF 目录查找名为[servlet-name]-servlet.xml 的文件,并创建在那里定义的 bean,覆盖使用相同名称定义的任何 bean 的定义在全球范围内。

考虑以下 DispatcherServlet Servlet 配置(在 web.xml 文件中):

<web-app>

    <servlet>
        <servlet-name>golfing</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>golfing</servlet-name>
        <url-pattern>/golfing/*</url-pattern>
    </servlet-mapping>

</web-app>



About contextConfigLocation and namespace

关于 contextConfigLocation 和命名空间

From the documentation (emphasis mine):

从文档(强调我的):

With the above Servlet configuration in place, you will need to have a file called
/WEB-INF/golfing-servlet.xmlin your application; this file will contain all of your Spring Web MVC-specific components (beans). You can change the exact location of this configuration file through a Servlet initialization parameter (see below for details).
...
You can customize individual DispatcherServlet instancesby adding Servlet initialization parameters (init-param elements) to the Servlet declaration in the web.xml file. See the following table for the list of supported parameters.

  • contextClass: Class that implements WebApplicationContext, which instantiates the context used by this Servlet. By default, the XmlWebApplicationContext is used.

  • contextConfigLocation: String that is passed to the context instance (specified by contextClass) to indicate where context(s) can be found. The string consists potentially of multiple strings (using a comma as a delimiter) to support multiple contexts. In case of multiple context locations with beans that are defined twice, the latest location takes precedence.

  • namespace: Namespace of the WebApplicationContext. Defaults to [servlet-name]-servlet.

有了上面的 Servlet 配置,您将需要
/WEB-INF/golfing-servlet.xml在应用程序中调用一个文件;该文件将包含所有 Spring Web MVC 特定的组件(bean)。您可以通过 Servlet 初始化参数更改此配置文件的确切位置(有关详细信息,请参见下文)。
...
您可以通过将 Servlet 初始化参数(init-param 元素)添加到 web.xml 文件中的 Servlet 声明来自定义各个 DispatcherServlet 实例。有关支持的参数列表,请参阅下表。

  • contextClass:实现 WebApplicationContext 的类,它实例化此 Servlet 使用的上下文。默认情况下,使用 XmlWebApplicationContext。

  • contextConfigLocation:传递给上下文实例(由 contextClass 指定)以指示可以找到上下文的位置的字符串。该字符串可能包含多个字符串(使用逗号作为分隔符)以支持多个上下文。如果 bean 的多个上下文位置被定义两次,则最新位置优先。

  • namespace:WebApplicationContext 的命名空间。默认为 [servlet-name]-servlet。


Now let's research the API documentation for the related classes. The class DispatcherServletextends abstract class FrameworkServlet. From the FrameworkServletAPI docs (emphasis mine):


现在让我们研究相关类的 API 文档。DispatcherServlet类扩展了抽象类FrameworkServlet。来自FrameworkServletAPI 文档(重点是我的):

Passes a "contextConfigLocation" servlet init-param to the context instance, parsing it into potentially multiple file paths which can be separated by any number of commas and spaces, like
"test-servlet.xml, myServlet.xml". If not explicitly specified, the context implementation is supposed to build a default location from the namespace of the servlet.

The default namespace is "'servlet-name'-servlet", e.g. "test-servlet" for a servlet-name "test" (leading to a "/WEB-INF/test-servlet.xml" default location with XmlWebApplicationContext). The namespace can also be set explicitly via the "namespace" servlet init-param.

将“contextConfigLocation”servlet init-param 传递给上下文实例,将其解析为多个文件路径,这些路径可以用任意数量的逗号和空格分隔,例如
“test-servlet.xml, myServlet.xml”。如果没有明确指定,上下文实现应该从 servlet 的命名空间构建一个默认位置

默认命名空间是“'servlet-name'-servlet”,例如“test-servlet”代表servlet-name“test”(通过XmlWebApplicationContext 导致“/WEB-INF/test-servlet.xml”默认位置)。命名空间也可以通过“命名空间”servlet init-param 显式设置

This is the excerpt from the FrameworkServletsource code:
FrameworkServlet.java

这是FrameworkServlet源代码的摘录:
FrameworkServlet.java

....
/**
* Suffix for WebApplicationContext namespaces. If a servlet of this class is
* given the name "test" in a context, the namespace used by the servlet will
* resolve to "test-servlet".
*/
public static final String DEFAULT_NAMESPACE_SUFFIX = "-servlet";
....


The default context class for FrameworkServletis XmlWebApplicationContext. From the XmlWebApplicationContextAPI docs (emphasis mine):


FrameworkServlet的默认上下文类是XmlWebApplicationContext。来自XmlWebApplicationContextAPI 文档(重点是我的):

By default, the configuration will be taken from "/WEB-INF/applicationContext.xml" for the root context, and "/WEB-INF/test-servlet.xml" for a context with the namespace "test-servlet" (like for a DispatcherServlet instance with the servlet-name "test").

The config location defaults can be overridden via the "contextConfigLocation" context-param of ContextLoader and servlet init-param of FrameworkServlet. Config locations can either denote concrete files like "/WEB-INF/context.xml" or Ant-style patterns like "/WEB-INF/*-context.xml" (see PathMatcher javadoc for pattern details).

默认情况下,配置将从“/WEB-INF/applicationContext.xml”获取根上下文,从“/WEB-INF/test-servlet.xml”获取命名空间为“test-servlet”的上下文(如对于具有 servlet 名称“test”的 DispatcherServlet 实例)。

可以通过 ContextLoader 的“contextConfigLocation”上下文参数和 FrameworkServlet 的 servlet init-param 覆盖配置位置默认值。配置位置可以表示诸如“/WEB-INF/context.xml”之类的具体文件或诸如“/WEB-INF/*-context.xml”之类的 Ant 样式模式(有关模式详细信息,请参阅 PathMatcher javadoc)。

Overriding default config locations using contextConfigLocationis the same as in the above example for the root application context.

使用覆盖默认配置位置contextConfigLocation与上述根应用程序上下文示例中的相同。

As for the overriding the default namespacethere are some important moments. When you set a new namespace, don't prepend it with /WEB-INFand don't append .xmlto it. The reason for that can be discovered if we look in the source file for the XmlWebApplicationContextclass:
XmlWebApplicationContext.java

至于覆盖默认命名空间,有一些重要的时刻。当你设置一个新的命名空间时,不要在它前面加上/WEB-INF也不要附加.xml到它。如果我们查看XmlWebApplicationContext类的源文件,就可以发现原因:
XmlWebApplicationContext.java

...

/** Default config location for the root context */
public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";

/** Default prefix for building a config location for a namespace */
public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";

/** Default suffix for building a config location for a namespace */
public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";

...

/**
* The default location for the root context is "/WEB-INF/applicationContext.xml",
* and "/WEB-INF/test-servlet.xml" for a context with the namespace "test-servlet"
* (like for a DispatcherServlet instance with the servlet-name "test").
*/
@Override
protected String[] getDefaultConfigLocations() {
    if (getNamespace() != null) {
        return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX};
    }
    else {
        return new String[] {DEFAULT_CONFIG_LOCATION};
    }
}

As you can see, the source code says it all.

如您所见,源代码说明了一切。



Example of specifying custom namespace

指定自定义命名空间的示例

web.xml

网页.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                            http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">


    <!-- Configurations for the DispatcherServlet application context (child context) -->
    <servlet>
        <servlet-name>spring-mvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>namespace</param-name>
            <param-value>spring/mvc/spring-mvc</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring-mvc</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>

The result is that, instead of using the default namespace for constructing the path to the config file, that would otherwise be /WEB-INF/spring-mvc-servlet.xml, the container will look for /WEB-INF/spring/mvc/spring-mvc.xml.

结果是,/WEB-INF/spring-mvc-servlet.xml容器将查找/WEB-INF/spring/mvc/spring-mvc.xml.

NOTE:
The above explanations related to the setting custom namespace are for the default XmlWebApplicationContextcontext class. One can specify an alternative class, like AnnotationConfigWebApplicationContext, so there will be some special moments for that.

注意:
上述与设置自定义命名空间相关的说明适用于默认的XmlWebApplicationContext上下文类。可以指定一个替代类,例如AnnotationConfigWebApplicationContext,因此会有一些特殊的时刻。



CONCLUSION

结论

It is (IMHO) much more easier to use contextConfigLocationparameter to define custom config files, both for the root application context and for the individual contexts. The only difference is that for the root application context you use <context-param>within <web-app>element, but NOT within a specific servlet (also don't forget the listener class). And for the child context you use <init-param>nested inside the <servlet>element for each specific servlet. See my example configurations (web.xml) in the very beginning of this post.

contextConfigLocation对于根应用程序上下文和单个上下文,使用参数来定义自定义配置文件(恕我直言)要容易得多。唯一的区别是,对于您<context-param><web-app>元素中使用的根应用程序上下文,而不是在特定的 servlet 中(也不要忘记侦听器类)。对于子上下文,您使用<init-param>嵌套在每个特定 servlet<servlet>元素内。请参阅本文开头的示例配置 ( web.xml)。

Additional resources (as if the above was not enough :-)):

其他资源(好像以上还不够:-)):

回答by Sava Jcript

I think LuckyLuke's answer has a lot of useful info, but it doesn't answer the question. In particular, how "namespace" and "contextConfigLocation" parameters work together?

我认为 LuckyLuke 的回答有很多有用的信息,但它没有回答问题。特别是,“namespace”和“contextConfigLocation”参数如何协同工作?

The only place I could find the concrete answer is the source code:

我能找到具体答案的唯一地方是源代码:

  • namespaceparemeter sets a custom namespace to be used for building a defaultcontext config location
  • contextConfigLocationparameter sets the context config location explicitly, instead of relying on the default location built from the namespace
  • 命名空间参数设置用于构建默认上下文配置位置的自定义命名空间
  • contextConfigLocation参数显式设置上下文配置位置,而不是依赖于从命名空间构建的默认位置

回答by Hunter Zhao

What is the difference between the contextConfigLocation and namespace?contextConfigLocation is used to specify the path of spring config files, that means they'll be initialized. namespace is used to specify the path and name of the DispatcherServlet of Spring MVC. default is [Dispatcher_name]-servlet.xml, here is an example:

contextConfigLocation 和命名空间有什么区别?contextConfigLocation 用于指定 spring 配置文件的路径,这意味着它们将被初始化。namespace 用于指定 Spring MVC 的 DispatcherServlet 的路径和名称。默认为[Dispatcher_name]-servlet.xml,这是一个示例:

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>namespace</param-name>
        <param-value>config/spring-mvc</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

Spring will search a file to be used as it's mvc config by the path of /WEB-INF/config/spring-mvc.xml.
Is the contextConfigLocation meant only for specifying the folders where the context class can find a XML definition

Spring 将通过/WEB-INF/config/spring-mvc.xml.
contextConfigLocation 是否仅用于指定上下文类可以在其中找到 XML 定义的文件夹

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/config/app-*.xml</param-value>
</context-param>

The code above showed that when application starting Spring will load all the the files which name starts with 'app-' and ends with '.xml' in the WEB-INF/config directory.

上面的代码表明,当应用程序启动 Spring 时,将加载 WEB-INF/config 目录中所有名称以“app-”开头并以“.xml”结尾的文件。

Should it use /WEB-INF/application-context.xml? And should you specify paths?
Through the example all above we can know that when configurating Spring we need to specify the full path and generic file name and when SpringMVC only we should specify the path(if it's located in a directory, not include the WEB-INF directory) and name(not include the extension).
Hope to help you:)

它应该使用 /WEB-INF/application-context.xml 吗?你应该指定路径吗?
通过上面的例子我们可以知道,配置Spring时需要指定完整路径和通用文件名,只有SpringMVC时我们应该指定路径(如果它位于目录中,不包括WEB-INF目录)和名称(不包括扩展名)。
希望能帮到你:)