RabbitMQ 入门指南(Java)

RabbitMQ是一个受欢迎的消息代理,通常用于应用程序之间或者程序的不同组件之间通过消息来进行集成。本文简单介绍了如何使用 RabbitMQ,假定你已经配置好了rabbitmq服务器。

RabbitMQ是用Erlang,对于主要的编程语言都有驱动或者客户端。我们这里要用的是Java,所以先要获得Java客户端。。下面是Java客户端的maven依赖的配置。

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

像RabbitMQ这样的消息代理可用来模拟不同的场景,例如点对点的消息分发或者订阅/推送。我们的程序足够简单,有两个基本的组件,一个生产者用于产生消息,还有一个消费者用来使用产生的消息。

在这个例子里,生产者会产生大量的消息,每个消息带有一个序列号,另一个线程中的消费者会使用这些消息。

 

抽象类EndPoint:

我们首先写一个类,将产生产者和消费者统一为 EndPoint类型的队列。不管是生产者还是消费者, 连接队列的代码都是一样的,这样可以通用一些。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package co.syntx.examples.rabbitmq;
 
import java.io.IOException;
 
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
 
/**
  * Represents a connection with a queue
  * @author syntx
  *
  */
public abstract class EndPoint{
     
     protected Channel channel;
     protected Connection connection;
     protected String endPointName;
     
     public EndPoint(String endpointName)  throws IOException{
          this .endPointName = endpointName;
         
          //Create a connection factory
          ConnectionFactory factory =  new ConnectionFactory();
         
          //hostname of your rabbitmq server
          factory.setHost( "localhost" );
         
          //getting a connection
          connection = factory.newConnection();
         
          //creating a channel
          channel = connection.createChannel();
         
          //declaring a queue for this channel. If queue does not exist,
          //it will be created on the server.
          channel.queueDeclare(endpointName,  false false false null );
     }
     
     
     /**
      * 关闭channel和connection。并非必须,因为隐含是自动调用的。
      * @throws IOException
      */
      public void close()  throws IOException{
          this .channel.close();
          this .connection.close();
      }
}
 

生产者:

生产者类的任务是向队列里写一条消息。我们使用Apache Commons Lang把可序列化的Java对象转换成 byte 数组。commons lang的maven依赖如下:

<dependency>
	<groupId>commons-lang</groupId>
	<artifactId>commons-lang</artifactId>
	<version>2.6</version>
</dependency>
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package co.syntx.examples.rabbitmq;
 
import java.io.IOException;
import java.io.Serializable;
 
import org.apache.commons.lang.SerializationUtils;
 
 
/**
  * The producer endpoint that writes to the queue.
  * @author syntx
  *
  */
public class Producer  extends EndPoint{
     
     public Producer(String endPointName)  throws IOException{
         super (endPointName);
     }
 
     public void sendMessage(Serializable object)  throws IOException {
         channel.basicPublish( "" ,endPointName,  null , SerializationUtils.serialize(object));
     }  
}


消费者:

消费者可以以线程方式运行,对于不同的事件有不同的回调函数,其中最主要的是处理新消息到来的事件。

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


Putting it together:

在下面的测试类中,先运行一个消费者线程,然后开始产生大量的消息,这些消息会被消费者取走。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package co.syntx.examples.rabbitmq;
 
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;
 
public class Main {
     public Main()  throws Exception{
         
         QueueConsumer consumer =  new QueueConsumer( "queue" );
         Thread consumerThread =  new Thread(consumer);
         consumerThread.start();
         
         Producer producer =  new Producer( "queue" );
         
         for ( int i =  0 ; i <  100000 ; i++) {
             HashMap message =  new HashMap();
             message.put( "message number" , i);
             producer.sendMessage(message);
             System.out.println( "Message Number " + i + " sent." );
         }
     }
     
     /**
      * @param args
      * @throws SQLException
      * @throws IOException
      */
     public static void main(String[] args)  throws Exception{
       new Main();
     }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值