背景:
我们有一个基于JMS(点对点)的独立应用程序。我们目前通过Java主程序在单独的JVM实例中启动JMS侦听器,并通过另一个Java主程序将请求从另一个JVM实例发布到此侦听器。
要求:
我们希望仅将JMS侦听器作为war / ear移植到Web /应用程序服务器上。我们希望在容器部署war / ear时启动JMS侦听器。
问题:
编写Servlet并将<load-on-startup>
配置为true是一个好主意。然后,我们可以在servlet的init方法中启动JMS侦听器。这样做的优点和缺点是什么?
在应用程序启动时启动JMS侦听器是否有比第1点更好的选项?
我们在应用程序中使用Spring和Spring JMS。我们可以简单地将弹簧上下文文件移动到META-INF,或者是否需要对弹簧上下文文件进行任何其他配置更改才能对Web应用程序可见。
请注意,对于我们无法控制的约束,我们需要将JMS侦听器移植到Web应用程序。我不想知道移植这个是不是一个好主意,而是想知道如何做到这一点。
答案 0 :(得分:2)
首先,参考检查the JMS chapter of the documentation
我不确定我是否真正了解Web应用程序的实际问题:就Spring而言,这只是一个应用程序,就像任何其他应用程序一样。如果你还没有这样做,你应该为你的JMS监听器注册一个监听器容器,如:
<!-- this is your message listener -->
<bean id="messageListener" class="jmsexample.ExampleListener" />
<!-- and this is the message listener container -->
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="destination"/>
<property name="messageListener" ref="messageListener" />
</bean>
现在您要确保此侦听器不会消耗消息,除非应用程序已启动。典型的Spring Web应用程序定义为核心部分的根ApplicationContext
和servlet相关部分的子ApplicationContext
。
默认情况下,容器作为已定义它的应用程序上下文的一部分启动。我假设你的监听器不依赖于web东西,所以你应该只在root中定义它。有一种方法可以指定容器的阶段,该容器将在启动应用程序时控制关于其他bean。
您也可以将autoStartup
设置为false
。在这种情况下,容器根本不会启动,您可以随时自由启动它。例如,您可以创建一个ApplicationListener
来监听ContextRefreshEvent
并注入您的监听器并在那时启动它。像
public class YourListener implements ApplicationListener<ContextRefreshedEvent> {
private DefaultMessageListenerContainer container;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
this.container.start();
}
public void setContainer(DefaultMessageListnerContainer container {
this.container = container;
}
}
请注意,如果您做依赖于Web部件可用,那么正确注册侦听器可能会非常棘手。查看此问题的this answer for a full description。