环境
  win7
  rabbitmq-server-3.7.17
  Erlang 22.1

一、概念
1、队列
队列用于临时存储消息和转发消息。
队列类型有两种,即时队列和延时队列。
  即时队列:队列中的消息会被立即消费;
  延时队列:队列中的消息会在指定的时间延时之后被消费。

2、交换机
交换机的功能主要是接收消息并且转发到绑定的队列,交换机不存储消息,在启用ack模式后,交换机找不到队列会返回错误。

交换机有四种类型:Direct, topic, Headers and Fanout。
Direct[精确匹配类型]:Direct是RabbitMQ默认的交换机模式,先匹配, 再投送。即创建消息队列的时候,指定一个BindingKey.当发送者发送消息的时候,指定对应的Key.当Key和消息队列的BindingKey一致的时候,消息将会被发送到该消息队列中.

Topic[模式匹配]:按通配符匹配规则转发消息(最灵活),队列和交换机的绑定主要是依据一种模式(通配符+字符串),而当发送消息的时候,只有指定的Key和该模式相匹配的时候,消息才会被发送到该消息队列中.

Headers[键值对匹配]:设置header attribute参数类型的交换机。
消息队列和交换机绑定的时候会指定一组键值对规则,而发送消息的时候也会指定一组键值对规则,当两组键值对规则相匹配的时候,消息会被发送到匹配的消息队列中.

Fanout[转发消息最快]:
路由广播的形式,简单的将队列绑定到交换机上将会把消息发给绑定它的全部队列,即便设置了key,也会被忽略.

3、使用spring boot和rabbitmq整合   搭建演示工程

二、Direct Exchange-Work模式

配置类:

  1. package com.wjy.direct;
  2.  
  3. import org.springframework.amqp.core.Queue;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6.  
  7. //@Configuration这个注解是必须的,保证在基本类实例化之前该类已经被实例化
  8. @Configuration
  9. public class RabbitConfig {
  10.  
  11. /**
  12. * @Desc: 配置一个消息队列(routingKey=q_hello)
  13. */
  14. @Bean
  15. public Queue queue() {
  16. return new Queue("q_hello");
  17. }
  18.  
  19. /**
  20. * @Desc: 配置一个消息队列(routingKey=notify.refund)
  21. */
  22. @Bean
  23. public Queue refundNotifyQueue() {
  24. return new Queue("notify.refund");
  25. }
  26.  
  27. /**
  28. * @Desc: 配置一个消息队列(routingKey=query.order) 测试RPC
  29. */
  30. @Bean
  31. public Queue queryOrderQueue() {
  32. return new Queue("query.order");
  33. }
  34. }

生产者:

  1. package com.wjy.direct;
  2.  
  3. import com.wjy.mojo.Order;
  4. import org.springframework.amqp.core.AmqpTemplate;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.stereotype.Component;
  7.  
  8. import java.text.SimpleDateFormat;
  9. import java.util.Date;
  10.  
  11. /**
  12. * @Desc: 生产者
  13. */
  14. @Component
  15. public class MqSender {
  16. @Autowired
  17. private AmqpTemplate rabbitTemplate;
  18.  
  19. /**
  20. * @Desc: 将消息发送至默认的交换机且routingKey为q_hello
  21. */
  22. public void send() {
  23. //24小时制
  24. String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
  25. String context = "hello " + date;
  26. System.err.println("Sender : " + context);
  27. //简单对列的情况下routingKey即为Q名
  28. this.rabbitTemplate.convertAndSend("q_hello", context);
  29. }
  30.  
  31. /**
  32. * @Desc: 将消息发送至默认的交换机且routingKey为q_hello
  33. */
  34. public void send(String i) {
  35. //24小时制
  36. String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
  37. String context = "hello " + i + " " + date;
  38. System.err.println("Sender : " + context);
  39. //简单对列的情况下routingKey即为Q名
  40. this.rabbitTemplate.convertAndSend("q_hello", context);
  41. }
  42.  
  43. /**
  44. * @Desc: 将发送对象
  45. */
  46. public void sender(Order order){
  47. System.err.println("notify.refund send message: "+order);
  48. rabbitTemplate.convertAndSend("notify.refund", order);
  49. }
  50.  
  51. /**
  52. * @Desc: 测试RPC
  53. */
  54. public void sender(String orderId){
  55. System.err.println("query.order send message: "+orderId);
  56. Order order = (Order) rabbitTemplate.convertSendAndReceive("query.order", orderId);
  57. System.err.println("query.order return message: "+order);
  58. }
  59. }

消费者:

  1. package com.wjy.direct;
  2.  
  3. import org.springframework.amqp.rabbit.annotation.RabbitHandler;
  4. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  5. import org.springframework.stereotype.Component;
  6.  
  7. /**
  8. * @Desc: 消费者
  9. */
  10. @Component
  11. @RabbitListener(queues = "q_hello")
  12. public class Receiver {
  13.  
  14. /**
  15. * @Desc: 监听routingKey为nq_hello的队列消息
  16. */
  17. @RabbitHandler
  18. public void process(String hello) {
  19. System.err.println("Receiver1 : " + hello);
  20. }
  21. }
  1. package com.wjy.direct;
  2.  
  3. import com.wjy.mojo.Order;
  4. import org.springframework.amqp.rabbit.annotation.RabbitHandler;
  5. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  6. import org.springframework.stereotype.Component;
  7.  
  8. @Component
  9. @RabbitListener(queues = "notify.refund")
  10. public class RefundNotifyReceive {
  11. @RabbitHandler
  12. public void receive(Order order) {
  13. System.err.println("notify.refund receive message: "+order);
  14. }
  15. }
  1. package com.wjy.direct;
  2.  
  3. import com.wjy.mojo.Order;
  4. import org.springframework.amqp.rabbit.annotation.RabbitHandler;
  5. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  6. import org.springframework.stereotype.Component;
  7.  
  8. import java.math.BigDecimal;
  9. import java.util.Date;
  10.  
  11. @Component
  12. @RabbitListener(queues = "query.order")
  13. public class QueryOrderReceive {
  14. @RabbitHandler
  15. public Order receive(String orderId) {
  16. System.err.println("notify.refund receive message: "+orderId);
  17.  
  18. Order order = new Order();
  19. order.setId(100001);
  20. order.setOrderId(orderId);
  21. order.setAmount(new BigDecimal("2999.99"));
  22. order.setCreateTime(new Date());
  23. return order;
  24. }
  25. }

