RabbitMQ注解方式配置说明

RabbitMQ注解方式配置说明

1.共通配置

  • spring-rabbit使用1.6版本,需要spring 4.2以上才可以支持使用注解方式配置
  • 每个项目配置自己的exchange,格式为项目名称简写+exchange,如: 
    rabbitmq.direct.exchange=ccs.direct.exchange 
    可以防止队列重名
  • routeKey和queue的名称也要加上项目名称简写防止重名
  • 例子中传输数据使用了String,实际使用时可以放入任意对象和返回。
  • 附件中spring-rabbit.xml为异步回调方式的完整生产者配置
  • 生产者配置时,exchange共有三种方式发送消息,含义请参考http://www.360doc.com/content/14/0608/22/834950_384932402.shtml
<dependency>
    <groupId>org.springframework.amqp</groupId>
    <artifactId>spring-rabbit</artifactId>
</dependency>
   
   
  • 1
  • 2
  • 3
  • 4
<rabbit:connection-factory id="connectionFactory"
    addresses="${rabbitmq.addresses}" username="${rabbitmq.username}"
    password="${rabbitmq.password}" channel-cache-size="${rabbitmq.channel.cache.size}" />

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

<!-- json转换器,消息可以自动根据转换器转换格式,不配置时默认为java序列化,可以自行配置 -->
<bean id="messageConverter" class="org.springframework.amqp.support.converter.Jackson2JsonMessageConverter" />
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
#地址,两个rabbitmq服务器之间为镜像队列
rabbitmq.addresses=192.168.5.130:5672,192.168.5.132:5672
rabbitmq.username=test
rabbitmq.password=test
rabbitmq.concurrentConsumers=5
rabbitmq.channel.cache.size=50
#exchange名称
rabbitmq.direct.exchange=ccs.direct.exchange
rabbitmq.fanout.exchange=ccs.fanout.exchange
rabbitmq.topic.exchange=ccs.topic.exchange
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2.direct模式配置

2.1.队列配置

队列配置需要在生产者消费者两边同时配置。 
如果只在生产者方配置,rabbitmq服务器中无队列时,会导致消费者服务器启动时找不到监听队列报错

<!-- 将queue和routingKey进行绑定 -->
<rabbit:queue name="ccs.queue.sync" />
<rabbit:queue name="ccs.queue.async" />
<!-- 定义回复queue -->
<rabbit:queue name="ccs.queue.async.reply" />
<!-- direct方式:根据routingKey将消息发送到所有绑定的queue中 -->
<rabbit:direct-exchange name="${rabbitmq.direct.exchange}">
    <rabbit:bindings>
        <rabbit:binding queue="ccs.queue.sync" key="ccs.binding.sync" />
        <rabbit:binding queue="ccs.queue.async" key="ccs.binding.async" />
        <rabbit:binding queue="ccs.queue.async.reply" key="ccs.binding.async.reply" />
    </rabbit:bindings>
</rabbit:direct-exchange>
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

注:队列分为同步和异步模式,异步模式支持异步回复功能。ccs.queue.sync队列为同步,ccs.queue.async和ccs.queue.async.reply组合为异步。

2.2.生产者配置
<bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate">
    <property name="backOffPolicy">
        <bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
            <property name="initialInterval" value="500" />
            <property name="multiplier" value="10.0" />
            <property name="maxInterval" value="10000" />
        </bean>
    </property>
</bean>

<rabbit:template id="template" message-converter="messageConverter"
    connection-factory="connectionFactory" reply-timeout="2000" retry-template="retryTemplate" 
    exchange="${rabbitmq.direct.exchange}"  />

<!-- exchange为direct模式 -->
<rabbit:template id="template" message-converter="messageConverter"
    connection-factory="connectionFactory" reply-timeout="2000" retry-template="retryTemplate" 
    exchange="${rabbitmq.direct.exchange}"  />
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

retryTemplate为连接失败时的重发队列所用的templete

2.3.消费者配置
<rabbit:annotation-driven />

<bean id="rabbitListenerContainerFactory"
    class="org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory">
    <property name="messageConverter" ref="messageConverter" />
    <property name="connectionFactory" ref="connectionFactory" />
    <property name="concurrentConsumers" value="3" />
    <property name="maxConcurrentConsumers" value="10" />
</bean>
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
2.4.消费者配置

因为测试用的系统使用了quartz来定时发送队列,代码仅提供rabbitmq相关的功能。使用者根据需要自行修改。

    @Override
    protected void execute(final ScheduleJob scheduleJob, final String id) {
        RabbitTemplate template = (RabbitTemplate) SpringContextHolder.getBean("template");
        template.convertAndSend(template.getExchange(), "ccs.binding.async", id, new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                message.getMessageProperties().setHeader("jobName", scheduleJob.getName());
                return message;
            }
        });
    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • ccs.binding.async为队列的bind名称,一个binding可以绑定多个队列,实现广播功能;
  • 同步和异步发送部分代码相同
  • MessagePostProcessor可以为队列配置一些参数,本例中配置了jobName
  • SpringContextHolder为持有spring上下文的静态对象,参考如下方式配置: 
    SpringContextHolder配置
