当前位置:   article > 正文

Springboot整合RabbitMQ_springboot rabbitmq消费配置类

springboot rabbitmq消费配置类

目录

1、创建Springboot项目、导入依赖

2、配置文件中添加rabbitmq的连接信息

3、编写rabbitmq的配置类

4、编写投递消息接口

5、编写邮件消费者

6、编写短信消费者

7、测试

8、使用两个邮件消费者监听邮件队列

9、实现能者多劳和手动消息确认


1、创建Springboot项目、导入依赖

  1. <dependencies>
  2. <!-- springboot-web组件 -->
  3. <dependency>
  4. <groupId>org.springframework.boot</groupId>
  5. <artifactId>spring-boot-starter-web</artifactId>
  6. </dependency>
  7. <!-- 添加springboot对amqp的支持 -->
  8. <dependency>
  9. <groupId>org.springframework.boot</groupId>
  10. <artifactId>spring-boot-starter-amqp</artifactId>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.apache.commons</groupId>
  14. <artifactId>commons-lang3</artifactId>
  15. </dependency>
  16. <!--fastjson -->
  17. <dependency>
  18. <groupId>com.alibaba</groupId>
  19. <artifactId>fastjson</artifactId>
  20. <version>1.2.49</version>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.projectlombok</groupId>
  24. <artifactId>lombok</artifactId>
  25. </dependency>
  26. </dependencies>

2、配置文件中添加rabbitmq的连接信息

  1. spring:
  2. rabbitmq:
  3. #连接地址
  4. host: 127.0.0.1
  5. #端口号
  6. port: 5672
  7. #账号
  8. username: guest
  9. #密码
  10. password: guest
  11. #虚拟主机
  12. virtual-host: /rkVirtualHost
  13. server:
  14. port: 8080

3、编写rabbitmq的配置类

  1. package com.rk.config;
  2. import org.springframework.amqp.core.Binding;
  3. import org.springframework.amqp.core.BindingBuilder;
  4. import org.springframework.amqp.core.FanoutExchange;
  5. import org.springframework.amqp.core.Queue;
  6. import org.springframework.context.annotation.Bean;
  7. import org.springframework.context.annotation.Configuration;
  8. /**
  9. * @author :Rk.
  10. * @date : 2022/10/8
  11. * 定义完成后 rabbitmq服务器会自动创建交换机和队列 以及绑定关系
  12. */
  13. @Configuration
  14. public class RabbitMQConfig {
  15. /**
  16. * 定义交换机名称
  17. */
  18. private String EXCHANGE_NAME="springboot_falout_exchange";
  19. /**
  20. * 短信队列
  21. */
  22. private String FANOUT_SMS_QUEUE = "fanout_sms_queuerk";
  23. /**
  24. * 邮件队列
  25. */
  26. private String FANOUT_EMAIL_QUEUE = "fanout_email_queuerk";
  27. /**
  28. * 定义 扇形交换机
  29. */
  30. @Bean
  31. public FanoutExchange fanoutExchange(){
  32. //参数 交换机名称
  33. return new FanoutExchange(EXCHANGE_NAME);
  34. }
  35. /**
  36. *参数一:队列名称
  37. *参数二durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
  38. *参数三exclusive:默认也是false,是否独占队列
  39. *参数四autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
  40. */
  41. @Bean
  42. public Queue smsQueue(){
  43. return new Queue(FANOUT_SMS_QUEUE,true, false,false);
  44. }
  45. /**
  46. *参数一:队列名称
  47. *参数二:durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
  48. *参数三:exclusive:默认也是false,是否独占队列
  49. *参数四:autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
  50. */
  51. @Bean
  52. public Queue emailQueue(){
  53. return new Queue(FANOUT_EMAIL_QUEUE,true,false,false);
  54. }
  55. /**
  56. * 短信队列绑定交换机
  57. * @param smsQueue 短信队列注入到容器的id,也就是方法名 sumQueue
  58. * @param fanoutExchange 交换机注入到容器的id,也就是方法名 fanoutExchange
  59. * @return
  60. */
  61. @Bean
  62. public Binding bindingSmsFanoutExchange(Queue smsQueue,FanoutExchange fanoutExchange){
  63. return BindingBuilder.bind(smsQueue).to(fanoutExchange);
  64. }
  65. /**
  66. * 邮件队列队列绑定交换机
  67. * @param emailQueue 短信队列注入到容器的id,也就是方法名 emailQueue
  68. * @param fanoutExchange 交换机注入到容器的id,也就是方法名 fanoutExchange
  69. * @return
  70. */
  71. @Bean
  72. public Binding bindingEmailFanoutExchange(Queue emailQueue,FanoutExchange fanoutExchange){
  73. return BindingBuilder.bind(emailQueue).to(fanoutExchange);
  74. }
  75. }

        这里使用的是扇形交换机,交换机会把消息路由到绑定到它的所有队列。

        在Spring启动时,利用Spring Bean管理工厂BeanFactory接口,实现动态创建交换机队列交换机和队列的绑定关系,让我们无需进行重复的编码工作。

