在两个WAR之间共享应用程序上下文?
有没有办法在两次部署的战争之间共享应用程序上下文? 一场战争需要接通另一场战争的服务,我不知道从哪里开始。
像tomcat这样的Web应用程序容器的一般用途是每个应用程序都能够独立运行(因此您可以在不影响其他应用程序的情况下停止和启动单个应用程序),这意味着可能需要花费大量精力才能将其开发到阻止你这样做。 因此,即使你发现了一个漏洞,我建议不要使用它,除非建议或至少由设计师批准。
我建议你开始寻找其他解决方案。 例如:
- 你真的需要共享对象实例吗? 如果它们是无状态的,您可能不需要,并且您只需在每个应用程序中运行上下文的副本。
- 您是否可以将您尝试共享的代码分成暴露rest服务的第三个WAR? 或者也许现有的WAR中的一个可以作为服务。
我们的团队也有同样的要求 – 在Tomcat中的多个WAR之间共享Spring bean,老实说,诸如“不要那样做”这样的答案没有帮助。
该要求源于我们在Tomcat上运行多WAR应用程序,并且所有WAR都需要访问相同的RDBMS以获取持久性信息。 我们使用Spring和Hibernate来访问RDBM,并且所有WAR共享相同的模式,理想情况下可以使用相同的Hibernate SessionFactory和Spring事务管理器。
关于如何做到这一点的答案发布在这里:
StackOverflow:在EAR中共享ApplicationContext
总而言之,您在web.xml中执行以下操作:
parentContextKey sharedContext locatorFactorySelector classpath:beanRefContext.xml contextConfigLocation classpath:yourWarSpecificAppContext.xml org.springframework.web.context.ContextLoaderListener
其中beanRefContext.xml包含:
classpath:yourSharedAppContext.xml
这使用Spring ContextSingletonBeanFactoryLocator来公开和共享父上下文(在本例中使用名称“sharedContext”)。 当第一个WAR引用它时,将延迟加载共享上下文。
无论您在共享上下文中引用的bean都必须可以访问所有WAR,这意味着它们无法从特定WAR中的WEB-INF / classes或WEB-INF / lib加载。 必须使用EAR文件共享它们,或者将包含bean(和依赖项)的jar放在Tomcat共享的“lib”文件夹($ CATALINA_HOME / lib)中,这是我们团队所做的。
公平警告,如果您使用此方法,您可能会将大多数JAR放在共享lib文件夹中而不是单独的Web应用程序中。 对于我们的项目,这是有道理的,因为大多数webapp共享和访问相同的后端服务。
由于硬核Tomcat开发人员可能会反对将大量代码放入Tomcat共享库目录中,因此我将列举其他建议答案可能不起作用的一些原因。
- 为每个WAR使用单独的应用程序上下文意味着拥有多个连接池到数据库,每个WAR一个连接池,并为每个WAR单独初始化昂贵的Hibernate SessionFactory,这会增加服务器启动时间和内存消耗。 更一般地说,它不允许在同一Tomcat中运行的Web应用程序之间共享共享后端服务的状态。
- 将持久性代码放入单独的WAR并使用REST调用(至少在我们的情况下)对开发人员来说是非常不方便的,并且与直接调用共享bean相比,增加了到达数据库的路径长度。
我认为你应该查看一篇信息丰富的博客文章: 在多战Spring应用程序中使用共享的父应用程序上下文
如果启动嵌入式jetty服务器并从启动和配置jetty服务器的类访问这两个Web应用程序,可能有一种方法。
看到:
嵌入docker
您是否需要共享运行时上下文,或者您是否只想在两个应用程序中重用bean定义?
如果它只是后者,那么您可以轻松地将常见的Spring上下文XML文件提取到一些共享依赖项中,并且只需在两个Web应用程序中重用JAR。 但是,如果您需要每个应用程序中的bean /服务相互通信,则需要使用其他选项。
如果上下文不存在,您可以将上下文绑定到JNDI。
这样做的代价是每个webapp的上下文都必须知道它可能不是主要的。
此外,你需要非常小心竞争条件,例如
- 第一个webapp启动,检测到没有上下文
- 首先,webapp开始构建上下文
- 第二个webapp启动,检测到没有上下文
- 第二个webapp开始构建上下文
- 首先,webapp完成构建上下文,绑定它
- 第二个webapp完成构建上下文,绑定它
- 恭喜,你已经从第一个webapp的上下文中丢失了所有bean
同意@RichardSmith,接受的答案对我没有帮助。 虽然理查德的回答有助于指出我正确的方向,但我正在使用Jetty,所以我不能使用EAR。 我最终使用服务器上下文在战争之间共享一个对象 – 甚至可以使用热(重新)部署的webapps:
https://stackoverflow.com/a/46968645/1287091
也许是一种适应Tomcat的方法。
- Spring限定符和属性占位符
- Android TestCase中的Dagger 2dependency injection
- 使用applicationcontext.getbean vs @configurable 的优点
- 我应该将我的ThreadLocals放入弹簧注入的单例中吗?
- 可以在JSR 330中使@Inject成为可选项(如@Autowire(required = false)吗?
- 选择在运行时弹出时要注入的实现
- Spring Context init(java)
- 为什么我在Spring配置类中不需要@Autowired @Bean方法?
- Spring IoC – dependency injection – > NullPointerException