【问题标题】:JMS Standalone consumer with ActiveMQ and Spring使用 ActiveMQ 和 Spring 的 JMS 独立使用者
【发布时间】:2012-06-12 17:06:31
【问题描述】:

从历史上看,我将我的 JMS 消费者应用程序部署为部署在 Tomcat(Windows 框)下的 Spring webapps。然后,这些消费者将在同一个 Tomcat 实例下与我的其他 Web 应用程序一起运行。然而,随着我使用的消费者数量的增加,我意识到这正在变成一场维护噩梦。

我的解决方案是将这些 web 应用程序转换为部署为 jar 的“主要方法”独立应用程序。事实上,我能够成功地将它们全部打包在一起,以尝试尽可能多地重用资源(DAO、依赖项等)。

这是我的主要方法的样子:

public static void main(String[] args) {

    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

    try {
        FooListener fooListener = (FooListener) context.getBean("fooListener");

        fooListener.start();
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    }

    try {
        BarListener barListener = (BarListener) context.getBean("barListener");

        barListener.start();
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    }
}

我的问题:

  1. 我是否需要执行任何特殊操作来关闭我的 main 方法应用程序中的 JMS 连接,或者它们是否会在应用程序终止时正常关闭?
  2. 对于是否使用 tomcat 或作为独立应用程序部署 jms 消费者是否有任何个人偏好或其他方面?

编辑:

更多信息:FooListener 和 BarListener 扩展了以下抽象类。它们从 applicationContext.xml 文件中的相应 bean 继承它们的值,并且它们都覆盖 onMessage() 方法以异步消费消息。

public abstract class TextMessageListener implements MessageListener {

    protected ConnectionFactory connectionFactory;

    protected String queueName;

    protected String selectors;

    public void start() throws JMSException {
        Connection connection = connectionFactory.createConnection();

        Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);

        MessageConsumer consumer = session.createConsumer(session.createQueue(queueName), selectors);

        consumer.setMessageListener(this);

        connection.start();
    }

    public abstract void onMessage(Message message);
}

【问题讨论】:

    标签: java spring tomcat activemq


    【解决方案1】:

    您必须以这种方式为您的应用程序上下文注册一个关闭挂钩:

    context.registerShutdownHook();
    

    这将确保当 jvm 关闭时,上下文也被优雅地关闭。

    我个人的偏好总是将它部署到容器中——即使是像这样的独立应用程序,这是因为以下原因:

    • 管理更简单 - 部署/取消部署应用程序战争,启动/停止容器运行时。
    • 如果您需要构建任何类型的监控 - 消耗了多少消息,使用此设置会更容易,您可以添加显示相关信息的网页,而不是使用带有独立应用程序的 jmx。

    另外,为什么要显式调用 listener.start(),Spring 容器还是会自动执行此操作?

    【讨论】:

    • 这是一个非常好的问题——我不知道弹簧容器会自动调用监听器的 start() 方法。在搜索这方面的文档时,我偶然发现了 JmsTemplate 上的一个博客,这可能会让我的生活更轻松......bsnyderblog.blogspot.com/2010/02/…
    • 仅供参考 - 我能够通过将 init-method="start" 添加到我的 spring bean 中来删除手动 listener.start() 调用:
    • 哦,好吧,我明白你关于 start 方法的观点。实际上,即使这也不是必需的,因为您可以将侦听器注册为您注入 connectionFactory 的 MessageListenerContainer 的委托:这是一个很好的参考 - static.springsource.org/spring/docs/3.1.x/…
    • 我能够实现一个MessageListenerContainer,结果我创建的“TextMessageListener”类消失了,主要方法变成了一行代码:ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml ");这是我在 spring 配置中添加的内容:
    猜你喜欢
    • 2015-01-28
    • 1970-01-01
    • 2018-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-17
    • 2011-01-16
    • 2015-01-28
    相关资源
    最近更新 更多