测试类:

  1. package com.wjy.direct;
  2.  
  3. import com.wjy.mojo.Order;
  4. import org.junit.Test;
  5. import org.junit.runner.RunWith;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.boot.test.context.SpringBootTest;
  8. import org.springframework.test.context.junit4.SpringRunner;
  9.  
  10. import java.math.BigDecimal;
  11. import java.util.Date;
  12.  
  13. /**
  14. * @Desc: 测试类
  15. */
  16. @RunWith(SpringRunner.class)
  17. @SpringBootTest
  18. public class DirectExchangeTest {
  19. @Autowired
  20. private MqSender mqSender;
  21.  
  22. @Test
  23. public void hello() throws Exception {
  24. mqSender.send();
  25. }
  26.  
  27. /**
  28. * @Desc: 一对多
  29. * 应用场景:系统通常会做集群、分布式或灾备部署
  30. */
  31. @Test
  32. public void oneToMany() throws Exception {
  33. for (int i=0;i<100;i++){
  34. mqSender.send(i+"");
  35. Thread.sleep(200);
  36. }
  37. }
  38.  
  39. /**
  40. * @Desc: 多对一 请求参数为偶数
  41. * 应用场景:系统通常会做集群、分布式或灾备部署
  42. */
  43. @Test
  44. public void test_sender_many2one_1() throws Exception {
  45. for (int i = 0; i < 20; i+=2) {
  46. mqSender.send("支付订单号:"+i);
  47. Thread.sleep(1000);
  48. }
  49. }
  50.  
  51. /**
  52. * @Desc: 多对一 请求参数为奇数
  53. * 应用场景:系统通常会做集群、分布式或灾备部署
  54. */
  55. @Test
  56. public void test_sender_many2one_2() throws Exception {
  57. for (int i = 1; i < 20; i+=2) {
  58. mqSender.send("支付订单号:"+i);
  59. Thread.sleep(1000);
  60. }
  61. }
  62.  
  63. /**
  64. * @Desc: 测试发送对象
  65. */
  66. @Test
  67. public void test_sender() {
  68. Order order = new Order();
  69. order.setId(100001);
  70. order.setOrderId(String.valueOf(System.currentTimeMillis()));
  71. order.setAmount(new BigDecimal("1999.99"));
  72. order.setCreateTime(new Date());
  73. mqSender.sender(order);
  74. }
  75.  
  76. /**
  77. * @Desc: 测试RPC
  78. * RabbitMQ支持RPC远程调用,同步返回结果。
  79. * 虽然RabbitMQ支持RPC接口调用,但不推荐使用
  80. * 原因:
  81. * 1)RPC默认为单线程阻塞模型,效率极低。
  82. * 2)需要手动实现多线程消费。
  83. */
  84. @Test
  85. public void test_rpc() {
  86. mqSender.sender("900000001");
  87. }
  88. }

三、Topic Exchange-主题模式


符号“#”匹配一个或多个词,符号“*”匹配不多不少一个词.

配置类:

  1. package com.wjy.topic;
  2.  
  3. import org.springframework.amqp.core.Binding;
  4. import org.springframework.amqp.core.BindingBuilder;
  5. import org.springframework.amqp.core.Queue;
  6. import org.springframework.amqp.core.TopicExchange;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9.  
  10. @Configuration
  11. public class TopicRabbitConfig {
  12.  
  13. final static String message = "api.core";
  14. final static String messages = "api.payment";
  15.  
  16. /**
  17. * 配置一个routingKey为api.core的消息队列
  18. */
  19. @Bean
  20. public Queue coreQueue() {
  21. return new Queue(TopicRabbitConfig.message);
  22. }
  23.  
  24. /**
  25. * @Desc: 配置一个routingKey为api.payment的消息队列
  26. */
  27. @Bean
  28. public Queue paymentQueue() {
  29. return new Queue(TopicRabbitConfig.messages);
  30. }
  31.  
  32. /**
  33. * @Desc: coreExchange交换机
  34. */
  35. @Bean
  36. public TopicExchange coreExchange() {
  37. return new TopicExchange("coreExchange");
  38. }
  39.  
  40. /**
  41. * @Desc: paymentExchange交换机
  42. */
  43. @Bean
  44. public TopicExchange paymentExchange() {
  45. return new TopicExchange("paymentExchange");
  46. }
  47.  
  48. /**
  49. * 配置一个routingKey为api.core的消息队列并绑定在coreExchange交换机上(交换机的匹配规则为api.core.*)
  50. */
  51. @Bean
  52. public Binding bindingCoreExchange(Queue coreQueue, TopicExchange coreExchange) {
  53. return BindingBuilder.bind(coreQueue).to(coreExchange).with("api.core.*");
  54. }
  55.  
  56. /**
  57. * @Desc: 配置一个routingKey为api.payment的消息队列并绑定在paymentExchange交换机上(交换机的匹配规则为api.payment.#)
  58. */
  59. @Bean
  60. public Binding bindingPaymentExchange(Queue paymentQueue, TopicExchange paymentExchange) {
  61. return BindingBuilder.bind(paymentQueue).to(paymentExchange).with("api.payment.#");
  62. }
  63. }