4、编写投递消息接口

  1. package com.rk.controller;
  2. import com.rk.domain.User;
  3. import org.springframework.amqp.core.AmqpTemplate;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.GetMapping;
  6. import org.springframework.web.bind.annotation.RestController;
  7. /**
  8. * @author :Rk.
  9. * @date : 2022/10/8
  10. */
  11. @RestController
  12. public class FanoutProducerController {
  13. @Autowired
  14. private AmqpTemplate amqpTemplate;
  15. /**
  16. * 模拟注册接口
  17. * @param
  18. * @return
  19. */
  20. @GetMapping("/registered")
  21. public String sendMsg(){
  22. User user=new User("rk",22,"男","陕西西安");
  23. //1、将user存入数据库
  24. //2、发送邮件和短信
  25. //投递消息到交换机 交换机将消息路由到邮件队列和短信队列
  26. /**
  27. * 参数一 交换机名称
  28. * 参数二 路由key
  29. * 参数三 发送内容
  30. */
  31. amqpTemplate.convertAndSend("springboot_falout_exchange","",user);
  32. return "注册完成";
  33. }
  34. }

        这里直接发送的user对象,必须要将user对象实现Serializable接口。

5、编写邮件消费者

  1. import com.rk.domain.User;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.amqp.rabbit.annotation.RabbitHandler;
  4. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  5. import org.springframework.stereotype.Component;
  6. /**
  7. * @author :Rk.
  8. * @date : 2022/10/8
  9. /* */
  10. @Slf4j
  11. @Component
  12. @RabbitListener(queues = "fanout_email_queuerk") //监听队列
  13. public class EmailConsumer {
  14. //监听到队列消息后执行
  15. @RabbitHandler
  16. public void process(User user) {
  17. System.err.println("邮件消费者接收到消息发送邮件:"+user);
  18. }
  19. }

6、编写短信消费者

  1. import com.rk.domain.User;
  2. import org.springframework.amqp.rabbit.annotation.RabbitHandler;
  3. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  4. import org.springframework.stereotype.Component;
  5. /**
  6. * @author :Rk.
  7. * @date : 2022/10/8
  8. */
  9. @Component
  10. @RabbitListener(queues = "fanout_sms_queuerk")
  11. public class SumConsumer {
  12. @RabbitHandler
  13. public void process(User user){
  14. System.out.println("短信消费者接收到消息发送短信:"+user);
  15. }
  16. }

7、测试

  访问注册接口,会立即响应。

8、使用两个邮件消费者监听邮件队列

邮件消费者1:

  1. import com.rk.domain.User;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.amqp.rabbit.annotation.RabbitHandler;
  4. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  5. import org.springframework.stereotype.Component;
  6. /**
  7. * @author :Rk.
  8. * @date : 2022/10/8
  9. /* */
  10. @Slf4j
  11. @Component
  12. @RabbitListener(queues = "fanout_email_queuerk") //监听队列
  13. public class EmailConsumer1 {
  14. //监听到队列消息后执行
  15. @RabbitHandler
  16. public void process(User user) throws InterruptedException {
  17. //休眠10ms 模拟处理时间
  18. Thread.sleep(10);
  19. System.err.println("邮件消费者1接收到消息发送邮件:"+user);
  20. }
  21. }