2.5.消费者代码示例
@Component
public class AsyncQueueListener {

    /**
     * 同步队列
     * @param id 任务ID
     * @param type 任务名称
     */
    @RabbitListener(queues = "ccs.queue.sync")
    public void hello(String id, @Header("jobName") String jobName) {
        System.out.println("Received request for id " + id);
        System.out.println("Received request for job name " + jobName);
    }

    /**
     * 异步队列,SendTo为回复的队列名称
     * @param id 任务ID
     * @param type 任务名称
     * @return
     */
    @RabbitListener(queues = "ccs.queue.async")
    @SendTo("ccs.queue.async.reply")
    public BaseResponse hello(String id, @Header("jobName") String jobName) {
        System.out.println("Received request for id " + id);
        System.out.println("Received request for job name " + jobName);
        //返回执行结果(成功,失败)和ID
        BaseResponse response = new BaseResponse(true, id);
        return response;
    }
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

以下代码需要放在生产者服务器,监听异步消息返回的队列

@Component
public class AsyncReplyQueueLitener {
    private Logger logger = LoggerFactory.getLogger(AsyncReplyQueueLitener.class);

    @Autowired
    private CcsQtrtzLogService ccsQtrtzLogService;

    //参数中使用@Header获取mesage
    @RabbitListener(queues = { "ccs.queue.async.reply", "ccs.queue.bds.reply", "ccs.queue.etl.reply", "ccs.queue.mal.reply" })
    public void asyncReply(BaseResponse response) {
        logger.debug(response.getMsg());
        ccsQtrtzLogService.updateExecResultById(response.getMsg(), response.isSuccess());
    }
}

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

3.fanout模式配置

3.1.队列配置
<!-- fanout方式:发送到所有绑定的queue中,但每个queue只发一次 -->
<rabbit:queue name="ccs.queue.fanout1" />
<rabbit:queue name="ccs.queue.fanout2" />
<rabbit:fanout-exchange name="${rabbitmq.fanout.exchange}">
    <rabbit:bindings>
        <rabbit:binding queue="ccs.queue.fanout1" />
        <rabbit:binding queue="ccs.queue.fanout2" />
    </rabbit:bindings>
</rabbit:fanout-exchange>
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
3.2.生产者配置
<rabbit:template id="fanoutTemplate" message-converter="messageConverter"
    connection-factory="connectionFactory" reply-timeout="2000" retry-template="retryTemplate" 
    exchange="${rabbitmq.fanout.exchange}"  />
   
   
  • 1
  • 2
  • 3
3.3.消费者配置

同2.3

3.4.生产者示例代码
public class MqFanout extends BaseTask {

    @Override
    protected void execute(final ScheduleJob scheduleJob, final String id) {
        RabbitTemplate template = (RabbitTemplate) SpringContextHolder.getBean("fanoutTemplate");
        template.convertAndSend((Object) id, new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                message.getMessageProperties().setHeader("jobName", scheduleJob.getName());
                return message;
            }
        });
    }

}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
3.5.消费者示例代码
@Component
public class FanoutQueueListener {

    private static final Logger logger = LoggerFactory.getLogger(FanoutQueueListener.class);

    /**
     * 
     * @param id 任务ID
     * @param type 任务名称
     * @return
     */
    @RabbitListener(queues = "ccs.queue.fanout1")
    public void helloFanout1(String id, @Header("jobName") String jobName) {
        logger.debug("Received request for queue {}", "ccs.queue.fanout1");
        logger.debug("Received request for id {}", id);
        logger.debug("Received request for job name {}", jobName);
    }