生产者:

  1. package com.wjy.topic;
  2.  
  3. import org.springframework.amqp.core.AmqpTemplate;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.stereotype.Component;
  6.  
  7. @Component
  8. public class ApiCoreSender {
  9. @Autowired
  10. private AmqpTemplate rabbitTemplate;
  11.  
  12. /**
  13. * @Desc: 发送消息至coreExchange交换机且routingKey为api.core.user
  14. */
  15. public void user(String msg){
  16. System.err.println("api.core.user send message: "+msg);
  17. rabbitTemplate.convertAndSend("coreExchange", "api.core.user", msg);
  18. }
  19.  
  20. /**
  21. * @Desc: 发送消息至coreExchange交换机且routingKey为api.core.user.query
  22. */
  23. public void userQuery(String msg){
  24. System.err.println("api.core.user.query send message: "+msg);
  25. rabbitTemplate.convertAndSend("coreExchange", "api.core.user.query", msg);
  26. }
  27. }
  1. package com.wjy.topic;
  2.  
  3. import org.springframework.amqp.core.AmqpTemplate;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.stereotype.Component;
  6.  
  7. @Component
  8. public class ApiPaymentSender {
  9. @Autowired
  10. private AmqpTemplate rabbitTemplate;
  11.  
  12. /**
  13. * @Desc: 添加一个order()方法,发送消息至paymentExchange交换机且routingKey为api.payment.order
  14. */
  15. public void order(String msg){
  16. System.err.println("api.payment.order send message: "+msg);
  17. rabbitTemplate.convertAndSend("paymentExchange", "api.payment.order", msg);
  18. }
  19.  
  20. /**
  21. * @Desc: 添加一个orderQuery()方法,发送消息至paymentExchange交换机且routingKey为api.payment.order.query
  22. */
  23. public void orderQuery(String msg){
  24. System.err.println("api.payment.order.query send message: "+msg);
  25. rabbitTemplate.convertAndSend("paymentExchange", "api.payment.order.query", msg);
  26. }
  27.  
  28. /**
  29. * @Desc: 添加一个orderDetailQuery()方法,发送消息至paymentExchange交换机且routingKey为api.payment.order.detail.query
  30. */
  31. public void orderDetailQuery(String msg){
  32. System.err.println("api.payment.order.detail.query send message: "+msg);
  33. rabbitTemplate.convertAndSend("paymentExchange", "api.payment.order.detail.query", msg);
  34. }
  35. }

消费者:

  1. package com.wjy.topic;
  2.  
  3. import org.springframework.amqp.rabbit.annotation.RabbitHandler;
  4. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  5. import org.springframework.stereotype.Component;
  6.  
  7. @Component
  8. public class ApiCoreReceive {
  9. @RabbitHandler
  10. @RabbitListener(queues = "api.core")
  11. public void handle(String msg) {
  12. System.err.println("api.core receive message: "+msg);
  13. }
  14. }
  1. package com.wjy.topic;
  2.  
  3. import org.springframework.amqp.rabbit.annotation.RabbitHandler;
  4. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  5. import org.springframework.stereotype.Component;
  6.  
  7. @Component
  8. public class ApiPaymentReceive {
  9. @RabbitHandler
  10. @RabbitListener(queues = "api.payment")
  11. public void handle(String msg) {
  12. System.err.println("api.payment.order receive message: "+msg);
  13. }
  14. }

测试类:

  1. package com.wjy.topic;
  2.  
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7. import org.springframework.test.context.junit4.SpringRunner;
  8.  
  9. @RunWith(SpringRunner.class)
  10. @SpringBootTest
  11. public class ApiCoreSenderTests {
  12. @Autowired
  13. private ApiCoreSender sender;
  14.  
  15. @Test
  16. public void test_user() {
  17. sender.user("用户管理!");
  18. }
  19.  
  20. @Test
  21. public void test_userQuery() {
  22. sender.userQuery("查询用户信息!");
  23. }
  24. }
  1. package com.wjy.topic;
  2.  
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7. import org.springframework.test.context.junit4.SpringRunner;
  8.  
  9. @RunWith(SpringRunner.class)
  10. @SpringBootTest
  11. public class ApiPaymentSenderTests {
  12. @Autowired
  13. private ApiPaymentSender sender;
  14.  
  15. @Test
  16. public void test_order() {
  17. sender.order("订单管理!");
  18. }
  19.  
  20. @Test
  21. public void test_orderQuery() {
  22. sender.orderQuery("查询订单信息!");
  23. }
  24.  
  25. @Test
  26. public void test_orderDetailQuery() {
  27. sender.orderDetailQuery("查询订单详情信息!");
  28. }
  29. }

四、Fanout Exchange-订阅模式

配置类:

  1. package com.wjy.fanout;
  2.  
  3. import org.springframework.amqp.core.Binding;
  4. import org.springframework.amqp.core.BindingBuilder;
  5. import org.springframework.amqp.core.FanoutExchange;
  6. import org.springframework.amqp.core.Queue;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9.  
  10. @Configuration
  11. public class FanoutConfig {
  12.  
  13. /**
  14. * @Desc: 配置一个routingKey为api.report.payment的消息队列
  15. */
  16. @Bean
  17. public Queue reportPaymentQueue() {
  18. return new Queue("api.report.payment");
  19. }
  20.  
  21. /**
  22. * @Desc: 配置一个routingKey为api.report.refund的消息队列
  23. */
  24. @Bean
  25. public Queue reportRefundQueue() {
  26. return new Queue("api.report.refund");
  27. }
  28.  
  29. /**
  30. * @Desc: 配置一个reportExchange交换机
  31. */
  32. @Bean
  33. public FanoutExchange reportExchange() {
  34. return new FanoutExchange("reportExchange");
  35. }
  36.  
  37. /**
  38. * @Desc: 配置routingKey为api.report.payment的消息队列并绑定在reportExchange交换机上
  39. */
  40. @Bean
  41. public Binding bindingReportPaymentExchange(Queue reportPaymentQueue, FanoutExchange reportExchange) {
  42. return BindingBuilder.bind(reportPaymentQueue).to(reportExchange);
  43. }
  44.  
  45. /**
  46. * @Desc: 配置routingKey为api.report.refund的消息队列并绑定在reportExchange交换机上
  47. */
  48. @Bean
  49. public Binding bindingReportRefundExchange(Queue reportRefundQueue, FanoutExchange reportExchange) {
  50. return BindingBuilder.bind(reportRefundQueue).to(reportExchange);
  51. }
  52. }

