Spring 4.1 @JmsListener配置

Tem*_*arV 12 spring spring-annotations spring-jms

我想将Spring 4.1中提供的新注释和功能用于需要JMS侦听器的应用程序.

我仔细阅读了Spring 4.1 JMS改进帖子中的注释,但我仍然错过了我和设置应用程序之间的关系@JmsListener,DestinationResolver以及如何指示正确的DestinationEndpoint.

以下是@JmsListener的建议用法

@Component
public class MyService {

    @JmsListener(containerFactory = "myContainerFactory", destination = "myQueue")
    public void processOrder(String data) { ... }
}
Run Code Online (Sandbox Code Playgroud)

现在,我不能在我的实际代码中使用它,因为需要使用配置文件读取"myQueue" Environment.getProperty().

我可以设置一个合适的myContainerFactory DestinationResolver但主要是,DynamicDestinationResolver如果你不需要JNDI来查找app服务器中的队列而不需要做一些自定义的回复逻辑,你似乎只会使用它.我只是想了解Spring如何使用@JmsListener注释以参数化方式指示队列的名称.

在博客文章的下方,我找到了对此Configurer的引用:

@Configuration
@EnableJms
public class AppConfig implements JmsListenerConfigurer {

@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
    registrar.setDefaultContainerFactory(defaultContainerFactory());

    SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
    endpoint.setDestination("anotherQueue");
    endpoint.setMessageListener(message -> {
        // processing
    });
    registrar.registerEndpoint(endpoint);
}
Run Code Online (Sandbox Code Playgroud)

现在,这使得感一定量的,我可以看到,这将让我设定在一些外部串运行一个目标,但是这似乎是在冲突中使用@JmsListener,因为它似乎是压倒一切赞成注释endpoint.setMessageListener中上面的代码.

有关如何使用指定适当队列名称的任何提示@JmsListener

Gam*_*tes 15

另请注意,根据用例,您可以使用每个环境的属性文件和PropertySourcesPlaceholderConfigurer进行参数化

@JmsListener(destinations = "${some.key}")
Run Code Online (Sandbox Code Playgroud)

根据https://jira.spring.io/browse/SPR-12289


sha*_*i15 5

如果人们使用@JmsListenerSpring Boot,则不必进行配置PropertySourcesPlaceholderConfigurer。开箱即用

样品:

@JmsListener(destination = "${spring.activemq.queue.name}")
    public void receiveEntityMessage(final TextMessage message) {
    // process stuff 
}
}
Run Code Online (Sandbox Code Playgroud)

application.properties

spring.activemq.queue.name=some.weird.queue.name.that.does.not.exist
Run Code Online (Sandbox Code Playgroud)

弹簧启动输出

[26-Aug;15:07:53.475]-[INFO ]-[,]-[DefaultMes]-[o.s.j.l.DefaultMessageListenerContainer ]-[931 ]-Successfully refreshed JMS Connection 
[26-Aug;15:07:58.589]-[WARN ]-[,]-[DefaultMes]-[o.s.j.l.DefaultMessageListenerContainer ]-[880 ]-Setup of JMS message listener invoker failed for destination 'some.weird.queue.name.that.does.not.exist' - trying to recover. Cause: User user is not authorized to read from some.weird.queue.name.that.does.not.exist 
[26-Aug;15:07:59.787]-[INFO ]-[,]-[DefaultMes]-[o.s.j.l.DefaultMessageListenerContainer ]-[931 ]-Successfully refreshed JMS Connection 
[26-Aug;15:08:04.881]-[WARN ]-[,]-[DefaultMes]-[o.s.j.l.DefaultMessageListenerContainer ]-[880 ]-Setup of JMS message listener invoker failed for destination 'some.weird.queue.name.that.does.not.exist' - trying to recover. Cause: User user is not authorized to read from some.weird.queue.name.that.does.not.exist 
Run Code Online (Sandbox Code Playgroud)

这证明@JmsListener能够从application.properties中获取属性值,而无需实际设置任何显式的 PropertySourcesPlaceholderConfigurer

我希望这有帮助!


Ste*_*oll 2

您最终可以现在就这样做,但有点复杂。JmsListenerEndpointRegistry您可以使用设置自定义JmsListenerConfigurer

@Configuration
@EnableJms
public class AppConfig implements JmsListenerConfigurer {

    @Override
    public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
        registrar.setEndpointRegistry(customRegistry());
    }

}
Run Code Online (Sandbox Code Playgroud)

然后重写 registerListenerContainer 方法,例如

public void registerListenerContainer(JmsListenerEndpoint endpoint, JmsListenerContainerFactory<?> factory) {
    // resolve destination according to whatever -> resolvedDestination
    ((AbstractJmsListenerEndpoint)endpoint).setDestination(resolvedDestination);
    super.registerListenerContainer(endpoint, factory);
}
Run Code Online (Sandbox Code Playgroud)

但我们可以做得更好。请观看/投票SPR-12280