Spring MVC:共享内容

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

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

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

的applicationContext

      

beanRefContext.xml

      classpath*:applicationContext.xml     
  • webapp1webapp2是Spring MVC应用程序打包为单独的战争, web.xml文件如下所示

       parentContextKey sharedContext   locatorFactorySelector classpath:beanRefContext.xml   contextConfigLocation classpath*:applicationContext.xml   org.springframework.web.context.ContextLoaderListener   dos org.springframework.web.servlet.DispatcherServlet  contextConfigLocation /WEB-INF/dos-servlet.xml  1   dos /  

xx-servlet.xml类似,适用于webapp特定的上下文。 web命名空间是控制器所在的位置。

         
  • 在Controller类中,共享bean以正常方式@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,但正如我所理解的,如果没有它,这应该是可能的。

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

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

Spring.Source示例来自2007年的Spring 2.X,它使用不同的配置。 有点过时,正在寻找基于Spring 3.X的解决方案,正如赏金说明中所述。

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

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

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

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

更新:除了上述内容之外,您还需要检查共享jar是否对战争可见(在允许共享相同实例时可见)。 我尝试从博客中运行该示例,当我将其部署为Java EE6应用程序时,它对我不起作用,这是因为战争中的ear jar可见性规则从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配置中明确提到的所有耳罩。

希望这可以帮助。

我解决了。

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

Maven在每个war包中都包含了spring libs,因此它们被多次加载。 要解决这个问题,需要产生一场瘦弱的战争 。

我假设Akshay关于他从web.xml中的context-params中删除contextConfigLocation答案的注释也是关键角色。

我们遇到了类似的问题。 检查我们为实验创建的这个简单的maven示例(带有2个WEB模块的EAR和共享的父春季上下文服务模块): 战争之间的共享弹簧上下文的EAR