生产者:

  1. package com.wjy.fanout;
  2.  
  3. import org.springframework.amqp.core.AmqpTemplate;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.stereotype.Component;
  6.  
  7. @Component
  8. public class ApiReportSender {
  9. @Autowired
  10. private AmqpTemplate rabbitTemplate;
  11.  
  12. public void generateReports(String msg){
  13. System.err.println("api.generate.reports send message: "+msg);
  14. rabbitTemplate.convertAndSend("reportExchange", "api.generate.reports", msg);
  15. }
  16. }

消费者:

  1. package com.wjy.fanout;
  2.  
  3. import org.springframework.amqp.rabbit.annotation.RabbitHandler;
  4. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  5. import org.springframework.stereotype.Component;
  6.  
  7. @Component
  8. public class ApiReportReceive {
  9. @RabbitHandler
  10. @RabbitListener(queues = "api.report.payment")
  11. public void payment(String msg) {
  12. System.err.println("api.report.payment receive message: "+msg);
  13. }
  14.  
  15. @RabbitHandler
  16. @RabbitListener(queues = "api.report.refund")
  17. public void refund(String msg) {
  18. System.err.println("api.report.refund receive message: "+msg);
  19. }
  20. }

测试类:

  1. package com.wjy.fanout;
  2.  
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7. import org.springframework.test.context.junit4.SpringRunner;
  8.  
  9. @RunWith(SpringRunner.class)
  10. @SpringBootTest
  11. public class ApiReportSenderTests {
  12. @Autowired
  13. private ApiReportSender sender;
  14.  
  15. @Test
  16. public void test_generateReports() {
  17. sender.generateReports("开始生成报表!");
  18. }
  19. }

五、Headers Exchange

配置类:

  1. package com.wjy.headers;
  2.  
  3. import org.springframework.amqp.core.Binding;
  4. import org.springframework.amqp.core.BindingBuilder;
  5. import org.springframework.amqp.core.HeadersExchange;
  6. import org.springframework.amqp.core.Queue;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9.  
  10. import java.util.HashMap;
  11. import java.util.Map;
  12.  
  13. @Configuration
  14. public class HeadersConfig {
  15. /**
  16. * @Desc: 配置一个routingKey为credit.bank的消息队列
  17. */
  18. @Bean
  19. public Queue creditBankQueue() {
  20. return new Queue("credit.bank");
  21. }
  22.  
  23. /**
  24. * @Desc: 配置一个routingKey为credit.finance的消息队列
  25. */
  26. @Bean
  27. public Queue creditFinanceQueue() {
  28. return new Queue("credit.finance");
  29. }
  30.  
  31. /**
  32. * @Desc: 配置一个creditBankExchange交换机
  33. */
  34. @Bean
  35. public HeadersExchange creditBankExchange() {
  36. return new HeadersExchange("creditBankExchange");
  37. }
  38.  
  39. /**
  40. * @Desc: 配置一个creditFinanceExchange交换机
  41. */
  42. @Bean
  43. public HeadersExchange creditFinanceExchange() {
  44. return new HeadersExchange("creditFinanceExchange");
  45. }
  46.  
  47. /**
  48. * @Desc: 配置一个routingKey为credit.bank的消息队列并绑定在creditBankExchange交换机上
  49. */
  50. @Bean
  51. public Binding bindingCreditAExchange(Queue creditBankQueue, HeadersExchange creditBankExchange) {
  52. Map<String,Object> headerValues = new HashMap<>();
  53. headerValues.put("type", "cash");
  54. headerValues.put("aging", "fast");
  55. //whereall 完全匹配
  56. return BindingBuilder.bind(creditBankQueue).to(creditBankExchange).whereAll(headerValues).match();
  57. }
  58.  
  59. /**
  60. * @Desc: 配置一个routingKey为credit.finance的消息队列并绑定在creditFinanceExchange交换机上
  61. */
  62. @Bean
  63. public Binding bindingCreditBExchange(Queue creditFinanceQueue, HeadersExchange creditFinanceExchange) {
  64. Map<String,Object> headerValues = new HashMap<>();
  65. headerValues.put("type", "cash");
  66. headerValues.put("aging", "fast");
  67. //whereany 其中一项匹配即可
  68. return BindingBuilder.bind(creditFinanceQueue).to(creditFinanceExchange).whereAny(headerValues).match();
  69. }
  70. }

