【问题标题】:Sending spring integration jms message to specific queue (dynamically)将spring集成jms消息发送到特定队列(动态)
【发布时间】:2015-03-26 09:58:26
【问题描述】:

一个简单的消息发布者如下所示:

@Service("myPublisher")
public class MyPublisher{

   @Publisher(channel = "myChannel")
   public Message<?> sendMessage (Message<?> message) {
      return message;
   }
}

...并且是这样配置的:

<int:channel id="myChannel"/>   
<int-jms:outbound-channel-adapter channel="myChannel" destination="defaultDestination" session-transacted="true"/>
<bean class="org.springframework.integration.aop.PublisherAnnotationBeanPostProcessor"/>

问题是,这个发布者将消息发送到准备好的defaultDestination,但我需要将消息发送到不同的队列。就我而言,我的应用程序中的每个任务都需要一个消息队列。原因是,如果我想中止任务,我必须从代​​理中删除消息。如果一项任务有数千条消息,则使用选择器接收所有消息不是一个好习惯。我需要在不接收客户端的情况下从消息代理中删除所有已中止任务的消息。 JMS 只支持消息的发送和接收。我必须使用代理 API (QPID) 来删除消息。问题是,QPID 不支持通过选择器移除消息,但它支持移除队列。

我想,我需要一个 PublisherFactory,它的功能如下:

public class PublisherFactory {
    public MyPublisher getPublisher(String destinationName){...};
}

factory.getPublisher("testQueue");

这个方法应该返回一个向testQueue发送消息的发布者。

或者具有这样功能的服务:

public class PublisherService {
    public Message<?> sendMessage(Message<?> message, String desinationName){...};
}

service.sendMessage(new Message("test"), "testQueue");

简而言之,我想要的只是将Message 发送到特定目的地的服务。目标名称应设置为方法调用的参数或工厂的类变量。

我希望有人能解决我的问题。谢谢:)

【问题讨论】:

    标签: spring jms spring-integration messaging spring-jms


    【解决方案1】:

    &lt;int-jms:outbound-channel-adapter&gt; 不仅可以配置为静态destination,还可以通过一些动态行为在运行时针对请求消息使用 SpEL 来确定@​​987654323@。

    destination-expression="headers.destination"
    

    另一方面,@Publisher 的 AOP 允许构建消息以发布,不仅默认情况下将 payload 作为 return 值,而且具有更智能的逻辑。例如:

    @Publisher(channel="annotationConfigRegistrationTest")
    @Payload("#return + #args.lname")
    public String setName(String fname, String lname, @Header("x") int num) {
        return fname + " " + lname;
    }
    

    在这种情况下,要发布的消息将具有类似 payload 的返回值,以及 lname 参数。 @Header("x") 将在该消息中填充 x 标头,并以 num 作为值。

    由于您的sendMessage 方法返回整个Message&lt;?&gt;,您只需要在那里构建一个新消息并添加上面提到的destination 标头,基于当前状态的内容。

    HTH

    【讨论】:

    • 我刚刚为类变量添加了一个带有自己的标头和有效负载注释的消息 bean。因此,发布者和处理程序端的所有标头信息具有相同的消息类型:) 感谢您的回答。 :) 使用 SpEL 的问题是,我有未定义数量的并行运行的发布者。这意味着,每个发布者都需要自己的频道和频道适配器。当然,我可以使用一个阻塞单例服务,它为使用 SpEL 提供 desintinationName,但我从 spring 集成中获取发布者的同步。我认为这不是解决我的问题的最佳方法。 :(
    • ???如果您按照我的建议为每条消息填充标题,则sync 块中将不需要,因为 SpEL 是针对每条消息独立评估的。
    • 哦....对不起。我想我误解了你。 :D 现在,我明白你的意思了......我会尝试并在一些测试后再次发表评论:)
    • 哇,它的工作原理:) 这很简单。非常感谢。