介绍
rabbitMQ是基于AMQP协议的消息队列,erlang语言实现。引用官网如下:
RabbitMQ is a message broker: it accepts and forwards messages. You can think about it as a post office: when you put the mail that you want posting in a post box, you can be sure that Mr. or Ms. Mailperson will eventually deliver the mail to your recipient. In this analogy, RabbitMQ is a post box, a post office and a postman.
说白了,就是一个生产者、中间件和消费者的关系,发送者只负责生产消息,rabbitMQ作为中间件负责接收消息,缓存消息,发送消息。而消费者只负责从中间件获取消息。
本次helloworld示例模型如下:
下面用java方式实现。
首先导入maven:
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.8.0</version>
</dependency>
生产者实现
之后编写生产者:
创建步骤:
step1:通过连接工厂ConnnectionFactory创立连接Connection
step2:创立通道Channel
step3:申明队列
step4:发送消息
step5:先关闭Channel,再关闭Connection。
代码入下:
public class Producer01 {
private static final String QUEUENAME = "hello-world";
public static void main(String[] args) throws IOException, TimeoutException {
//通过连接工厂创建新的连接和mq建立连接
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//设置虚拟机,一个mq的服务可以设置多个虚拟机,每个虚拟机相当于一个独立的mq。
connectionFactory.setVirtualHost("/");
//建立新连接
Connection connection = null;
connection = connectionFactory.newConnection();
//创建会话通道,生产者和mq服务所有的通信都在channel里完成。
Channel channel = connection.createChannel();
//声明队列:如果队列在mq中没有,则创建
//参数String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
/**
* 参数明细:
* queue:队列名称
* durable:持久化,如果持久化,重启mq服务队列还在
* exclusive:是否独占连接,队列只允许在该连接中访问,如果连接关闭则队列删除,设置为true,可用于临时队列。
* autoDelete:自动删除,设置为true,连接不使用则删除队列
* arguments:指定一些扩展参数。例如存活时间等等
*/
channel.queueDeclare(QUEUENAME,true,false,false,null);
//发送消息
//参数:String exchange, String routingKey, BasicProperties props, byte[] body
/**
* 参数明细:
* exchange:交换机,不指定的话为默认交换机
* routingKey:交换机根据路由key,将消息转发到指定队列,如果使用默认交换机,routingKey设置为队列的名称
* props:消息的属性
* body:消息内容,字节数组形式
*/
channel.basicPublish("",QUEUENAME,null,"hello,world!请多指教".getBytes());
System.out.println("send to mq");
//关闭通道
channel.close();
//关闭连接
connection.close();
}
}
至此创建生产者成功,同时也创建了名为hello-world的消息队列,之后的消费者若要取出信息,就要到同名的队列中取出。
消费者实现
消费者的实现方式和生产者类似,仅仅将发送消息替换成监听队列即可。代码如下:
public class Consumer01 {
private static final String QUEUENAME = "hello-world";
public static void main(String[] args) throws IOException, TimeoutException {
//通过连接工厂创建新的连接和mq建立连接
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//设置虚拟机,一个mq的服务可以设置多个虚拟机,每个mq相当于一个独立的mq。
connectionFactory.setVirtualHost("/");
//建立新连接
Connection connection = null;
connection = connectionFactory.newConnection();
//创建会话通道,生产者和mq服务所有的通信都在channel里完成。
Channel channel = connection.createChannel();
//声明队列:如果队列在mq中没有,则创建
channel.queueDeclare(QUEUENAME,true,false,false,null);
//实现消费方法
DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
/**
* 当接收到消息后,此方法执行
* @param consumerTag 消费者标签,用来标识消费者,在监听队列时也可设置channel.basicConsume
* @param envelope 信封,可用信封获取一些信息,例如交换机、消息id等
* @param properties 消息属性,发送消息时设置的消息属性可在这里获取
* @param body 消息内容
* @throws IOException
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
//super.handleDelivery(consumerTag, envelope, properties, body);
//拿到交换机
String exchange = envelope.getExchange();
//消息id,mq在channel中用来表示消息的id,可用于确认消息已接收。
long deliveryTag = envelope.getDeliveryTag();
String message = new String(body,"UTF-8");
System.out.println("交换机:"+exchange+" 消息id"+deliveryTag+" 消息内容"+message);
}
};
//监听队列
//参数 String queue, boolean autoAck, Consumer callback
/**
* 参数明细:
* queue:队列名称
* autoAck:自动回复,消费者接受到消息会自动告诉mq服务消息已接收此参数设置为true
* 会自动回复mq,如果设置为false要通过编程回复,不回复的话消息一直在队列里。
* callback:回调方法,当消费者接收到消息要执行的方法。
*/
channel.basicConsume(QUEUENAME,true,defaultConsumer);
}
}