生产者:

  1. package com.wjy.headers;
  2.  
  3. import org.springframework.amqp.core.AmqpTemplate;
  4. import org.springframework.amqp.core.Message;
  5. import org.springframework.amqp.core.MessageProperties;
  6. import org.springframework.amqp.support.converter.MessageConverter;
  7. import org.springframework.amqp.support.converter.SimpleMessageConverter;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.stereotype.Component;
  10.  
  11. import java.util.Map;
  12.  
  13. @Component
  14. public class ApiCreditSender {
  15. @Autowired
  16. private AmqpTemplate rabbitTemplate;
  17.  
  18. public void creditBank(Map<String, Object> head, String msg){
  19. System.err.println("credit.bank send message: "+msg);
  20. rabbitTemplate.convertAndSend("creditBankExchange", "credit.bank", getMessage(head, msg));
  21. }
  22.  
  23. public void creditFinance(Map<String, Object> head, String msg){
  24. System.err.println("credit.finance send message: "+msg);
  25. rabbitTemplate.convertAndSend("creditFinanceExchange", "credit.finance", getMessage(head, msg));
  26. }
  27.  
  28. private Message getMessage(Map<String, Object> head, Object msg){
  29. MessageProperties messageProperties = new MessageProperties();
  30. for (Map.Entry<String, Object> entry : head.entrySet()) {
  31. messageProperties.setHeader(entry.getKey(), entry.getValue());
  32. }
  33. MessageConverter messageConverter = new SimpleMessageConverter();
  34. return messageConverter.toMessage(msg, messageProperties);
  35. }
  36. }

消费者:

  1. package com.wjy.headers;
  2.  
  3. import org.springframework.amqp.rabbit.annotation.RabbitHandler;
  4. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  5. import org.springframework.stereotype.Component;
  6.  
  7. @Component
  8. public class ApiCreditReceive {
  9. @RabbitHandler
  10. @RabbitListener(queues = "credit.bank")
  11. public void creditBank(String msg) {
  12. System.err.println("credit.bank receive message: "+msg);
  13. }
  14.  
  15. @RabbitHandler
  16. @RabbitListener(queues = "credit.finance")
  17. public void creditFinance(String msg) {
  18. System.err.println("credit.finance receive message: "+msg);
  19. }
  20. }

测试类:

  1. package com.wjy.headers;
  2.  
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7. import org.springframework.test.context.junit4.SpringRunner;
  8.  
  9. import java.util.HashMap;
  10. import java.util.Map;
  11.  
  12. @RunWith(SpringRunner.class)
  13. @SpringBootTest
  14. public class ApiCreditSenderTests {
  15. @Autowired
  16. private ApiCreditSender sender;
  17.  
  18. @Test
  19. public void test_creditBank_type() {
  20. Map<String,Object> head = new HashMap<>();
  21. head.put("type", "cash");
  22. sender.creditBank(head, "银行授信(部分匹配)");
  23. }
  24.  
  25. @Test
  26. public void test_creditBank_all() {
  27. Map<String,Object> head = new HashMap<>();
  28. head.put("type", "cash");
  29. head.put("aging", "fast");
  30. sender.creditBank(head, "银行授信(全部匹配)");
  31. }
  32.  
  33. @Test
  34. public void test_creditFinance_type() {
  35. Map<String,Object> head = new HashMap<>();
  36. head.put("type", "cash");
  37. sender.creditFinance(head, "金融公司授信(部分匹配)");
  38. }
  39.  
  40. @Test
  41. public void test_creditFinance_all() {
  42. Map<String,Object> head = new HashMap<>();
  43. head.put("type", "cash");
  44. head.put("aging", "fast");
  45. sender.creditFinance(head, "金融公司授信(全部匹配)");
  46. }
  47. }

六、延时队列

配置类:

  1. package com.wjy.delaymq;
  2.  
  3. import org.springframework.amqp.core.Binding;
  4. import org.springframework.amqp.core.BindingBuilder;
  5. import org.springframework.amqp.core.DirectExchange;
  6. import org.springframework.amqp.core.Queue;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9.  
  10. import java.util.HashMap;
  11. import java.util.Map;
  12.  
  13. @Configuration
  14. public class QueueConfiguration {
  15.  
  16. /**
  17. * @Desc:消息队列app.queue.hello
  18. */
  19. @Bean
  20. public Queue helloQueue() {
  21. Queue queue = new Queue("app.queue.hello", true, false, false);
  22. return queue;
  23. }
  24.  
  25. /**
  26. * 默认即时消息交换机
  27. */
  28. @Bean("defaultDirectExchange")
  29. public DirectExchange defaultDirectExchange() {
  30. return new DirectExchange("default.direct.exchange", true, false);
  31. }
  32.  
  33. /**
  34. * @Desc:消息队列app.queue.hello绑定到默认队列上
  35. * 交换机匹配规则:app.queue.hello
  36. */
  37. @Bean
  38. public Binding helloBinding() {
  39. return BindingBuilder.bind(helloQueue()).to(defaultDirectExchange()).with("app.queue.hello");
  40. }
  41.  
  42. /**
  43. * 配置延迟消息死信队列
  44. */
  45. @Bean
  46. public Queue defaultDeadLetterQueue() {
  47. Map<String, Object> arguments = new HashMap<>();
  48. //设置交换机路由
  49. arguments.put("x-dead-letter-exchange", "default.direct.exchange");
  50. //设置转发队列名称
  51. arguments.put("x-dead-letter-routing-key", "default.repeat.trade.queue");
  52. Queue queue = new Queue("default.dead.letter.queue", true, false, false, arguments);
  53. return queue;
  54. }
  55.  
  56. /**
  57. * @Desc:将延迟消息队列绑定到延迟交换机上
  58. * 交换机匹配规则:default.dead.letter.queue
  59. */
  60. @Bean
  61. public Binding defaultDeadLetterBinding() {
  62. Binding bind = BindingBuilder.bind(defaultDeadLetterQueue()).to(defaultDirectExchange()).with("default.dead.letter.queue");
  63. return bind;
  64. }
  65.  
  66. /**
  67. * 配置转发消息队列default.repeat.trade.queue
  68. * @return
  69. */
  70. @Bean
  71. public Queue defaultRepeatTradeQueue() {
  72. Queue queue = new Queue("default.repeat.trade.queue", true, false, false);
  73. return queue;
  74. }
  75.  
  76. /**
  77. * 转发队列和默认交换机的绑定;
  78. * 交换机匹配规则:default.repeat.trade.queue
  79. */
  80. @Bean
  81. public Binding defaultRepeatTradeBinding() {
  82. return BindingBuilder
  83. .bind(defaultRepeatTradeQueue())
  84. .to(defaultDirectExchange())
  85. .with("default.repeat.trade.queue");
  86. }
  87.  
  88. }

