Spring rabbitmq发送到动态绑定交换

时间:2016-02-11 10:37:49

标签: java spring rabbitmq spring-rabbit rabbitmq-exchange

我尝试使用TopicExchange来屏蔽消息。

配置:

    <rabbit:connection-factory id="connectionFactory"  host="localhost" username="guest" password="guest"/>

<rabbit:template id="rabbitTemplate" connection-factory="connectionFactory"/>

<rabbit:queue name="sample.queue"/>

<rabbit:admin id="rabbitAdmin" connection-factory="connectionFactory" />

<bean id="rabbitListenerContainerFactory"
      class="org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory">
    <property name="connectionFactory" ref="connectionFactory"/>
</bean>

<rabbit:annotation-driven container-factory="rabbitListenerContainerFactory"/>

<rabbit:listener-container connection-factory="connectionFactory" />

组件:

@Component
public class JmsComponent {

    private final Logger log = LoggerFactory.getLogger(JmsComponent.class);

    private final TopicExchange exchange = new TopicExchange("sample.exchange");

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private Queue queue;

    private String received;

    public void send(String msg) {
        rabbitTemplate.convertAndSend("sample.queue", new SimpleMessage(msg));
    }

    public void bindToKey(String keyMask) {
        BindingBuilder.bind(queue).to(exchange).with(keyMask);
        rabbitTemplate.setExchange(exchange.getName());
    }


    public void sendByKey(String key, String msg) {
        rabbitTemplate.convertAndSend(exchange.getName(), key, new SimpleMessage(msg));
    }

    @RabbitListener(queues = "sample.queue")
    public void handle(SimpleMessage message) {
        log.info("================ Received  " + message.getMsg());
        received = message.getMsg();
    }

    public String getReceived() {
        return received;
    }

当我使用send(包括TopicExchange之前) - 一切正常。消息直接发送到队列,handle()已收到它。 但对于TopicExchange ....我尝试使用它:

@Test
public void bind() throws InterruptedException {
    jmsComponent.bindToKey("qq");
    jmsComponent.sendByKey("qq", "message");
    Thread.sleep(5000);
    Assert.isTrue("message".equals(jmsComponent.getReceived()));
}

测试总是失败但是在日志中我看到了这个 - DEBUG o.s.amqp.rabbit.core.RabbitTemplate - 在交换上发布消息[sample.exchange],routingKey = [qq] 怎么了??? 感谢

2 个答案:

答案 0 :(得分:4)

此...

MediaMetadata mediaMetadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE);
                mediaMetadata.addImage(new WebImage(Uri.parse(MyAppConfigBase.IMAGE_API_ENDPOINT + movieVideoItem.getImages().getKeyart())));
                mediaMetadata.addImage(new WebImage(Uri.parse(MyAppConfigBase.IMAGE_API_ENDPOINT + movieVideoItem.getImages().getKeyart())));
                mediaMetadata.putString(MediaMetadata.KEY_TITLE, movieVideoItem.getTitle());
                mediaMetadata.putString(MediaMetadata.KEY_SUBTITLE, movieVideoItem.getDescription());
                mediaMetadata.putString("movie-urls", url);
                mediaMetadata.putString("content-type", movieVideoItem.getContent().getHighRes().getType());

                MediaTrack englishSubtitle = new MediaTrack.Builder(1 /* ID */, MediaTrack.TYPE_TEXT)
                        .setName("English Subtitle")
                        .setSubtype(MediaTrack.SUBTYPE_CAPTIONS)
                        .setContentId(closedCaptionsUrl)
                        /* language is required for subtitle type but optional otherwise */
                        .setLanguage("en-US")
                        .build();

                List tracks = new ArrayList();
                tracks.add(englishSubtitle);

                MediaInfo mediaInfo = new MediaInfo.Builder(url)
                        .setStreamDuration(movieVideoItem.getDuration())
                        .setStreamType(MediaInfo.STREAM_TYPE_NONE)
                        .setContentType(type)
                        .setMetadata(mediaMetadata)
                        .setMediaTracks(tracks)
                        .setCustomData(customData)
                        .build();

...除了创建一个BindingBuilder.bind(queue).to(exchange).with(keyMask); 对象然后扔掉它之外什么都不做。您需要获取该Binding个对象并在管理员上调用Binding。您还需要申报交换。

由于您的上下文中有管理员;最简单的方法是将declareBinding添加到上下文(以及绑定)。请参阅the documentation

<rabbit:exchange/>

顺便说一下,主题交换用于按键模式进行路由;如果您只想使用固定密钥路由/绑定,例如<rabbit:queue id="myQueue" name="sample.queue"/> <topic-exchange name="sample.exchange"> <bindings> <binding queue="myQueue" pattern="bucket.#"/> </bindings> </topic-exchange> ,则使用直接交换。请参阅RabbitMQ Tutorials

答案 1 :(得分:2)

我改变了我对Gary Russell的组件使用答案:

  • 我已添加

    @Autowired
    private RabbitAdmin rabbitAdmin;
    
    @PostConstruct
    public void init(){
        rabbitAdmin.declareExchange(exchange);
    }
    
  • 并修改绑定方法:

    public void bindToKey(String keyMask) {
        Binding binding = BindingBuilder.bind(queue).to(exchange).with(keyMask);
        rabbitAdmin.declareBinding(binding); // re-declare binding if mask changed
        rabbitTemplate.setExchange(exchange.getName());
    }
    
  • 然后测试就开始了!

更多,我在运行时添加了更改绑定掩码:

@Test
public void bind() throws InterruptedException {
    jmsComponent.bindToKey("qq");
    jmsComponent.sendByKey("qq", "message");
    Thread.sleep(5000);
    Assert.isTrue("message".equals(jmsComponent.getReceived()));

    jmsComponent.bindToKey("eeeee");
    jmsComponent.sendByKey("eeeee", "message one");
    Thread.sleep(5000);
    Assert.isTrue("message one".equals(jmsComponent.getReceived()));
}

一切正常。