Spring 4.1 @JmsListener 配置

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25899940/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 00:04:06  来源:igfitidea点击:

Spring 4.1 @JmsListener configuration

springspring-annotationsspring-jms

提问by TemarV

I would like to use the new annotations and features provided in Spring 4.1 for an application that needs a JMS listener.

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

I've carefully read the notes in the Spring 4.1 JMS improvements postbut I continue to miss the relationship between @JmsListenerand maybe the DestinationResolverand how I would setup the application to indicate the proper Destinationor Endpoint.

我已经仔细阅读笔记在春季4.1 JMS的改进后,但我仍然想念之间的关系@JmsListener,也许是DestinationResolver和我怎么会安装该应用程序,以指示正确DestinationEndpoint

Here is the suggested use of @JmsListener

这是@JmsListener 的建议使用

@Component
public class MyService {

    @JmsListener(containerFactory = "myContainerFactory", destination = "myQueue")
    public void processOrder(String data) { ... }
}

Now, I can't use this in my actual code because the "myQueue" needs to be read from a configuration file using Environment.getProperty().

现在,我不能在我的实际代码中使用它,因为“myQueue”需要使用Environment.getProperty().

I can setup an appropriate myContainerFactory with a DestinationResolverbut mostly, it seems you would just use DynamicDestinationResolverif you don't need JNDI to lookup a queue in an app server and didn't need to do some custom reply logic. I'm simply trying to understand how Spring wants me to indicate the name of the queue in a parameterized fashion using the @JmsListenerannotation.

我可以使用 a 设置一个合适的 myContainerFactory,DestinationResolver但大多数情况下,DynamicDestinationResolver如果您不需要 JNDI 在应用服务器中查找队列并且不需要执行一些自定义回复逻辑,那么您似乎只会使用。我只是想了解 Spring 如何希望我使用@JmsListener注释以参数化方式指示队列的名称。

Further down the blog post, I find a reference to this 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);
}

Now, this makes some amount of sense and I could see where this would allow me to set a Destination at runtime from some external string, but this seems to be in conflict with using @JmsListeneras it appears to be overriding the annotation in favor of endpoint.setMessageListenerin the code above.

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

Any tips on how to specify the appropriate queue name using @JmsListener?

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

采纳答案by Stephane Nicoll

You could eventually do that right now but it's a bit convoluted. You can set a custom JmsListenerEndpointRegistryusing JmsListenerConfigurer

你现在最终可以做到这一点,但这有点令人费解。您可以JmsListenerEndpointRegistry使用设置自定义JmsListenerConfigurer

@Configuration
@EnableJms
public class AppConfig implements JmsListenerConfigurer {

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

}

and then override the registerListenerContainer method, something like

然后覆盖 registerListenerContainer 方法,例如

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

But we could do better. Please watch/vote for SPR-12280

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

回答by GameSalutes

Also note that depending on use case you can already parameterize using properties file per environment and PropertySourcesPlaceholderConfigurer

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

@JmsListener(destinations = "${some.key}")

As per https://jira.spring.io/browse/SPR-12289

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

回答by shahshi15

In case people are using @JmsListenerwith spring boot, you do not have to configure PropertySourcesPlaceholderConfigurer. It work's out the box

如果人们使用@JmsListenerspring boot,则不必配置PropertySourcesPlaceholderConfigurer. 它开箱即用

Sample:

样本:

class

班级

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

application.properties

应用程序属性

spring.activemq.queue.name=some.weird.queue.name.that.does.not.exist

Spring boot output

春季开机输出

[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 

This proves that @JmsListener is able to pickup property values from application.properties without actually setting up any explicit PropertySourcesPlaceholderConfigurer

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

I hope this helps!

我希望这有帮助!