生产者:

  1. package com.wjy.delaymq;
  2.  
  3. import org.springframework.amqp.AmqpException;
  4. import org.springframework.amqp.core.Message;
  5. import org.springframework.amqp.core.MessagePostProcessor;
  6. import org.springframework.amqp.rabbit.core.RabbitTemplate;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.stereotype.Component;
  9.  
  10. @Component
  11. public class Sender {
  12. @Autowired
  13. private RabbitTemplate rabbitTemplate;
  14.  
  15. public void send(QueueMessage message) {
  16. //即时消息
  17. if(message.getType() == 10){
  18. sendMessage(message.getExchange(),message.getQueueName(),message.getMessage());
  19. }
  20. //延时消息
  21. if(message.getType() == 20){
  22. sendTimeMessage(message);
  23. }
  24. }
  25.  
  26. //发送即时消息;
  27. private void sendMessage(String exchange,String queueName,String msg){
  28. rabbitTemplate.convertAndSend(exchange,queueName, msg);
  29. }
  30.  
  31. //发送延时消息;
  32. public void sendTimeMessage(QueueMessage message) {
  33. int seconds = message.getSeconds();
  34. // 直接发送,无需进入死信队列
  35. if(seconds <= 0){
  36. sendMessage(message.getExchange(),message.getQueueName(), message.getMessage());
  37. }else{
  38. //rabbit默认为毫秒级
  39. long times = seconds * 1000;
  40. //这里需要字符定义延时处理器;
  41. MessagePostProcessor processor = new MessagePostProcessor() {
  42. @Override
  43. public Message postProcessMessage(Message message) throws AmqpException {
  44. message.getMessageProperties().setExpiration(times + "");
  45. return message;
  46. }
  47. };
  48. //注意传送的消息必须是字串串或者 字节或者实现序列化的对象
  49. //否则报错:Execution of Rabbit message listener failed
  50. //改完后将之前的队列数据清除 否则还会报错
  51. rabbitTemplate.convertAndSend("default.direct.exchange","default.dead.letter.queue", "转发消息", processor);
  52. }
  53. }
  54.  
  55. }

消费者:

  1. package com.wjy.delaymq;
  2.  
  3. import org.springframework.amqp.rabbit.annotation.RabbitHandler;
  4. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.stereotype.Component;
  7.  
  8. @Component
  9. @RabbitListener(queues = "default.repeat.trade.queue")
  10. public class TradeRecever {
  11. @Autowired
  12. private Sender sender;
  13.  
  14. @RabbitHandler
  15. public void process(String content) {
  16. System.err.println("-----------延时结束--------------"+content);
  17. QueueMessage message = new QueueMessage("app.queue.hello", "转发消息...");
  18. message.setType(10);
  19. sender.send(message);
  20. }
  21. }
  1. package com.wjy.delaymq;
  2.  
  3. import org.springframework.amqp.rabbit.annotation.RabbitHandler;
  4. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  5. import org.springframework.stereotype.Component;
  6.  
  7. @Component
  8. @RabbitListener(queues = "app.queue.hello")
  9. public class HelloRecever {
  10.  
  11. @RabbitHandler
  12. public void process(String content) {
  13.  
  14. System.err.println("hello 接受消息:" + content);
  15. }
  16. }

POJO:

  1. package com.wjy.delaymq;
  2.  
  3. import java.io.Serializable;
  4. import java.util.Date;
  5.  
  6. public class QueueMessage implements Serializable {
  7. private String exchange;
  8.  
  9. private String queueName;
  10.  
  11. private Integer type;
  12.  
  13. private Integer group;
  14.  
  15. private Date timestamp;
  16.  
  17. private String message;
  18.  
  19. private Integer status;
  20.  
  21. private int retry = 0;
  22.  
  23. private int maxRetry = 10;
  24.  
  25. private int seconds = 1;
  26.  
  27. public QueueMessage() {
  28. super();
  29. }
  30.  
  31. public QueueMessage(String queueName, String message) {
  32. super();
  33. this.queueName = queueName;
  34. this.message = message;
  35. this.exchange = "default.direct.exchange";
  36. this.type = 10;
  37. this.group = 10;
  38. this.timestamp = new Date();
  39. this.status = 10;
  40. }
  41.  
  42. public String getExchange() {
  43. return exchange;
  44. }
  45.  
  46. public void setExchange(String exchange) {
  47. this.exchange = exchange;
  48. }
  49.  
  50. public String getQueueName() {
  51. return queueName;
  52. }
  53.  
  54. public void setQueueName(String queueName) {
  55. this.queueName = queueName;
  56. }
  57.  
  58. public Integer getType() {
  59. return type;
  60. }
  61.  
  62. public void setType(Integer type) {
  63. this.type = type;
  64. }
  65.  
  66. public Integer getGroup() {
  67. return group;
  68. }
  69.  
  70. public void setGroup(Integer group) {
  71. this.group = group;
  72. }
  73.  
  74. public Date getTimestamp() {
  75. return timestamp;
  76. }
  77.  
  78. public void setTimestamp(Date timestamp) {
  79. this.timestamp = timestamp;
  80. }
  81.  
  82. public String getMessage() {
  83. return message;
  84. }
  85.  
  86. public void setMessage(String message) {
  87. this.message = message;
  88. }
  89.  
  90. public Integer getStatus() {
  91. return status;
  92. }
  93.  
  94. public void setStatus(Integer status) {
  95. this.status = status;
  96. }
  97.  
  98. public int getRetry() {
  99. return retry;
  100. }
  101.  
  102. public void setRetry(int retry) {
  103. this.retry = retry;
  104. }
  105.  
  106. public int getMaxRetry() {
  107. return maxRetry;
  108. }
  109.  
  110. public void setMaxRetry(int maxRetry) {
  111. this.maxRetry = maxRetry;
  112. }
  113.  
  114. public int getSeconds() {
  115. return seconds;
  116. }
  117.  
  118. public void setSeconds(int seconds) {
  119. this.seconds = seconds;
  120. }
  121. }