    /**
     * 
     * @param id 任务ID
     * @param type 任务名称
     * @return
     */
    @RabbitListener(queues = "ccs.queue.fanout2")
    public void helloFanout2(String id, @Header("jobName") String jobName) {
        logger.debug("Received request for queue {}", "ccs.queue.fanout2");
        logger.debug("Received request for id {}", id);
        logger.debug("Received request for job name {}", jobName);
        //返回执行结果(成功,失败)和ID
    }
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

4.topic模式配置

4.1.队列配置
<rabbit:queue name="ccs.queue.topic1" />
<rabbit:queue name="ccs.queue.topic2" />
<rabbit:queue name="ccs.queue.other.topic1" />
<rabbit:queue name="ccs.queue.other.topic2" />
<rabbit:topic-exchange name="${rabbitmq.topic.exchange}">
    <rabbit:bindings>
        <rabbit:binding queue="ccs.queue.topic1" pattern="ccs.binding.*"/>
        <rabbit:binding queue="ccs.queue.topic2" pattern="ccs.binding.*"/>
        <rabbit:binding queue="ccs.queue.other.topic1" pattern="ccs.binding.other.*"/>
        <rabbit:binding queue="ccs.queue.other.topic2" pattern="ccs.binding.other.*"/>
    </rabbit:bindings>
</rabbit:topic-exchange>
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
4.2.生产者配置
<rabbit:template id="topicTemplate" message-converter="messageConverter"
    connection-factory="connectionFactory" reply-timeout="2000" retry-template="retryTemplate" 
    exchange="${rabbitmq.topic.exchange}"  />
   
   
  • 1
  • 2
  • 3
4.3.消费者配置

同2.3

4.4.生产者代码示例
public class MqTopic extends BaseTask {

    @Override
    protected void execute(final ScheduleJob scheduleJob, final String id) {
        RabbitTemplate template = (RabbitTemplate) SpringContextHolder.getBean("topicTemplate");
        template.convertAndSend(template.getExchange(), "ccs.binding.test", id, new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                message.getMessageProperties().setHeader("jobName", scheduleJob.getName());
                return message;
            }
        });
    }

}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

ccs.binding.test这个消息会发到ccs.binding.*绑定的两个队列中

4.5.消费者代码示例

@Component
public class TopicQueueListener {

    private static final Logger logger = LoggerFactory.getLogger(TopicQueueListener.class);

    /**
     * 
     * @param id 任务ID
     * @param type 任务名称
     * @return
     */
    @RabbitListener(queues = "ccs.queue.topic1")
    public void helloTopic1(String id, @Header("jobName") String jobName) {
        logger.debug("Received request for queue {}", "ccs.queue.topic1");
        logger.debug("Received request for id {}", id);
        logger.debug("Received request for job name {}", jobName);
    }

    /**
     * 
     * @param id 任务ID
     * @param type 任务名称
     * @return
     */
    @RabbitListener(queues = "ccs.queue.topic2")
    public void helloTopic2(String id, @Header("jobName") String jobName) {
        logger.debug("Received request for queue {}", "ccs.queue.topic2");
        logger.debug("Received request for id {}", id);
        logger.debug("Received request for job name {}", jobName);
    }

    /**
     * 
     * @param id 任务ID
     * @param type 任务名称
     * @return
     */
    @RabbitListener(queues = "ccs.queue.other.topic1")
    public void helloOtherTopic1(String id, @Header("jobName") String jobName) {
        logger.debug("Received request for queue {}", "ccs.queue.other.topic1");
        logger.debug("Received request for id {}", id);
        logger.debug("Received request for job name {}", jobName);
    }

    /**
     * 
     * @param id 任务ID
     * @param type 任务名称
     * @return
     */
    @RabbitListener(queues = "ccs.queue.other.topic2")
    public void helloOtherTopic2(String id, @Header("jobName") String jobName) {
        logger.debug("Received request for queue {}", "ccs.queue.other.topic2");
        logger.debug("Received request for id {}", id);
        logger.debug("Received request for job name {}", jobName);
    }
}

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Boot中使用RabbitMQ实现消息的确认可以通过以下步骤进行操作: 1. 首先,需要配置RabbitMQ的连接信息和Exchange、Queue等相关信息。可以参考中提供的示例代码进行配置。 2. 创建消费者并使用@RabbitListener注解指定监听的队列。在消费者中,可以使用Channel的basicAck方法手动进行消息确认,如示例代码中的ComfirmConsumer类中的fanoutConsumer1方法所示。在消息消费成功后,调用basicAck方法确认消息的处理完成。 3. 在消息确认函数中,会用到deliveryTag、multiple和requeue等参数。其中,deliveryTag是消息的唯一标识ID,用于确认特定的消息;multiple参数表示是否批处理,当设置为true时,可以一次性确认小于等于传入值的所有消息;requeue参数表示被拒绝的消息是否重新入队列。 4. 通过调用basicAck方法进行消息确认,告知RabbitMQ消息已经被处理完成。 总结起来,使用Spring Boot和RabbitMQ实现消息确认的步骤包括配置RabbitMQ连接信息、创建消费者并使用@RabbitListener注解指定监听的队列,然后在消费者中使用Channel的basicAck方法手动进行消息确认。参考和提供的代码和参数说明,可以更加具体地了解如何使用Spring Boot和RabbitMQ实现消息确认的过程。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Springboot 集成 RabbitMq 实现消息确认机制](https://blog.csdn.net/wxw1997a/article/details/126170811)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值