RabbitMQ 入門指南(Java)

RabbitMQ是一個受歡迎的消息代理,通常用於應用程序之間或者程序的不同組件之間通過消息來進行集成。本文簡單介紹瞭如何使用 RabbitMQ,假定你已經配置好了rabbitmq服務器。

RabbitMQ是用Erlang,對於主要的編程語言都有驅動或者客戶端。我們這裏要用的是Java,所以先要獲得Java客戶端。。下面是Java客戶端的maven依賴的配置。

1 <dependency>
2         <groupId>com.rabbitmq</groupId>
3         <artifactId>amqp-client</artifactId>
4         <version>3.0.4</version>
5 </dependency>

像RabbitMQ這樣的消息代理可用來模擬不同的場景,例如點對點的消息分發或者訂閱/推送。我們的程序足夠簡單,有兩個基本的組件,一個生產者用於產生消息,還有一個消費者用來使用產生的消息。

在這個例子裏,生產者會產生大量的消息,每個消息帶有一個序列號,另一個線程中的消費者會使用這些消息。

抽象類EndPoint:

我們首先寫一個類,將產生產者和消費者統一爲 EndPoint類型的隊列。不管是生產者還是消費者, 連接隊列的代碼都是一樣的,這樣可以通用一些。

01 package co.syntx.examples.rabbitmq;
02  
03 import java.io.IOException;
04  
05 import com.rabbitmq.client.Channel;
06 import com.rabbitmq.client.Connection;
07 import com.rabbitmq.client.ConnectionFactory;
08  
09 /**
10  * Represents a connection with a queue
11  * @author syntx
12  *
13  */
14 public abstract class EndPoint{
15      
16     protected Channel channel;
17     protected Connection connection;
18     protected String endPointName;
19      
20     public EndPoint(String endpointName) throws IOException{
21          this.endPointName = endpointName;
22          
23          //Create a connection factory
24          ConnectionFactory factory = new ConnectionFactory();
25          
26          //hostname of your rabbitmq server
27          factory.setHost("localhost");
28          
29          //getting a connection
30          connection = factory.newConnection();
31          
32          //creating a channel
33          channel = connection.createChannel();
34          
35          //declaring a queue for this channel. If queue does not exist,
36          //it will be created on the server.
37          channel.queueDeclare(endpointName, falsefalsefalse,null);
38     }
39      
40      
41     /**
42      * 關閉channel和connection。並非必須,因爲隱含是自動調用的。
43      * @throws IOException
44      */
45      public void close() throws IOException{
46          this.channel.close();
47          this.connection.close();
48      }
49 }

生產者:

生產者類的任務是向隊列裏寫一條消息。我們使用Apache Commons Lang把可序列化的Java對象轉換成 byte 數組。commons lang的maven依賴如下:

<dependency>
	<groupId>commons-lang</groupId>
	<artifactId>commons-lang</artifactId>
	<version>2.6</version>
</dependency>
01 package co.syntx.examples.rabbitmq;
02  
03 import java.io.IOException;
04 import java.io.Serializable;
05  
06 import org.apache.commons.lang.SerializationUtils;
07  
08  
09 /**
10  * The producer endpoint that writes to the queue.
11  * @author syntx
12  *
13  */
14 public class Producer extends EndPoint{
15      
16     public Producer(String endPointName) throws IOException{
17         super(endPointName);
18     }
19  
20     public void sendMessage(Serializable object) throws IOException {
21         channel.basicPublish("",endPointName, null, SerializationUtils.serialize(object));
22     }  
23 }

消費者:

消費者可以以線程方式運行,對於不同的事件有不同的回調函數,其中最主要的是處理新消息到來的事件。

01 package co.syntx.examples.rabbitmq;
02  
03 import java.io.IOException;
04 import java.util.HashMap;
05 import java.util.Map;
06  
07 import org.apache.commons.lang.SerializationUtils;
08  
09 import com.rabbitmq.client.AMQP.BasicProperties;
10 import com.rabbitmq.client.Consumer;
11 import com.rabbitmq.client.Envelope;
12 import com.rabbitmq.client.ShutdownSignalException;
13  
14  
15 /**
16  * 讀取隊列的程序端,實現了Runnable接口。
17  * @author syntx
18  *
19  */
20 public class QueueConsumer extends EndPoint implements Runnable, Consumer{
21      
22     public QueueConsumer(String endPointName) throws IOException{
23         super(endPointName);       
24     }
25      
26     public void run() {
27         try {
28             //start consuming messages. Auto acknowledge messages.
29             channel.basicConsume(endPointName, true,this);
30         catch (IOException e) {
31             e.printStackTrace();
32         }
33     }
34  
35     /**
36      * Called when consumer is registered.
37      */
38     public void handleConsumeOk(String consumerTag) {
39         System.out.println("Consumer "+consumerTag +" registered");    
40     }
41  
42     /**
43      * Called when new message is available.
44      */
45     public void handleDelivery(String consumerTag, Envelope env,
46             BasicProperties props, byte[] body) throws IOException {
47         Map map = (HashMap)SerializationUtils.deserialize(body);
48         System.out.println("Message Number "+ map.get("message number") + " received.");
49          
50     }
51  
52     public void handleCancel(String consumerTag) {}
53     public void handleCancelOk(String consumerTag) {}
54     public void handleRecoverOk(String consumerTag) {}
55     public void handleShutdownSignal(String consumerTag, ShutdownSignalException arg1) {}
56 }

Putting it together:

在下面的測試類中,先運行一個消費者線程,然後開始產生大量的消息,這些消息會被消費者取走。

01 package co.syntx.examples.rabbitmq;
02  
03 import java.io.IOException;
04 import java.sql.SQLException;
05 import java.util.HashMap;
06  
07 public class Main {
08     public Main() throws Exception{
09          
10         QueueConsumer consumer = new QueueConsumer("queue");
11         Thread consumerThread = new Thread(consumer);
12         consumerThread.start();
13          
14         Producer producer = new Producer("queue");
15          
16         for (int i = 0; i < 100000; i++) {
17             HashMap message = new HashMap();
18             message.put("message number", i);
19             producer.sendMessage(message);
20             System.out.println("Message Number "+ i +" sent.");
21         }
22     }
23      
24     /**
25      * @param args
26      * @throws SQLException
27      * @throws IOException
28      */
29     public static void main(String[] args) throws Exception{
30       new Main();
31     }
32 }
轉自:http://www.oschina.net/translate/getting-started-with-rabbitmq-in-java?cmp
發佈了10 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章