测试类:

  1. package com.wjy.delaymq;
  2.  
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7.  
  8. import org.springframework.test.context.junit4.SpringRunner;
  9.  
  10. @RunWith(SpringRunner.class)
  11. @SpringBootTest
  12. public class DelayTest {
  13.  
  14. @Autowired
  15. private Sender sender;
  16.  
  17. @Test
  18. public void delaySendTest() {
  19. System.err.println("发送延迟消息...");
  20. QueueMessage message = new QueueMessage("app.queue.hello", "测试延时消息...");
  21. //20代表延时消息队列;
  22. message.setType(20);
  23. //设置延时时间,单位为毫秒;
  24. message.setSeconds(6);
  25. sender.send(message);
  26. try {
  27. Thread.sleep(600000);
  28. } catch (InterruptedException e) {
  29. e.printStackTrace();
  30. }
  31. }
  32. }

七、消息确认机制

配置类:

  1. package com.wjy.ack;
  2.  
  3. import org.springframework.amqp.core.Binding;
  4. import org.springframework.amqp.core.BindingBuilder;
  5. import org.springframework.amqp.core.FanoutExchange;
  6. import org.springframework.amqp.core.Queue;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9.  
  10. @Configuration
  11. public class AckRabbitConfig {
  12.  
  13. /**
  14. * 定义一个hello的队列
  15. * Queue 可以有4个参数
  16. * 1.队列名
  17. * 2.durable 持久化消息队列 ,rabbitmq重启的时候不需要创建新的队列 默认true
  18. * 3.auto-delete 表示消息队列没有在使用时将被自动删除 默认是false
  19. * 4.exclusive 表示该消息队列是否只在当前connection生效,默认是false
  20. */
  21. @Bean
  22. public Queue helloQueue() {
  23. return new Queue("queue-test");
  24. }
  25.  
  26. /** ======================== 定制一些处理策略 =============================*/
  27.  
  28. /**
  29. * Fanout 就是我们熟悉的广播模式或者订阅模式,给Fanout交换机发送消息,绑定了这个交换机的所有队列都收到这个消息。
  30. * @return
  31. */
  32. @Bean
  33. public FanoutExchange fanoutExchange() {
  34. return new FanoutExchange("ABExchange");
  35. }
  36.  
  37. @Bean
  38. public Binding bindingExchangeA(Queue helloQueue, FanoutExchange fanoutExchange) {
  39. return BindingBuilder.bind(helloQueue).to(fanoutExchange);
  40. }
  41.  
  42. }

生产者:

  1. package com.wjy.ack;
  2.  
  3. import org.springframework.amqp.core.Message;
  4. import org.springframework.amqp.rabbit.core.RabbitTemplate;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.stereotype.Component;
  7.  
  8. import java.util.Date;
  9.  
  10. @Component
  11. public class Producer implements RabbitTemplate.ReturnCallback {
  12. @Autowired
  13. private RabbitTemplate rabbitTemplate;
  14.  
  15. /**
  16. * 给hello队列发送消息
  17. */
  18. public void send() {
  19. String context = "你好现在是 " + new Date() +"";
  20. System.err.println("HelloSender发送内容 : " + context);
  21. this.rabbitTemplate.setReturnCallback(this);
  22. this.rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
  23. if (!ack) {
  24. System.out.println("HelloSender消息发送失败" + cause + correlationData.toString());
  25. } else {
  26. System.out.println("HelloSender 消息发送成功 ");
  27. }
  28. });
  29.  
  30. rabbitTemplate.convertAndSend("queue-test", context);
  31. }
  32.  
  33. @Override
  34. public void returnedMessage(Message message, int i, String s, String s1, String s2) {
  35. System.err.println("sender return success" + message.toString()+"==="+i+"==="+s1+"==="+s2);
  36. }
  37. }

消费者:

  1. package com.wjy.ack;
  2.  
  3. import com.rabbitmq.client.Channel;
  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.  
  9. import java.io.IOException;
  10.  
  11. @Component
  12. @RabbitListener(queues = "queue-test")
  13. public class Comsumer {
  14.  
  15. @RabbitHandler
  16. public void process(String msg,Message message, Channel channel) throws IOException {
  17. try {
  18. // 采用手动应答模式, 手动确认应答更为安全稳定
  19. /*channel.basicAck(deliveryTag,ack)
  20. deliveryTag-当前消息的类似编号的号码,服务端为每一个消息生成的类似编号的号码
  21. ack-false只确认当前一个消息收到,true确认所有consumer获得的消息
  22. */
  23. channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
  24. System.err.println("receive: " + new String(message.getBody()));
  25. }
  26. catch (Exception e){
  27. //丢弃这条消息
  28. channel.basicNack(message.getMessageProperties().getDeliveryTag(), false,false);
  29. //拒绝这条消息
  30. //channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
  31. }
  32. }
  33. }

