目录
1:什么是MQ
MQ(Message Queue)消息队列,是基础数据结构中“先进先出”的一种数据机构。指把要传输的数据(消息)放在队列中,用队列机制来实现消息传递——生产者产生消息并把消息放入队列,然后由消费者去处理。消费者可以到指定队列拉取消息,或者订阅相应的队列,由MQ服务端给其推送消息。
2:主流MQ中间间对比
3:RabbitMQ安装
https://www.cnblogs.com/yihuihui/p/9095130.html
4:RabbitMQ案例
4.1:添加用户、添加Virtual Hosts
添加用户和虚拟主机
=======================虚拟主机的作用========================
4.1: 点对点发送(hello word模型)
总结:点对点发送,发送者发送多少消息,接受者接受多少消息。发送消息到Queues
生产者:
package com.thit.mq;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;
import com.thit.util.MqUtil;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author :huyiju
* @date :2020-05-28 19:03
* 直接发送对列
* 1对1 消费消息
*/
public class Producter {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection= MqUtil.getconnection();
//创建通道
Channel channel=connection.createChannel();
//设置创建的queue状态
//参数1:队列名字
//参数2:队列的持久化 true持久化 false不持久化 重启会消失
//参数3:是否独占队列
//参数4:true 消费完删除对列
//参数5:传递的参数
channel.queueDeclare("test1",true,false,false,null);
//推送消息 消息设置持久化
//1:交换机名字
//2:对列名字
//3:基础参数MessageProperties.PERSISTENT_TEXT_PLAIN,消息持久化
//4:发送消息
for (int i=0;i<20;i++){
channel.basicPublish("","test1", MessageProperties.PERSISTENT_TEXT_PLAIN,("第几次发送消息:"+i).getBytes());
}
//关闭通道
MqUtil.close(connection,channel);
System.out.println("发送消息结束");
}
}
消费者:
package com.thit.mq;
import com.rabbitmq.client.*;
import com.thit.util.MqUtil;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* @author :huyiju
* @date :2020-05-28 19:03
* 直接发送对列
* 1对1 消费消息
*/
public class Customer1 {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection= MqUtil.getconnection();
//创建通道
Channel channel=connection.createChannel();
//一次消费一个消息
channel.basicQos(1);
//设置创建的queue状态
//参数1:队列名字
//参数2:队列的持久化 true持久化 false不持久化 重启会消失
//参数3:是否独占队列
//参数4:true 消费完删除对列
//参数5:传递的参数
channel.queueDeclare("test1",true,false,false,null);
//消费消息
//参数1:对垒名字
//参数2:ack确认 true的话,如果消费者代码出错,也会确认消费消息 消息会丢失
channel.basicConsume("test1",false,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
String a=new String(body);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("111接收到的参数是:"+a);
//消费者1 报错,没有确认消息消费,消费者2 会重复消费1得到的消息
//int b=10/0;
//当确认参数是false的时候,手动确认
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
//关闭通道
//MqUtil.close(connection,channel);
System.out.println("接受消息结束");
}
}
4.2:一个生产者和多个消费者(Work Queues)
总结:消息平均分配,即使接受者空闲,也不能多干活,直接发送消息到Queues
您可能已经注意到,调度仍然无法完全按照我们的要求进行。例如,在有两名工人的情况下,当所有奇怪的消息都很重,甚至消息很轻时,一位工人将一直忙碌而另一位工人将几乎不做任何工作。好吧,RabbitMQ对此一无所知,并且仍将平均分配消息。
发生这种情况是因为RabbitMQ在消息进入队列(queues)时才调度消息。它不会查看使用者的未确认消息数。它只是盲目地将每第n条消息发送给第n个使用者
代码案例:生产者一个,消费者多个
生产者:
package com.thit.mq;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;
import com.thit.util.MqUtil;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author :huyiju
* @date :2020-05-28 19:03
* 直接发送对列
* 1对1 消费消息
*/
public class Producter {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection= MqUtil.getconnection();
//创建通道
Channel channel=connection.createChannel();
//设置创建的queue状态
//参数1:队列名字
//参数2:队列的持久化 true持久化 false不持久化 重启会消失
//参数3:是否独占队列
//参数4:true 消费完删除对列
//参数5:传递的参数
channel.queueDeclare("test1",true,false,false,null);
//推送消息 消息设置持久化
//1:交换机名字
//2:对列名字
//3:基础参数MessageProperties.PERSISTENT_TEXT_PLAIN,消息持久化
//4:发送消息
for (int i=0;i<20;i++){
channel.basicPublish("","test1", MessageProperties.PERSISTENT_TEXT_PLAIN,("第几次发送消息:"+i).getBytes());
}
//关闭通道
MqUtil.close(connection,channel);
System.out.println("发送消息结束");
}
}
消费者多个:
package com.thit.mq;
import com.rabbitmq.client.*;
import com.thit.util.MqUtil;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* @author :huyiju
* @date :2020-05-28 19:03
* 直接发送对列
* 1对1 消费消息
*/
public class Customer1 {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection= MqUtil.getconnection();
//创建通道
Channel channel=connection.createChannel();
//一次消费一个消息
channel.basicQos(1);
//设置创建的queue状态
//参数1:队列名字
//参数2:队列的持久化 true持久化 false不持久化 重启会消失
//参数3:是否独占队列
//参数4:true 消费完删除对列
//参数5:传递的参数
channel.queueDeclare("test1",true,false,false,null);
//消费消息
//参数1:对垒名字
//参数2:ack确认 true的话,如果消费者代码出错,也会确认消费消息 消息会丢失
channel.basicConsume("test1",false,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
String a=new String(body);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("111接收到的参数是:"+a);
//消费者1 报错,没有确认消息消费,消费者2 会重复消费1得到的消息
//int b=10/0;
//当确认参数是false的时候,手动确认
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
//关闭通道
//MqUtil.close(connection,channel);
System.out.println("接受消息结束");
}
}
4.3:发布订阅模式
总结:类型是:Fanout,每一个消费者都能接受到相同的消息
1:生产者发送消息到交换机(ExChange)
2:交换机负责把广播发送到不同的对列(queues,队列名字不能相同),队列绑定指定交换机
3:不同的消费者在队列接收到消息
代码案例:生产者1个,消费者多个
生产者:
package com.thit.mq2;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.MessageProperties;
import com.thit.util.MqUtil;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author :huyiju
* @date :2020-05-28 19:03
* 直接发送对列
* 1对1 消费消息
*/
public class Producter2 {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection= MqUtil.getconnection();
//创建通道
Channel channel=connection.createChannel();
//创建交换机
//参数1:交换机名字
//参数2:交换机广播类型 固定值
channel.exchangeDeclare("exchange1","fanout");
//推送消息 消息设置持久化
//1:交换机名字
//2:路由key
//3:基础参数MessageProperties.PERSISTENT_TEXT_PLAIN,消息持久化
//4:发送消息
for (int i=0;i<20;i++){
channel.basicPublish("exchange1","", MessageProperties.PERSISTENT_TEXT_PLAIN,("第几次发送消息:"+i).getBytes());
}
//关闭通道
MqUtil.close(connection,channel);
System.out.println("发送消息结束");
}
}
消费者:
package com.thit.mq2;
import com.rabbitmq.client.*;
import com.thit.util.MqUtil;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* @author :huyiju
* @date :2020-05-28 19:03
* 直接发送对列
* 1对1 消费消息
*/
public class Customer3 {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection= MqUtil.getconnection();
//创建通道
Channel channel=connection.createChannel();
//创建交换机
//参数1:交换机名字
//参数2:交换机广播类型 固定值
channel.exchangeDeclare("exchange1","fanout");
//设置创建的queue状态
//参数1:队列名字
//参数2:队列的持久化 true持久化 false不持久化 重启会消失
//参数3:是否独占队列
//参数4:true 消费完删除对列
//参数5:传递的参数
channel.queueDeclare("c1",false,false,false,null);
// String aname= channel.queueDeclare().getQueue();
//绑定队列和交换机
//参数1:队列名字
//参数2:交换机名字
//参数3:路由key
channel.queueBind("c1","exchange1","");
//消费消息
//参数1:对垒名字
//参数2:ack确认 true的话,如果消费者代码出错,也会确认消费消息 消息会丢失
channel.basicConsume("c1",false,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
String a=new String(body);
System.out.println("111接收到的参数是:"+a);
//消费者1 报错,没有确认消息消费,消费者2 会重复消费1得到的消息
//int b=10/0;
//当确认参数是false的时候,手动确认
//1 channel.basicAck(envelope.getDeliveryTag(),false);
}
});
//关闭通道
//MqUtil.close(connection,channel);
System.out.println("接受消息结束");
}
}
package com.thit.mq2;
import com.rabbitmq.client.*;
import com.thit.util.MqUtil;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* @author :huyiju
* @date :2020-05-28 19:03
* 直接发送对列
* 1对1 消费消息
*/
public class Customer4 {
public static void main(String[] args) throws IOException, TimeoutException {
{
Connection connection= MqUtil.getconnection();
//创建通道
Channel channel=connection.createChannel();
//创建交换机
//参数1:交换机名字
//参数2:交换机广播类型 固定值
channel.exchangeDeclare("exchange1","fanout");
//设置创建的queue状态
//参数1:队列名字
//参数2:队列的持久化 true持久化 false不持久化 重启会消失
//参数3:是否独占队列
//参数4:true 消费完删除对列
//参数5:传递的参数
channel.queueDeclare("c2",false,false,false,null);
//绑定队列和交换机
//参数1:队列名字
//参数2:交换机名字
//参数3:路由key
channel.queueBind("c2","exchange1","");
//消费消息
//参数1:对垒名字
//参数2:ack确认 true的话,如果消费者代码出错,也会确认消费消息 消息会丢失
channel.basicConsume("c2",false,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
String a=new String(body);
// try {
// TimeUnit.SECONDS.sleep(2);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
System.out.println("111接收到的参数是:"+a);
//消费者1 报错,没有确认消息消费,消费者2 会重复消费1得到的消息
//int b=10/0;
//当确认参数是false的时候,手动确认
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
//关闭通道
//MqUtil.close(connection,channel);
System.out.println("接受消息结束");
}
}
}
4.4:Rooting路由模式
总结:类型是:Direct,每一个消费者都能接受到相同的消息,但是根据key路由
生产者:
package com.thit.mq3;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.MessageProperties;
import com.thit.util.MqUtil;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author :huyiju
* @date :2020-05-28 19:03
* 直接发送对列
* 1对1 消费消息
*/
public class Producter3 {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection= MqUtil.getconnection();
//创建通道
Channel channel=connection.createChannel();
//创建交换机
//参数1:交换机名字
//参数2:交换机广播类型 固定值direct 路由模式
channel.exchangeDeclare("exchange3","direct");
//自定义key的值
String key="demo";
//推送消息 消息设置持久化
//1:交换机名字
//2:路由key
//3:基础参数MessageProperties.PERSISTENT_TEXT_PLAIN,消息持久化
//4:发送消息
for (int i=0;i<1;i++){
channel.basicPublish("exchange3",key, MessageProperties.PERSISTENT_TEXT_PLAIN,
("路由key第几次发送消息:"+i+":key的值是:"+key).getBytes());
}
//关闭通道
MqUtil.close(connection,channel);
System.out.println("发送消息结束");
}
}
消费者:
package com.thit.mq3;
import com.rabbitmq.client.*;
import com.thit.util.MqUtil;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author :huyiju
* @date :2020-05-28 19:03
* 直接发送对列
* 1对1 消费消息
*/
public class Customer5 {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection= MqUtil.getconnection();
//创建通道
Channel channel=connection.createChannel();
//创建交换机
//参数1:交换机名字
//参数2:交换机广播类型 固定值
channel.exchangeDeclare("exchange3","direct");
//设置创建的queue状态
//参数1:队列名字
//参数2:队列的持久化 true持久化 false不持久化 重启会消失
//参数3:是否独占队列
//参数4:true 消费完删除对列
//参数5:传递的参数
//channel.queueDeclare("c5",false,false,false,null);
String aname= channel.queueDeclare().getQueue();
//绑定队列和交换机
//参数1:队列名字
//参数2:交换机名字
//参数3:路由key
channel.queueBind(aname,"exchange3","demo1");
channel.queueBind(aname,"exchange3","demo2");
channel.queueBind(aname,"exchange3","demo3");
//消费消息
//参数1:对垒名字
//参数2:ack确认 true的话,如果消费者代码出错,也会确认消费消息 消息会丢失
channel.basicConsume(aname,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
String a=new String(body);
System.out.println("111接收到的参数是:"+a);
// channel.basicAck(envelope.getDeliveryTag(),false);
}
});
//关闭通道
//MqUtil.close(connection,channel);
System.out.println("接受消息结束");
}
}
package com.thit.mq3;
import com.rabbitmq.client.*;
import com.thit.util.MqUtil;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author :huyiju
* @date :2020-05-28 19:03
* 直接发送对列
* 1对1 消费消息
*/
public class Customer6 {
public static void main(String[] args) throws IOException, TimeoutException {
{
Connection connection= MqUtil.getconnection();
//创建通道
Channel channel=connection.createChannel();
//创建交换机
//参数1:交换机名字
//参数2:交换机广播类型 固定值
channel.exchangeDeclare("exchange3","direct");
//设置创建的queue状态
//参数1:队列名字
//参数2:队列的持久化 true持久化 false不持久化 重启会消失
//参数3:是否独占队列
//参数4:true 消费完删除对列
//参数5:传递的参数
//channel.queueDeclare("c6",false,false,false,null);
String aname= channel.queueDeclare().getQueue();
//绑定队列和交换机
//参数1:队列名字
//参数2:交换机名字
//参数3:路由key
channel.queueBind(aname,"exchange3","demo3");
//消费消息
//参数1:对垒名字
//参数2:ack确认 true的话,如果消费者代码出错,也会确认消费消息 消息会丢失
channel.basicConsume(aname,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
String a=new String(body);
System.out.println("111接收到的参数是:"+a);
//channel.basicAck(envelope.getDeliveryTag(),false);
}
});
//关闭通道
//MqUtil.close(connection,channel);
System.out.println("接受消息结束");
}
}
}
4.5:Topics订阅模式
总结:类型是:Topic,每一个消费者都能接受到相同的消息,根据key的正则表达式路由
代码案例:
生产者:
package com.thit.mq4;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.MessageProperties;
import com.thit.util.MqUtil;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author :huyiju
* @date :2020-05-28 19:03
* 直接发送对列
* 1对1 消费消息
*/
public class Producter4 {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection= MqUtil.getconnection();
//创建通道
Channel channel=connection.createChannel();
//创建交换机
//参数1:交换机名字
//参数2:fanout 交换机广播类型 大家都接收到消息
//参数2:direct 路由模式 指定路由
//参数2:topic 动态路由模式 动态匹配路由
channel.exchangeDeclare("exchange4","topic");
//自定义key的值
String key="user.huyiju.test";
//推送消息 消息设置持久化
//1:交换机名字
//2:路由key
//3:基础参数MessageProperties.PERSISTENT_TEXT_PLAIN,消息持久化
//4:发送消息
for (int i=0;i<1;i++){
channel.basicPublish("exchange4",key, MessageProperties.PERSISTENT_TEXT_PLAIN,
("路由key第几次发送消息:"+i+":key的值是:"+key).getBytes());
}
//关闭通道
MqUtil.close(connection,channel);
System.out.println("发送消息结束");
}
}
消费者:
package com.thit.mq4;
import com.rabbitmq.client.*;
import com.thit.util.MqUtil;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author :huyiju
* @date :2020-05-28 19:03
* 直接发送对列
* 1对1 消费消息
*/
public class Customer7 {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection= MqUtil.getconnection();
//创建通道
Channel channel=connection.createChannel();
//创建交换机
//参数1:交换机名字
//参数2:交换机广播类型 固定值
channel.exchangeDeclare("exchange4","topic");
//设置创建的queue状态
//参数1:队列名字
//参数2:队列的持久化 true持久化 false不持久化 重启会消失
//参数3:是否独占队列
//参数4:true 消费完删除对列
//参数5:传递的参数
//channel.queueDeclare("c5",false,false,false,null);
String aname= channel.queueDeclare().getQueue();
//绑定队列和交换机
//参数1:队列名字
//参数2:交换机名字
//参数3:路由key
channel.queueBind(aname,"exchange4","user.*.#");
//消费消息
//参数1:对垒名字
//参数2:ack确认 true的话,如果消费者代码出错,也会确认消费消息 消息会丢失
channel.basicConsume(aname,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
String a=new String(body);
System.out.println("111接收到的参数是:"+a);
// channel.basicAck(envelope.getDeliveryTag(),false);
}
});
//关闭通道
//MqUtil.close(connection,channel);
System.out.println("接受消息结束");
}
}
package com.thit.mq4;
import com.rabbitmq.client.*;
import com.thit.util.MqUtil;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author :huyiju
* @date :2020-05-28 19:03
* 直接发送对列
* 1对1 消费消息
*/
public class Customer8 {
public static void main(String[] args) throws IOException, TimeoutException {
{
Connection connection= MqUtil.getconnection();
//创建通道
Channel channel=connection.createChannel();
//创建交换机
//参数1:交换机名字
//参数2:交换机广播类型 固定值
channel.exchangeDeclare("exchange4","topic");
//设置创建的queue状态
//参数1:队列名字
//参数2:队列的持久化 true持久化 false不持久化 重启会消失
//参数3:是否独占队列
//参数4:true 消费完删除对列
//参数5:传递的参数
//channel.queueDeclare("c6",false,false,false,null);
String aname= channel.queueDeclare().getQueue();
//绑定队列和交换机
//参数1:队列名字
//参数2:交换机名字
//参数3:路由key
channel.queueBind(aname,"exchange4","user.huyiju.#");
//消费消息
//参数1:对垒名字
//参数2:ack确认 true的话,如果消费者代码出错,也会确认消费消息 消息会丢失
channel.basicConsume(aname,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
String a=new String(body);
System.out.println("111接收到的参数是:"+a);
//channel.basicAck(envelope.getDeliveryTag(),false);
}
});
//关闭通道
//MqUtil.close(connection,channel);
System.out.println("接受消息结束");
}
}
}
4.6:总结
5:springboot整合rabbitmq
1:pom
<!--springboot的rabbit的mq-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2:代码案例
生产者:
//注入rabbitTemplate
@Autowired
RabbitTemplate RabbitTemplate;
/**
* 一对一
* 一对多
* 消费合集等于发送方
* 消费者轮流消费
* @param id
* @return
*/
public int mq1(int id) {
CorrelationData cData = new CorrelationData("huyiju001");
Users users = new Users();
users.setId(2);
users.setName("张三");
String message = JSON.toJSONString(users);
for (int a = 0; a < 1; a++) {
RabbitTemplate.convertAndSend("mq88", message + ":" + a);
}
return 0;
}
/**
* 广播模式
* @param id
* @return
* 多个接受者 接受相同的数据
*/
public int mq2(int id) {
Users users = new Users();
users.setId(1);
users.setName("李四");
String message = JSON.toJSONString(users);
for (int a = 0; a < 5; a++) {
//参数1:交换机名字
//参数2:路由key名字
//参数3:发送的消息
RabbitTemplate.setConfirmCallback(confirmCallback);
RabbitTemplate.setReturnCallback(returnCallback);
RabbitTemplate.convertAndSend("hexchange1",null,message + ":" + a);
}
return 0;
}
/**
* 广播模式
* @param id
* @return
* 多个接受者 根据key接受数据
*/
public int mq3(int id) {
Users users = new Users();
users.setId(5);
users.setName("天天");
String message = JSON.toJSONString(users);
for (int a = 0; a < 4; a++) {
//参数1:交换机名字
//参数2:路由key名字
//参数3:发送的消息
RabbitTemplate.convertAndSend("hexchange4","user.test",message + ":" + a);
}
return 0;
}
消费者队列模式:多个消费者不能重复消费,两个消费者
package com.thit.springbootmq1;//package com.thit.SpringBootMq;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
@RabbitListener(queuesToDeclare = @Queue("mq88")) //消费者注解 没有创建
//@RabbitListener(queues = "mq2") //没有对列 会报错 需要初始化创建
public class SCustomer1 {
@RabbitHandler
public void receive(Message message1, Channel channel, String meaage) throws IOException {
try {
System.out.println("1接收消息次数");
String json = new String(message1.getBody());
System.out.println("11接收到的消息是:"+meaage);
System.out.println("11接收到的消息是:"+json);
int a=10/0;
//1:模拟数据库操作,此可能执行失败,需要将消费的消息重新放回队列
//2:当确认参数是false的时候,手动确认,没有出错,手动删除消息哦
channel.basicAck(message1.getMessageProperties().getDeliveryTag(),false);
}catch (Exception e){
System.out.println("1消息接收方程序出错~,需要将消息返回给队列:");
// 1:处理消息失败,将消息重新放回队列
channel.basicNack(message1.getMessageProperties().getDeliveryTag(), false,true);
//2:或者将失败的消息插入消费者的数据库,落地处理
//insertDb(meaage);
}
}
}
package com.thit.springbootmq1;//package com.thit.SpringBootMq;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
@RabbitListener(queuesToDeclare = @Queue("mq88")) //消费者注解 没有创建
//@RabbitListener(queues = "mq2") //没有对列 会报错 需要初始化创建
public class SCustomer2 {
@RabbitHandler
public void receive(Message message1, Channel channel, String meaage) throws IOException {
try {
System.out.println("2接收消息次数");
String json = new String(message1.getBody());
System.out.println("22接收到的消息是:"+meaage);
//int a=10/0;
//1:模拟数据库操作,此可能执行失败,需要将消费的消息重新放回队列
//2:当确认参数是false的时候,手动确认,没有出错,手动删除消息哦
channel.basicAck(message1.getMessageProperties().getDeliveryTag(),false);
}catch (Exception e){
System.out.println("2消息接收方程序出错~,需要将消息返回给队列:");
// 1:处理消息失败,将消息重新放回队列
channel.basicNack(message1.getMessageProperties().getDeliveryTag(), false,true);
//2:或者将失败的消息插入消费者的数据库,落地处理
//insertDb(meaage);
}
}
}
消费者广播模式:多个消息者重复得到相同的数据,两个消费者
package com.thit.springbootmq;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class SCustomer3 {
//type = "topic" 根据key正则表达式
//type = "direct" 根据key
// type = "fanout" 扇区 都会接受
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,//临时对列
exchange = @Exchange(value = "hexchange4",
type = "topic" ),//type = "topic" 根据key正则表达式
key = {"user.test"}
)
})
public void listerQueue1(String message){
System.out.println("消费者1:" + message);
System.out.println("======================");
}
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,//临时对列
exchange = @Exchange(value = "hexchange4",type = "topic"),
key = {"user.#"}
)
})
public void listerQueue2(String message)
{
System.out.println("消费者2:" + message);
}
}
6:springboot整合rabbitmq分布式事务
6.1:消息发送方
操作数据库,发送数据到mq,如果数据库事务失败,不发送数据,事务成功,发送数据到mq,如果发送mq失败,需要有临时流水表,定时任务,重新发送,知道数据发送到mq。
6.2:消息接收方
消息接收到数据,入库,如是事务提交成功,则确认消息消费。如果事务入库失败。则不要确认消息,等待在此消费。或者将消息插入数据库,返回消息接受成功,后续的插入数据库的消息在进行处理。