JMSListener - 动态选择器

时间:2016-09-13 14:17:58

标签: java jms activemq spring-jms

我目前有一个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 :(得分:0)

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

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

答案 1 :(得分: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;
    }
}