由于目前编写的代码无法给我们自动创建用户和虚拟机,所以需要我们自己先手动创建一下用户和虚拟机。
创建用户
用户创建成功如下图所示
创建完虚拟机之后,发现虚拟机还没有指定的用户,给它添加用户
添加用户
用户和虚拟机绑定成功之后如下图所示:
这是一个常量类,定义着队列的名称
public class RabbitConstant {
public static final String QUEUE_HELLO_WORLD = "QUEUE_HELLO_WORLD";
public static final String QUEUE_SMS = "QUEUE_SMS";
public static final String QUEUE_EXCHANGE_WEATHER = "QUEUE_EXCHANGE_WEATHER";
public static final String QUEUE_EXCHANGE_WEATHER_ROUTING = "QUEUE_EXCHANGE_WEATHER_ROUTING";
public static final String QUEUE_BAI_DU = "QUEUE_BAI_DU";
public static final String QUEUE_SIN_LANG = "QUEUE_SIN_LANG";
public static final String QUEUE_EXCHANGE_WEATHER_TOPIC = "QUEUE_EXCHANGE_WEATHER_TOPIC";
}
public class RabbitUtils {
private static ConnectionFactory connectionFactory = new ConnectionFactory();
static {
// 连接rabbitmq的ip地址
connectionFactory.setHost("192.168.231.132");
// 5672是RabbitMQ的默认端口号
connectionFactory.setPort(5672);
// 连接rabbitmq中的那一个用户 用户名名称
connectionFactory.setUsername("ale");
// 连接rabbitmq中的那一个用户 用户名密码
connectionFactory.setPassword("ale123");
// 使用rabbit的时候需要连接一个虚拟机,虚拟机里面存放的是交换机以及队列
// 对于不同的租户同一个rabbitmq提供的交换机或者队列都是独立的(也就是不同的虚拟机)
connectionFactory.setVirtualHost("ale_virtual");
}
public static Connection getConnection() throws IOException, TimeoutException {
Connection conn = null;
conn = connectionFactory.newConnection();
return conn;
}
}
<dependency>
<groupId>com.rabbitmqgroupId>
<artifactId>amqp-clientartifactId>
<version>5.3.0version>
dependency>
<dependency>
<groupId>com.google.code.gsongroupId>
<artifactId>gsonartifactId>
<version>2.8.5version>
dependency>
简单模式呢,就是一个生产者一个消费者,生产者生产出消息放到队列中,然后消费者去队列里面拿,如下图所示:
public class Consumer {
public static void main(String[] args) throws IOException, TimeoutException {
// 获取TCP长连接
Connection conn = RabbitUtils.getConnection();
// 创建通信“通道”,相当于TCP中的虚拟连接
Channel channel = conn.createChannel();
// 创建队列,声明并创建一个队列,如果队列已存在,则使用这个队列
// 第一个参数:队列名称ID
// 第二个参数:是否持久化,false对应不持久化数据,MQ停掉数据就会丢失
// 第三个参数:是否队列私有化,false则代表所有消费者都可以访问,true代表只有第一次拥有它的消费者才能一直使用,其他消费者不让访问
// 第四个:是否自动删除,false代表连接停掉后不自动删除掉这个队列
// 其他额外的参数, null
channel.queueDeclare(RabbitConstant.QUEUE_HELLO_WORLD,false, false, false, null);
// 从MQ服务器中获取数据
// 创建一个消息消费者
// 第一个参数:队列名
// 第二个参数代表是否自动确认收到消息,false代表手动编程来确认消息,这是MQ的推荐做法
// 第三个参数要传入DefaultConsumer的实现类
channel.basicConsume(RabbitConstant.QUEUE_HELLO_WORLD, false, new Reciver(channel));
}
}
class Reciver extends DefaultConsumer {
private Channel channel;
//重写构造函数,Channel通道对象需要从外层传入,在handleDelivery中要用到
public Reciver(Channel channel) {
super(channel);
this.channel = channel;
}
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body);
System.out.println("消费者接收到的消息:"+message);
System.out.println("消息的TagId:"+envelope.getDeliveryTag());
// false只确认签收当前的消息,设置为true的时候则代表签收该消费者所有未签收的消息
channel.basicAck(envelope.getDeliveryTag(), false);
}
}
public class Producer {
public static void main(String[] args) throws IOException, TimeoutException {
//获取TCP长连接
Connection conn = RabbitUtils.getConnection();
//创建通信“通道”,相当于TCP中的虚拟连接
Channel channel = conn.createChannel();
//创建队列,声明并创建一个队列,如果队列已存在,则使用这个队列
//第一个参数:队列名称ID
//第二个参数:是否持久化,false对应不持久化数据,MQ停掉数据就会丢失
//第三个参数:是否队列私有化,false则代表所有消费者都可以访问,true代表只有第一次拥有它的消费者才能一直使用,其他消费者不让访问
//第四个:是否自动删除,false代表连接停掉后不自动删除掉这个队列,true代表连接停掉后自动删除这个队列
//其他额外的参数, null
channel.queueDeclare(RabbitConstant.QUEUE_HELLO_WORLD,false, false, false, null);
String message = "Ale,Hello World";
// 四个参数
// exchange 交换机,暂时用不到,在后面进行发布订阅时才会用到,简单模式会使用默认的交换机
// 队列名称,这里在程序运行后,队列会自己创建
// 额外的设置属性
// 最后一个参数是要传递的消息字节数组
channel.basicPublish("", RabbitConstant.QUEUE_HELLO_WORLD, null,message.getBytes());
// 这里关闭连接的意思是我们不关心消息是否能发送到,只需要发送成功就行
channel.close();
conn.close();
System.out.println("===发送成功===");
}
}
先运行消费者,再运行生产者
生产者会在控制台输出消费成功,如下图所示:
消费者会在控制台输出,打印出生产者生产的消息,如下图所示:
工作队列的模式就是一个生产者多个消费者,这里我们模仿乘客买票下订单,订单系统需要往一个队列里面放很多条短信,然后多个消费者去队列里面轮询去拿,如下图所示:
这里定义了三个消费者:
消费者1
public class SMSSender1 {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = RabbitUtils.getConnection();
final Channel channel = connection.createChannel();
channel.queueDeclare(RabbitConstant.QUEUE_SMS, false, false, false, null);
//如果不写basicQos(1),则自动MQ会将所有请求平均发送给所有消费者
//basicQos,MQ不再对消费者一次发送多个请求,而是消费者处理完一个消息后(确认后),在从队列中获取一个新的
//处理完一个再取下一个
channel.basicQos(1);
channel.basicConsume(RabbitConstant.QUEUE_SMS , false , new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String jsonSMS = new String(body);
System.out.println("SMSSender1-短信发送成功:" + jsonSMS);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
channel.basicAck(envelope.getDeliveryTag() , false);
}
});
}
}
消费者2
public class SMSSender2 {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = RabbitUtils.getConnection();
final Channel channel = connection.createChannel();
channel.queueDeclare(RabbitConstant.QUEUE_SMS, false, false, false, null);
//如果不写basicQos(1),则自动MQ会将所有请求平均发送给所有消费者
//basicQos,MQ不再对消费者一次发送多个请求,而是消费者处理完一个消息后(确认后),在从队列中获取一个新的
//处理完一个再取下一个
channel.basicQos(1);
channel.basicConsume(RabbitConstant.QUEUE_SMS , false , new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String jsonSMS = new String(body);
System.out.println("SMSSender2-短信发送成功:" + jsonSMS);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
channel.basicAck(envelope.getDeliveryTag() , false);
}
});
}
}
消费者3
public class SMSSender3 {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = RabbitUtils.getConnection();
final Channel channel = connection.createChannel();
channel.queueDeclare(RabbitConstant.QUEUE_SMS, false, false, false, null);
//如果不写basicQos(1),则自动MQ会将所有请求平均发送给所有消费者
//basicQos,MQ不再对消费者一次发送多个请求,而是消费者处理完一个消息后(确认后),在从队列中获取一个新的
//处理完一个再取下一个
channel.basicQos(1);
channel.basicConsume(RabbitConstant.QUEUE_SMS , false , new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String jsonSMS = new String(body);
System.out.println("SMSSender3-短信发送成功:" + jsonSMS);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
channel.basicAck(envelope.getDeliveryTag() , false);
}
});
}
}
public class OrderSystem {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = RabbitUtils.getConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(RabbitConstant.QUEUE_SMS, false, false, false, null);
for(int i = 1 ; i <= 100 ; i++) {
SMS sms = new SMS("乘客" + i, "13900000" + i, "您的车票已预订成功");
String jsonSMS = new Gson().toJson(sms);
channel.basicPublish("" , RabbitConstant.QUEUE_SMS , null , jsonSMS.getBytes());
}
System.out.println("发送数据成功");
channel.close();
connection.close();
}
}
public class SMS {
private String name;
private String mobile;
private String content;
public SMS(String name, String mobile, String content) {
this.name = name;
this.mobile = mobile;
this.content = content;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
本来工作队列模式的默认是三个消费者轮询去取数据的,但是我上面的代码里加了如下一行代码,这行代码的意思就是,我消费完成一条消息之后再去取下一条,然后运行的结果就如下所示:
// 处理完一个再取下一个
channel.basicQos(1);
生产者截图:
消费者运行截图
消费者1
消费者2
消费者3