Spring MVC:共享内容

时间:2013-04-23 06:56:56

标签: java spring spring-mvc

我有一个耳包,其中包含一个带有常见对象的jar和两个war webapps,我想使用常见的jar。我已经将配置设置为通过ContextLoaderListener和webapp上下文分别为DispatcherServlet使用应用程序范围的上下文。

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

  • common.jar包含 applicationContext.xml beanRefContext.xml ,它们应该是应用程序(耳朵)广泛的上下文。文件如下所示。 shared 名称空间是共享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>
  • webapp1webapp2是将Spring MVC应用程序打包为单独的战争,其中包含 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>
    

对于特定于webapp的上下文,

xx-servlet.xml 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
    
  • 耳包含有战争和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一个,因为每个战争中只有一个控制器。我试图改变配置,但无论我做什么,我要么得到零个实例,要么得到两个实例。

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

我读过很多博客文章,论坛等,他们说这应该就这么简单。有人建议JNDI,但正如我所理解的那样,如果没有它,这应该是可能的。

并不可能将战争结合起来并将罐子捆绑在里面。因为它可能适用于这个演示应用程序,我正在使用的真实案例不允许这样做。

对此事的任何帮助都非常感谢。提前谢谢。

对于Spring 2.X,

SpringSource example from 2007执行相同但配置不同的操作。有点过时,正在寻找基于Spring 3.X的解决方案,正如赏金描述中所述。

4 个答案:

答案 0 :(得分:7)

就应用程序上下文层次结构而言,我认为从Spring 2.x到3.x没有任何变化。

据我所知,你的配置问题是你正在加载applicationContext.xml - 加载到sharedContext的那个,也被每个webapp加载,因为它在context-param contextConfigLocation中提到的事实。

由于同一文件被加载两次,一次在父上下文中,一次在Web应用程序的根上下文中,所以有副本和子上下文,即。 webapp,使用它创建的那些,而不是父级中存在的那些。

更改您的配置,这样您就不会重新加载相同的bean xml两次,它应该可以正常工作。您可以使用parentContextKeycontextConfigLocation,只是不加载相同的文件。

更新: 除了上述内容之外,您还需要检查共享jar是否对战争可见(在允许共享同一实例时可见)。我尝试从博客中运行该示例,当我将其部署为Java EE6应用程序时,它对我不起作用,这是因为战争中的耳罐可见性规则从Java EE5更改为EE6。当我在Glass Fish的兼容模式下运行样本时,一切都按预期工作。

因此,请检查您的EAR / WAR以查看正在运行的servlet规范,并确保您的服务器正在相应地部署应用程序。

如果必须升级到Java EE 6,请确保遵循最新的可见性规则http://docs.oracle.com/cd/E19226-01/820-7688/gjjdt/index.html。检查战争的MANIFEST文件,确保他们拥有Class-Path配置中明确提到的所有耳塞。

希望这有帮助。

答案 1 :(得分:3)

我解决了。

问题在于课堂加载,因为我在评论中怀疑@ Akshay的答案。

Maven在每个war包中都包含了spring libs,因此它们被多次加载。要解决此问题,需要generate skinny wars

我认为Akshay关于他在web.xml中从context-params中删除contextConfigLocation的答案的说明也是关键角色。

答案 2 :(得分:2)

我们遇到了类似的问题。检查我们为实验创建的这个简单的maven示例(具有2个WEB模块的EAR和通过父春季上下文服务模块共享): EAR with shared spring context between wars

答案 3 :(得分:1)

尽管这个问题很旧,但是如果有人想知道为什么documented approach在Spring Framework 5.0+中不能正常工作。截至发布此答案之时,Spring Framework 5.0+中当前已中断了对在耳朵内共享上下文的支持。 Spring Framework Issue-20805

上存在一个未解决的问题