(一)RabbitMQ的使用教程
RabbitMQ的官網提供了RabbitMQ的六種創建消息傳遞應用程序的方式https://www.rabbitmq.com/getstarted.html
分別是簡單隊列、工作隊列、Publish/Subscribe訂閱模式、routing路由模式、Topics主題模式和RPC,首先介紹簡單隊列。maven項目依賴如下:
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>4.0.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.28</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
(二)Rabbit的簡單隊列
簡單隊列主要由三大結構組成:
簡單隊列即生產者將消息發送到隊列中,當消費者要用的時候直接在隊列中取即可。通過實際操作來模擬簡單隊列的運行流程
2.1 新建工具類
public class ConnectionUtil {
public static Connection getConnection() throws IOException, TimeoutException {
//定義一個連接工廠
ConnectionFactory factory=new ConnectionFactory();
//設置服務地址
factory.setHost("127.0.0.1");
//設置AMQP端口
factory.setPort(5672);
//設置VHOSTS
factory.setVirtualHost("/vhosts_sdxb");
//設置用戶名
factory.setUsername("user_sdxb");
factory.setPassword("123456");
return factory.newConnection();
}
}
需要注意的是連接工廠中設置的端口不是rabbitmq可視化界面的端口,而是AMQP協議的端口,這個端口號可在rabbitmq的可視化界面中查看到:
2.2 創建生產者
public class Send {
private static final String QUEUE_NAME="simple_queue";
public static void main(String[] args) throws IOException, TimeoutException {
//獲取一個連接
Connection connection = ConnectionUtil.getConnection();
//從連接中獲取一個通道
Channel channel = connection.createChannel();
//創建隊列聲明
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
String msg="Hello rabbitmq";
//發佈隊列
channel.basicPublish("",QUEUE_NAME,null,msg.getBytes());
channel.close();
connection.close();
}
}
這段代碼創建了一個名爲simple_queue的隊列,並且發佈了一條msg到隊列中,可在rabbitmq的可視化界面看到詳情:
標記1處表示隊列的名稱,標記2處代表此時隊列中的消息數。
channel.queueDeclare(String queue , boolean durable , boolean exclusive , boolean autoDelete , Map arguments);
queue:隊列名稱
durable:是否設置持久化,隊列中的消息是存放在內存中的,理論上如果隊列掛掉消息也就消失了,
因此持久化參數可以讓隊列消息持久化到硬盤
exclusive:設置是否排他,即如果一個隊列被聲明爲排他隊列,該隊列僅對首次聲明它的連接可見
autoDelete:設置是否自動刪除,爲true則設置隊列爲自動刪除
arguments:設置隊列的其他一些參數
channel.basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
exchange:交換器名稱
routingKey:路由鍵
props:有14個應用程序標識號 - 生成消息的應用程序標識符
body:真正要發送的消息
2.3 創建消費者
public class Receive {
private static final String QUEUE_NAME = "simple_queue";
public static void main(String[] args) throws IOException, TimeoutException {
//獲取一個連接
Connection connection = ConnectionUtil.getConnection();
//從連接中獲取一個通道
Channel channel = connection.createChannel();
//創建隊列聲明
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
//創建消費者監聽方法
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String msg = new String(body, "utf-8");
System.out.println("receive:" + msg);
}
};
//監聽隊列
channel.basicConsume(QUEUE_NAME, true, consumer);
}
}
通過重寫DefaultConsumer的handleDelivery方法來獲取隊列中的消息,並通過channel.basicConsume來監聽隊列,一旦隊列中有消息存在就取出。
(三)簡單隊列的不足
簡單隊列耦合性高,一個消費者對應於一個生產者,無法處理多個消費者同時調用消息隊列的情況。