邮件消费者2:

  1. import com.rk.domain.User;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.amqp.rabbit.annotation.RabbitHandler;
  4. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  5. import org.springframework.stereotype.Component;
  6. /**
  7. * @author :Rk.
  8. * @date : 2022/10/8
  9. /* */
  10. @Slf4j
  11. @Component
  12. @RabbitListener(queues = "fanout_email_queuerk")
  13. public class EmailConsumer2 {
  14. @RabbitHandler
  15. public void process(User user) throws InterruptedException {
  16. //休眠20ms 模拟处理时间
  17. Thread.sleep(20);
  18. System.out.println("邮件消费者2接收到消息发送邮件:"+user);
  19. }
  20. }

测试: 生产者往交换机发送20条消息:

        两个消费者使用轮询的方式对消息进行消费,而且不存在重复消费。 这里消费者1的处理时间是10ms,消费者2的处理时间为20ms,所以使用轮询的方式来进行消费并不合理,需要实现能者多劳

9、实现能者多劳和手动消息确认

更改配置文件的参数来解决这一个问题:

邮件消费者1:

  1. package com.rk.service;
  2. import com.rabbitmq.client.Channel;
  3. import com.rk.domain.User;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.springframework.amqp.core.Message;
  6. import org.springframework.amqp.rabbit.annotation.RabbitHandler;
  7. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  8. import org.springframework.stereotype.Component;
  9. import java.io.IOException;
  10. /**
  11. * @author :Rk.
  12. * @date : 2022/10/8
  13. /* */
  14. @Slf4j
  15. @Component
  16. @RabbitListener(queues = "fanout_email_queuerk")
  17. public class EmailConsumer1 {
  18. @RabbitHandler
  19. public void process(User user, Message message, Channel channel) throws IOException {
  20. try {
  21. //休眠20ms 模拟处理时间
  22. Thread.sleep(10);
  23. System.err.println("邮件消费者1接收到消息发送邮件:"+user);
  24. //确认一条消息
  25. channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
  26. }catch (Exception e){
  27. //消费者告诉队列信息消费失败
  28. /**
  29. * 拒绝确认消息:
  30. * channel.basicNack(long deliveryTag, boolean multiple, boolean requeue) ;
  31. * deliveryTag:该消息的index
  32. * multiple:是否批量true:将一次性拒绝所有小于deliveryTag的消息
  33. * requeue:被拒绝的是否重新入队列
  34. */
  35. channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
  36. }
  37. }
  38. }

邮件消费者2:

  1. import com.rabbitmq.client.Channel;
  2. import com.rk.domain.User;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.springframework.amqp.core.Message;
  5. import org.springframework.amqp.rabbit.annotation.RabbitHandler;
  6. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  7. import org.springframework.stereotype.Component;
  8. import java.io.IOException;
  9. /**
  10. * @author :Rk.
  11. * @date : 2022/10/8
  12. /* */
  13. @Slf4j
  14. @Component
  15. @RabbitListener(queues = "fanout_email_queuerk")
  16. public class EmailConsumer4 {
  17. @RabbitHandler
  18. public void process(User user, Message message, Channel channel) throws IOException {
  19. try {
  20. //确认一条消息
  21. channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
  22. //休眠20ms 模拟处理时间
  23. Thread.sleep(20);
  24. System.out.println("邮件消费者2接收到消息发送邮件:"+user);
  25. }catch (Exception e){
  26. //消费者告诉队列信息消费失败
  27. /**
  28. * 拒绝确认消息:
  29. * channel.basicNack(long deliveryTag, boolean multiple, boolean requeue) ;
  30. * deliveryTag:该消息的index
  31. * multiple:是否批量true:将一次性拒绝所有小于deliveryTag的消息
  32. * requeue:被拒绝的是否重新入队列
  33. */
  34. channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
  35. }
  36. }
  37. }

        实现能者多劳和手动确认。上面的演示过程都是将生产者和消费者写在同一个项目中,在实际开发过程中,一般使用2个项目,一个项目来投递消息,一个专门用来消费消息,使用不同的JVM来运行生产者和消费者。

整合直连交换机和主题交换机可以看下面这篇博客:

Springboot 整合RabbitMq ,用心看完这一篇就够了_小目标青年的博客-CSDN博客_springboot整合rabbitmq

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/688468
推荐阅读
相关标签
  

闽ICP备14008679号