【问题标题】:WEB-INF/myproject-servlet.xml versus WEB-INF/web.xmlWEB-INF/myproject-servlet.xml 与 WEB-INF/web.xml
【发布时间】:2014-05-13 09:15:19
【问题描述】:

我花了几天时间修复我的 Spring 项目中的错误。很长一段时间以来,我在错误日志中的主要问题是:

Bean already exists

我有两个文件:

WEB-INF/myproject-servlet.xml
WEB-INF/web.xml

在第一个中,我可以输入以下内容(假设我有一个管理动物园动物的应用程序):

<context:component-scan base-package="com.my.package.animals" />

这样(据我所知)我们正在启用 Spring bean 自动发现。所以现在,当我们运行我们的应用程序时,Spring 将从这个包中获取所有类,稍后它将遍历 resources 目录中的所有配置文件并初始化所有 bean(放置在与给定包关联的配置文件中) .

第二个,web.xml 包含这样的行

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/myproject-servlet.xml</param-value>
</context-param>

我还可以放置我的配置文件的路径,例如:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:animals-config.xml</param-value>
</context-param>

所以现在,我在 myproject-servlet.xml 中有“自动检测”,我在 web.xml 中有 context-param 用于相同的对象。

我的问题是,错误 "Bean already exists" 是否可能来自此?我几乎可以肯定,是的,我检查了所有 bean id 并且没有重复。

所以我还有一个问题。这样做的好方法是什么?当我创建新的配置文件时,我应该在哪里通知我的应用程序?在myproject-servlet.xml 或web.xml。我真的需要清理我的应用程序,我将从它开始。

我检查了一些示例,人们宁愿不要在web.xml 文件Simple example 中放置多个&lt;context-param&gt;

提前谢谢你


好的,我真的很接近解决我的问题了。

假设我有两个包:

com.my.pckg.a
com.my.pckg.b

类

com.my.pckg.a.ClassA
com.my.pckg.b.ClassB

我在myproject-servlet.xml 中添加了以下行:

<context:component-scan base-package="com.my.pckg.a" />

我有一个配置文件 myconfig.xml,里面有基于类 ClassA 和 ClassB 的 bean。

假设我们有如下 id 的 bean:

ClassA: ida1, ida2
ClassB: idb1, idb2

所以,我正在运行我的码头服务器,问题是:

哪些 bean 将被初始化?我只声明了包 com.my.pckg.a,所以从 myconfig.xml 开始,spring 应该只加载 ida1 和 ida2 但这个文件还包括另一个类的 bean .

那么最后...?


最后,我想我发现了一个问题。在web.xml 文件中我有一行:

<context:component-scan base-package="com.dirty.pckg" />

在这个包中,我有一个带有@Controller 注释的类DirtyClass。该类的字段之一是:

private static ApplicationContext context = new ClassPathXmlApplicationContext("dirty-config.xml");

所以,当我的应用程序启动时,Spring 使用DirtyClass(因为它有@)并映射它。因为 os static 上下文修饰符触发读取 dirty-config.xml。这就是我无法理解为什么我的代码会以奇怪的方式表现的方式。

【问题讨论】:

  • 你的 animals-config.xml 中有什么?如果您的 bean 定义与 myproject-servlet.xml 中的相同,并将两者都声明为 contextConfigLocation,则可能是一个问题。
  • 其实我改了很多东西,现在,这个案例不存在,也没有错误。最后,我想重点谈谈我的第二个问题。 myproject-servlet.xml 和web.xml 中应该是什么(考虑到“春天的味道”)?

标签: java xml spring


【解决方案1】:

web.xml 文件是您的 Web 应用程序的配置。它与 Spring 无关。

contextConfigLocation context-param 是一个用于搜索 Spring 配置文件的 Spring 侦听器。它与弹簧有关。

您可以在web.xml 中注册多个spring 配置文件,但这些文件不能定义相同的bean(bean id 必须不同)。您也可以只有一个 spring 配置文件,它会自动包含其他配置文件,如下所述:http://www.mkyong.com/spring/load-multiple-spring-bean-configuration-file/


回答另一个问题:

当您添加组件扫描时,您要求 spring 扫描包 com.my.pckg.a 以查找 @Service、@Component 等注释。组件扫描不是其余配置的过滤器,它是配置本身.因此,您添加组件扫描的事实不会改变 myconfig.xml 的行为。 ida1, ida2 和 idb1, idb2 都会被实例化。

我真的不明白你想用你的配置文件来完成什么。也许如果您说明您的需求,我们可以帮助您设置正确的配置。

【讨论】:

  • 好的,谢谢。现在,对我来说很清楚。当然为你点赞。我编辑了我的帖子,我问了另一个问题。我想它最终会解决我的问题。
  • 添加编辑以回答您的新问题
  • (当然)你是对的。我在帖子中解释了发生的事情。非常感谢。
【解决方案2】:

web.xml 是配置文件。它具有应用程序的类(如侦听器、过滤器、过滤器映射、servlet、servlet-mapping)、资源和配置(如上下文参数、显示名称、错误页面、会话配置)以及 Web 服务器如何使用它们来处理网络请求。当 Web 服务器收到对应用程序的请求时,它使用 web.xml 将请求的 URL 映射到应该处理请求的代码。

来看看 web.xml 应该是什么以及 myproject-servlet.xml 应该是什么:
1)在Spring中,ApplicationContext可以是分层的。一个 ApplicationContext 可以有多个子 ApplicationContext,并且只能有一个父级。子 ApplicationContext 中的 bean 可以访问父级中的 bean。

2)DispatcherServlet 将请求分派给处理程序(控制器),具有可配置的处理程序映射、视图解析配置(您用于应用程序的视图模板,例如 jsp)。

牢记这两点,我们的 web.xml 应该是这样的:

    <!--Root web application context(Parent context) - beans for service or persistence layer should be in this -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:service-layer-beans.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <!--DispatcherServlet loads its configuration into its own context(chile context) and refers Root web application context as a parent, so it have access to beans in parent context and can override it but not vice versa.-->
        <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/myproject-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>

【讨论】:

    猜你喜欢
    • 2011-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-18
    • 2023-03-23
    • 2016-02-22
    • 2012-06-05
    相关资源
    最近更新 更多