一尘不染

Spring MVC:在耳边共享上下文

spring-mvc

我有一个Auricle,其中包含一个带普通对象的jar和两个我想使用普通jar的战争Web应用程序。我已将配置设置为通过ContextLoaderListener和Webapp上下文分别为DispatcherServlet使用应用程序范围的上下文。

我的演示应用程序的设置大致如下

  • common.jar包含 applicationContext.xmlbeanRefContext.xml ,它们应该是应用程序(耳朵)范围的上下文。文件如下。 共享 名称空间是共享bean所在的位置。

applicationContext

    <beans>
        <!-- namespace etc declarations omitted -->
        <context:annotation-config />
        <context:component-scan base-package="study.spring.multicontext.shared" />
    </beans>

beanRefContext.xml

    <beans>
        <!-- namespace etc declarations omitted -->
    <bean id="sharedContext" class="org.springframework.context.support.ClassPathXmlApplicationContext">
        <constructor-arg>
            <list>
                <value>classpath*:applicationContext.xml</value>
            </list>
        </constructor-arg>
    </bean>
</beans>
  • webapp1webapp2Spring MVC应用程序打包为单独的war,并带有如下所示的 web.xml 文件
        <web-app>

    <context-param>
      <param-name>parentContextKey</param-name>
      <param-value>sharedContext</param-value>
    </context-param>
    <context-param>
      <param-name>locatorFactorySelector</param-name>
      <param-value>classpath:beanRefContext.xml</param-value>
    </context-param>
    <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath*:applicationContext.xml</param-value>
    </context-param>

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

    <servlet>
        <servlet-name>dos</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/dos-servlet.xml</param-value>
        </init-param>

        <load-on-startup>1</load-on-startup>
    </servlet>


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

xx-servlet.xml, 例如针对Webapp的特定上下文。 Web 名称空间是控制器所在的位置。

    <beans>
        <!-- namespace etc declarations omitted -->

        <context:component-scan base-package="study.spring.multicontext.web"/>
        <mvc:annotation-driven />

        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

          <property name="suffix" value=".jsp"/>
        </bean>

    </beans>
  • 共享bean在Controller类中以常规方式@Autowired

    @Autowired
    

    MySharedBean mySharedBean

  • Auricle既包含战争也包含jar,结构类似于

        ear
     |
     |--common.jar
     |   |--META-INF
     |   |--applicationContext.xml
     |   |--beanRefContext.xml
     |
     |--webapp1.war
     |   |--WEB-INF
     |       |--xx-servlet.xml
     |       |--web.xml
     |
     |--webapp2.war
     |   |--WEB-INF
     |       |--xx-servlet.xml
     |       |--web.xml

问题是仍然有两个bean实例。每个控制器/
webapp一个,因为每次战争中只有一个Controller。我试图扭曲配置,但是无论我做什么,我要么得到零个实例,要么得到两个实例。

我从内存转储中使用Eclipse
MAT检查了引用,实际上有4个实例,但是我猜这两个实例供Spring内部使用。无论如何,从那里可以清楚地看到每个控制器都有自己的实例。

我读过许多博客文章,讨论论坛等,他们说这应该就这么简单。有人建议使用JNDI,但据我所知,没有它,应该可以实现。

而且不可能将战争结合在一起并将jar捆在里面。由于它可能适用于此演示应用程序,因此我正在使用的现实生活案例不允许这样做。

对此表示任何帮助,我们深表感谢。提前致谢。

来自 Spring
2.X的2007年版SpringSource示例,其功能相同但配置不同。有点过时了,正在寻找基于Spring 3.X的解决方案,如赏金描述中所述。


阅读 418

收藏
2020-06-01

共1个答案

一尘不染

我解决了。

正如我在对@Akshay的答案的评论中所怀疑的那样,问题出在类加载中。

Maven在每个war包中都包含spring
lib,因此它们被多次加载。为了解决这个问题,需要引起一场皮包骨头的战争

我假设Akshay关于他的回答(contextConfigLocation从web.xml中的context-params中删除)的注释也起着关键作用。

2020-06-01