首页 文章

JMSListener - 动态选择器

提问于
浏览
1

我目前有一个JMSListener,如下所示 . 它使用属性文件中值的选择器 . 这很好用 .

@JmsListener(destination = "myQueueDest",
     selector = MyHeaders.SELECTOR_KEY + " = '${myapp.selector_val}'")
 private void consumeData(MyCustomObj mycustomObj) { }

我现在需要在内存中使用带有值的动态选择器,而不是spring属性 . 有没有办法使用JMSListener(或其他一些监听器mechnaism)从ActiveMQ队列中进行选择?

更新:

可以为我的 @JMSListener 分配一个ID,然后从我的 JmsListenerEndpointRegistry bean中检索它 . 按ID获取侦听器容器,将其强制转换为 DefaultMessageListenerContainer ,然后调用 setMessageSelector() ,尽管我不确定这是否可行 .

这需要将我的DefaultJmsListenerContainerFactory bean设置为具有 CACHE_SESSION 的缓存级别 .

但这似乎不起作用,因为监听器接收所有消息,无论我设置消息选择器是什么 .

2 回答

  • 0

    JMS规范说在创建使用者时必须提供选择字符串 . 所以答案是否定的 . 必须使用不同的选择字符串关闭和重新创建使用者,以接收符合不同选择条件的消息 .

    如果您的项目不是必须使用JMS API,那么您可以使用Active MQ的本机API进行探索 . 我确信每次调用receive时API都会有一种指定不同选择字符串的方法 . IBM MQ的本机API提供了这样的功能 .

  • 0

    如其中一条评论所述:

    setMessageSelector的javadoc表示可以在运行时设置它 . http://docs.spring.io/spring-framework/docs/2.5.x/api/org/springframework/jms/listener/AbstractMessageListenerContainer.html#setMessageSelector(java.lang.String)

    这个例子解释了如何在启动时进行设置,但是可以通过一些技巧来动态地进行设置:

    @EnableJms
    @Configuration
    public class JmsConfiguration {
    
        @Value("${my.int.param:100}")
        private int config;
    
        @Bean
        public MessageConverter messageConverter() {
            final MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
            converter.setTargetType(MessageType.TEXT);
            converter.setTypeIdPropertyName("_type");
            return converter;
        }
    
        @Bean
        public JmsListenerContainerFactory<?> specialQueueListenerFactory() {
            final String selector = "foo > " + config;
            final DefaultJmsListenerContainerFactory factory = new CustomJmsListenerContainerFactory(selector);
            factory.setMessageConverter(messageConverter());
            return factory;
        }
    }
    

    和CustomJmsListenerContainerFactory

    public class CustomJmsListenerContainerFactory extends DefaultJmsListenerContainerFactory {
    
        private final String selector;
    
        public CustomJmsListenerContainerFactory(String jmsSelector) {
            this.selector = jmsSelector;
        }
    
        @Override
        public DefaultMessageListenerContainer createListenerContainer(JmsListenerEndpoint endpoint) {
            final DefaultMessageListenerContainer instance = super.createListenerContainer(endpoint);
            instance.setMessageSelector(selector);
            return instance;
        }
    }
    

相关问题