测试类:

  1. package com.wjy.ack;
  2.  
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7. import org.springframework.test.context.junit4.SpringRunner;
  8.  
  9. @RunWith(SpringRunner.class)
  10. @SpringBootTest
  11. public class RabbitmqAckTests {
  12. @Autowired
  13. private Producer producer;
  14.  
  15. /**
  16. * @Desc: 测试之前需在application.yml开启消息确认的配置
  17. */
  18. @Test
  19. public void send() {
  20. producer.send();
  21. }
  22. }

演示代码

参考:

springboot集成rabbitmq(实战)

延时队列

5种消息队列

RabbitMQ四种交换机类型介绍

【RabbitMQ学习之二】RabbitMQ四种交换机模式应用的更多相关文章

  1. rabbitmq系列(二)几种常见模式的应用场景及实现

    一.简单模式 原理:生产者将消息交给默认的交换机,交换机获取消息后交给绑定这个生产者的队列(投递规则为队列名称和routing key 相同的队列),监听当前队列的消费者获取信息并执行消费逻辑. 场景 ...

  2. RabbitMQ四种交换机类型介绍

    RabbitMQ  原文地址: https://baijiahao.baidu.com/s?id=1577456875919174629&wfr=spider&for=pc 最新版本的 ...

  3. ActiveMQ、RabbitMQ、RocketMQ、Kafka四种消息中间件分析介绍

    ActiveMQ.RabbitMQ.RocketMQ.Kafka四种消息中间件分析介绍 我们从四种消息中间件的介绍到基本使用,以及高可用,消息重复性,消息丢失,消息顺序性能方面进行分析介绍! 一.消息 ...

  4. Rabbitmq的几种交换机模式

    Rabbitmq的核心概念(如下图所示):有虚拟主机.交换机.队列.绑定: 交换机可以理解成具有路由表的路由程序,仅此而已.每个消息都有一个称为路由键(routing key)的属性,就是一个简单的字 ...

  5. RabbitMQ学习系列二-C#代码发送消息

    RabbitMQ学习系列二:.net 环境下 C#代码使用 RabbitMQ 消息队列 http://www.80iter.com/blog/1437455520862503 上一篇已经讲了Rabbi ...

  6. 学习笔记:CentOS7学习之二十四:expect-正则表达式-sed-cut的使用

    目录 学习笔记:CentOS7学习之二十四:expect-正则表达式-sed-cut的使用 24.1 expect实现无交互登录 24.1.1 安装和使用expect 24.2 正则表达式的使用 24 ...

  7. 设计模式学习(二十四):Spring 中使用到的设计模式

    设计模式学习(二十四):Spring 中使用到的设计模式 作者:Grey 原文地址: 博客园:设计模式学习(二十四):Spring 中使用到的设计模式 CSDN:设计模式学习(二十四):Spring ...

  8. 从零学习Fluter(八):Flutter的四种运行模式--Debug、Release、Profile和test以及命名规范

    从零学习Fluter(八):Flutter的四种运行模式--Debug.Release.Profile和test以及命名规范 好几天没有跟新我的这个系列文章,一是因为这两天我又在之前的基础上,重新认识 ...

  9. python3.4学习笔记(二十四) Python pycharm window安装redis MySQL-python相关方法

    python3.4学习笔记(二十四) Python pycharm window安装redis MySQL-python相关方法window安装redis,下载Redis的压缩包https://git ...

随机推荐

  1. Linq分批次,每组1000条

    /// <summary> /// 分组插入每次插入1000 /// </summary> /// <param name="data">< ...

  2. C# 获取所有可用的打印机

    C# 获取所有安装了的打印机代码如下: using System.Drawing.Printing; var printers = PrinterSettings.InstalledPrinters; ...

  3. 【转载】C#的ArrayList使用Contains方法判断是否包含某个元素

    在C#的编程开发中,ArrayList集合是一个常用的非泛型类集合,在ArrayList集合中可以使用Contains方法判断是否包含某个元素数据,如果包含则返回true,否则返回false,Cont ...

  4. 英语chrysopal金绿宝石chrysopal单词

    chrysopal金绿宝石,也称金绿玉.化学成分为BeAl2O4.晶体属正交(斜方)晶系的氧化物矿物.它位列名贵宝石,具有四个变种:猫眼,变石,变石猫眼和金绿宝石晶体. 金绿宝石本身就是较稀少的矿物, ...

  5. idea使用过程中的一些常见问题,做个笔记

    :当实现这个接口方法时重载是不允许的. 首先我相信我的代码肯定没问题,因为我实现的接口确实有这个方法.在编程阶段就提示这个错误,于是我有理由相信应该是编译错误!通过google,解决办法so easy ...

  6. pgsql主备搭建及切换

    二.主从搭建 2.1测试目标 测试postgresql主从搭建安装过程 2.2环境准备 实例级别的复制 流复制主库可读写,但从库只允许查询不允许写人, 而逻辑复制的从库可读写 流复制实验环境 主机 主 ...

  7. es更新说明(dsl)

    一.旧版elasticsearch-dsl 很多同学在python搜索引擎视频中关于看到的第十章elasticsearch使用中使用python创建mapping老师使用的以下代码,这些代码对于ela ...

  8. 【MySQL】自增步长调整

    mysql> show variables like '%increment%'; +-----------------------------+-------+ | Variable_name ...

  9. Centos7防火墙firewalled基本使用

    firewalld支持动态更新技术并加入了区域(zone)的概念.简单来说,区域就是firewalld预先准备了几套防火墙策略集合(策略模板),用户可以根据生产场景的不同而选择合适的策略集合,从而实现 ...

  10. linux之shell脚本学习(一)

    #!/bin/bash echo 'hello' your_name='longxiong' echo $your_name echo ${your_name} for i in `ls /opt`; ...