微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么 JmsListeners 不能共享公共 Jms 连接?

如何解决为什么 JmsListeners 不能共享公共 Jms 连接?

我以这种方式创建了一个消息处理程序:

@JmsListeners(
  JmsListener(destination = "queue1"),JmsListener(destination = "queue2"),JmsListener(destination = "queue3"),JmsListener(destination = "queue4")
)
fun handleMessage(message: String) {
  // handle a message
}

当我检查我的消息代理时,我看到我的应用已经建立了 4 个连接。 不幸的是,我对来自 MQ 管理员的连接数量有限制,因此我希望消息处理程序仅使用 1 个连接。

在检查 Spring Jms 内部之后,我发现 DefaultMessageListenerContainer has an ability to use a shared connection。但问题是 Spring 的 DefaultMessageListenerContainerFactory 为每个 DefaultMessageListenerContainer 创建了一个单独的 @JmsListener

同时,JMS API 允许从单个 JMSConsumer 创建多个 JMSContext,例如

val jmsContext = connectionFactory.createContext(Session.SESSION_TRANSACTED)
val consumer1 = jmsContext.createConsumer(jmsContext.createQueue("queue1"))
val consumer2 = jmsContext.createConsumer(jmsContext.createQueue("queue2"))

如何设置 JmsListener 以共享公共连接?如果这是不可能的,Spring 是否有合理的理由?

解决方法

我想将此作为评论发布,但我也需要显示代码,因此作为妥协...

我想你已经这样做了。这就像剥洋葱一样。

看起来好像不能通过 application.properties - https://docs.spring.io/spring-boot/docs/2.4.1/reference/htmlsingle/#common-application-properties-integration

控制 sharedConnection

也不是,不能直接在代码中设置,但可能有办法影响它。使用以下一种或多种机制。

对于侦听器,您必须指定容器工厂。顺便提一句。我不喜欢硬编码的字符串,所以在 application.properties 中有一个 my.queue.name1 属性。

import org.springframework.jms.annotation.JmsListener;
    ...

    // Set upper concurrency limit on listener
    @JmsListener(destination = "${my.queue.name1}",containerFactory = "myListenerFactory",concurrency = "2")
    ...

回过头来,您将需要一个用于自定义工厂的 bean,您可以在其中控制如何创建连接。可以 @Override createContainerInstance 方法,但 DefaultMessageListenerContainer::sharedConnectionEnabled 方法是受保护的和最终的,因此无法调用或覆盖。所以需要用其他方式来限制可用连接数...

import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
...    

    @Bean("myListenerFactory")
    public DefaultJmsListenerContainerFactory myCustomisedListenerFactory() {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory() {
            @Override
            protected DefaultMessageListenerContainer createContainerInstance() {
                DefaultMessageListenerContainer dmlc = new DefaultMessageListenerContainer();

                // This may the way to control how many concurrent consumers are created
                dmlc.setMaxConcurrentConsumers(2);
                return dmlc;
            }
        };
        factory.setConnectionFactory(connectionFactory);

        // Set the concurrency lower limit to upper limit
        factory.setConcurrency("1-2");

        // Plus any other customisations
        ...

        return factory;
    }

以及您的自动有线连接工厂。

import import javax.jms.ConnectionFactory;
...

    @Autowired
    private ConnectionFactory connectionFactory;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?