├── README.MD
├── pom.xml
└── src
├── main
└── java
│ └── org
│ └── cs
│ └── basic
│ └── mq
│ ├── consumer
│ ├── EventProcesser.java
│ ├── EventProcesserRPC.java
│ └── EventProcesserTopic.java
│ ├── global
│ ├── CodecFactory.java
│ ├── DefaultEventController.java
│ ├── EventControlConfig.java
│ ├── EventController.java
│ ├── EventMessage.java
│ ├── HessionCodecFactory.java
│ ├── MessageAdapterHandler.java
│ └── MessageErrorHandler.java
│ ├── producer
│ ├── DefaultEventTemplate.java
│ └── EventTemplate.java
│ ├── rpc
│ ├── RPCClient.java
│ ├── RPCServer.java
│ └── RPCServerListener.java
│ ├── topic
│ ├── TopicConsumer.java
│ └── TopicProducter.java
│ └── util
│ ├── ConnectionUtil.java
│ └── ObjectAndByte.java
└── test
├── java
└── org
│ └── cs
│ └── basic
│ └── mq
│ └── test
│ ├── People.java
│ ├── RabbitMqMessageTest.java
│ └── RabbitMqTest.java
└── resources
└── log4j.properties
/README.MD:
--------------------------------------------------------------------------------
1 | ## Basic-mq
2 | ### 说明:
3 | 本项目是对spring-amqp 进行的封装,可以直接打包成jar,加入到自己项目中,然后在自己项目中配置响应依赖就可以。
4 |
5 |
6 | ### 项目结构
7 |
8 |
9 |
10 | --org.cs.basic.mq
11 | --consumer
12 | --global
13 | --producer
14 | --rpc
15 | --topic
16 | --util --工具类 连接工具类,对象和byte转换工具类
17 | --test
18 | --org.cs.basic.test
19 | --resources
20 |
21 |
22 |
23 |
24 | ### 使用方法
25 | 1:编译项目打包成jar,加入到自己项目中
26 | 2:在项目中加入依赖
27 |
28 |
29 |
30 | com.rabbitmq
31 | amqp-client
32 | 3.2.4
33 |
34 |
35 | org.springframework.amqp
36 | spring-amqp
37 | 1.3.4.RELEASE
38 |
39 |
40 | org.springframework.amqp
41 | spring-rabbit
42 | 1.3.4.RELEASE
43 |
44 |
45 | com.caucho
46 | hessian
47 | 4.0.7
48 |
49 |
50 |
51 |
52 | 3:初始化配置
53 |
54 | EventControlConfig config2 = new EventControlConfig("192.168.0.19","admin","admin",1,1);
55 |
56 | 4:初始化链接
57 |
58 | DefaultEventController controller = DefaultEventController.getInstance(config2);
59 |
60 |
61 | 5:发送消息
62 | 需要先获得发送模板对象
63 |
64 | EventTemplate eventTemplate=controller.getEopEventTemplate();
65 | eventTemplate.send("Q_T_Message_Expiration", defaultExchange, "hello world!", 8000, 0);
66 |
67 |
68 | 6:消费消息
69 | 在消费端同样要执行第一步和第二步
70 | 还需要添加监听队列,启动监听
71 |
72 | controller.add("Q_T_Message_Expiration", defaultExchange,new MessagePriority());
73 | controller.start();
74 |
75 |
76 |
77 | class MessagePriority implements EventProcesser{
78 | public void process(Object e) {
79 | try {
80 | Thread.sleep(1000);
81 | System.out.println(e);
82 | } catch (InterruptedException e1) {
83 | e1.printStackTrace();
84 | }
85 |
86 | }
87 |
88 | }
89 |
90 |
91 | ### 配置
92 | ### config配置
93 | - public EventControlConfig(String serverHost)
94 | - public EventControlConfig(String serverHost,String username,String password)
95 | - public EventControlConfig(String serverHost,int port,String username,String password)
96 | - public EventControlConfig(String serverHost,String username,String password,int processThreadNum,int prefetchSize)
97 | - public EventControlConfig(String serverHost,String username,String password,int prefetchSize)
98 |
99 | > 当然自己可以在EventControlConfig.java中配置
100 |
101 |
102 | #### 发送模式
103 |
104 | - void send(String queueName,String exchangeName,Object eventContent)
105 | - Object sendAndReceive(String queueName,String exchangeName,Object eventContent)
106 | - void send(String queueName,String exchangeName,String routing,Object eventContent)
107 | - void send(String queueName,String exchangeName,String consumerQueueName,String consumerExchange,String routing,Object eventContent)
108 | - void send(String queueName,String exchangeName,String consumerQueueName,String consumerExchange,String routing,Object eventContent,int expiration,int priority)
109 | - void send(String queueName, String exchangeName, Object eventContent,int expiration,int priority)
110 | - void send(String queueName, String exchangeName, String routing,Object eventContent,int expiration,int priority)
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | org.cs.basic
6 | basic-mq
7 | 0.0.4-SNAPSHOT
8 | jar
9 |
10 | basic-mq
11 |
12 |
13 | UTF-8
14 |
15 |
16 |
17 |
18 | junit
19 | junit
20 | 4.8
21 | test
22 |
23 |
24 | com.rabbitmq
25 | amqp-client
26 | 3.2.4
27 |
28 |
29 | org.springframework.amqp
30 | spring-amqp
31 | 1.3.4.RELEASE
32 |
33 |
34 | org.springframework.amqp
35 | spring-rabbit
36 | 1.3.4.RELEASE
37 |
38 |
39 | com.caucho
40 | hessian
41 | 4.0.7
42 |
43 |
44 | org.jboss.logging
45 | jboss-logging
46 | 3.3.0.Final
47 |
48 |
49 | commons-lang
50 | commons-lang
51 | 2.4
52 |
53 |
54 | log4j
55 | log4j
56 | 1.2.16
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/src/main/java/org/cs/basic/mq/consumer/EventProcesser.java:
--------------------------------------------------------------------------------
1 | package org.cs.basic.mq.consumer;
2 | /**
3 | * 消费接口(所有消费者方法都实现)
4 | * @author Mr.Cheng
5 | *
6 | */
7 | public interface EventProcesser {
8 | public void process(Object e);
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/org/cs/basic/mq/consumer/EventProcesserRPC.java:
--------------------------------------------------------------------------------
1 | package org.cs.basic.mq.consumer;
2 |
3 | public interface EventProcesserRPC {
4 | public Object process(Object e);
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/org/cs/basic/mq/consumer/EventProcesserTopic.java:
--------------------------------------------------------------------------------
1 | package org.cs.basic.mq.consumer;
2 |
3 | public interface EventProcesserTopic {
4 | public void process(Object e);
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/org/cs/basic/mq/global/CodecFactory.java:
--------------------------------------------------------------------------------
1 | package org.cs.basic.mq.global;
2 |
3 | import java.io.IOException;
4 | /**
5 | * 序列化和反序列化工厂
6 | * @author Mr.Cheng
7 | *
8 | */
9 | public interface CodecFactory {
10 | byte[] serialize(Object obj) throws IOException;
11 | Object deSerialize(byte[] in) throws IOException;
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/org/cs/basic/mq/global/DefaultEventController.java:
--------------------------------------------------------------------------------
1 | package org.cs.basic.mq.global;
2 |
3 | import java.util.HashMap;
4 | import java.util.HashSet;
5 | import java.util.Map;
6 | import java.util.Set;
7 | import java.util.concurrent.atomic.AtomicBoolean;
8 |
9 | import org.apache.commons.lang.StringUtils;
10 | import org.cs.basic.mq.consumer.EventProcesser;
11 | import org.cs.basic.mq.consumer.EventProcesserRPC;
12 | import org.cs.basic.mq.producer.DefaultEventTemplate;
13 | import org.cs.basic.mq.producer.EventTemplate;
14 | import org.springframework.amqp.core.AcknowledgeMode;
15 | import org.springframework.amqp.core.Binding;
16 | import org.springframework.amqp.core.BindingBuilder;
17 | import org.springframework.amqp.core.DirectExchange;
18 | import org.springframework.amqp.core.FanoutExchange;
19 | import org.springframework.amqp.core.MessageListener;
20 | import org.springframework.amqp.core.Queue;
21 | import org.springframework.amqp.core.ReceiveAndReplyCallback;
22 | import org.springframework.amqp.core.TopicExchange;
23 | import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
24 | import org.springframework.amqp.rabbit.core.RabbitAdmin;
25 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
26 | import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
27 | import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
28 | import org.springframework.amqp.support.converter.MessageConverter;
29 | import org.springframework.amqp.support.converter.SerializerMessageConverter;
30 |
31 |
32 | /**
33 | * 和rabbitmq通信的控制器,主要负责:
34 | *
1、和rabbitmq建立连接
35 | * 2、声明exChange和queue以及它们的绑定关系
36 | * 3、启动消息监听容器,并将不同消息的处理者绑定到对应的exchange和queue上
37 | * 4、持有消息发送模版以及所有exchange、queue和绑定关系的本地缓存
38 | * @author Mr.Cheng
39 | *
40 | */
41 | public class DefaultEventController implements EventController {
42 |
43 | private CachingConnectionFactory rabbitConnectionFactory;
44 |
45 | private EventControlConfig config;
46 |
47 | private RabbitAdmin rabbitAdmin;
48 |
49 | private static RabbitTemplate rabbitTemplate;
50 |
51 | private CodecFactory defaultCodecFactory = new HessionCodecFactory();
52 |
53 | private SimpleMessageListenerContainer msgListenerContainer; // rabbitMQ msg listener container
54 |
55 | private MessageAdapterHandler msgAdapterHandler = new MessageAdapterHandler();
56 |
57 | private MessageConverter serializerMessageConverter = new SerializerMessageConverter(); // 直接指定
58 | //queue cache, key is exchangeName
59 | private Map exchanges = new HashMap();
60 | //queue cache, key is queueName
61 | private Map queues = new HashMap();
62 | //bind relation of queue to exchange cache, value is exchangeName | queueName
63 | private Set binded = new HashSet();
64 |
65 | private EventTemplate eventTemplate; // 给App使用的Event发送客户端
66 |
67 | private AtomicBoolean isStarted = new AtomicBoolean(false);
68 |
69 | private static DefaultEventController defaultEventController;
70 |
71 | public synchronized static DefaultEventController getInstance(EventControlConfig config){
72 | if(defaultEventController==null){
73 | defaultEventController = new DefaultEventController(config);
74 | }
75 | return defaultEventController;
76 | }
77 |
78 | private DefaultEventController(EventControlConfig config){
79 | if (config == null) {
80 | throw new IllegalArgumentException("Config can not be null.");
81 | }
82 | this.config = config;
83 | initRabbitConnectionFactory();
84 | // 初始化AmqpAdmin
85 | rabbitAdmin = new RabbitAdmin(rabbitConnectionFactory);
86 | // 初始化RabbitTemplate
87 | rabbitTemplate = new RabbitTemplate(rabbitConnectionFactory);
88 | rabbitTemplate.setMessageConverter(serializerMessageConverter);
89 | eventTemplate = new DefaultEventTemplate(rabbitTemplate,defaultCodecFactory);
90 | }
91 |
92 | public static RabbitTemplate getRabbitTemplate(){
93 | return rabbitTemplate;
94 | }
95 |
96 | /**
97 | * 初始化rabbitmq连接
98 | */
99 | private void initRabbitConnectionFactory() {
100 | rabbitConnectionFactory = new CachingConnectionFactory();
101 | if(config.getServerHost().contains(",")){
102 | rabbitConnectionFactory.setAddresses(config.getServerHost());
103 | }else{
104 | rabbitConnectionFactory.setHost(config.getServerHost());
105 | rabbitConnectionFactory.setPort(config.getPort());
106 | }
107 | rabbitConnectionFactory.setChannelCacheSize(config.getEventMsgProcessNum());
108 |
109 | rabbitConnectionFactory.setUsername(config.getUsername());
110 | rabbitConnectionFactory.setPassword(config.getPassword());
111 | if (!StringUtils.isEmpty(config.getVirtualHost())) {
112 | rabbitConnectionFactory.setVirtualHost(config.getVirtualHost());
113 | }
114 | }
115 |
116 | public CachingConnectionFactory getRabbitConnectionFactory() {
117 | return rabbitConnectionFactory;
118 | }
119 |
120 | /**
121 | * 注销程序
122 | */
123 | public synchronized void destroy() throws Exception {
124 | if (!isStarted.get()) {
125 | return;
126 | }
127 | msgListenerContainer.stop();
128 | eventTemplate = null;
129 | rabbitAdmin = null;
130 | rabbitConnectionFactory.destroy();
131 | }
132 |
133 | public void start() {
134 | if (isStarted.get()) {
135 | return;
136 | }
137 | Set mapping = msgAdapterHandler.getAllBinding();
138 | for (String relation : mapping) {
139 | String[] relaArr = relation.split("\\|");
140 | declareBinding(relaArr[1], relaArr[0],relaArr[2]);
141 | }
142 | initMsgListenerAdapter();
143 | isStarted.set(true);
144 | }
145 |
146 | /**
147 | * 初始化消息监听器容器
148 | */
149 | private void initMsgListenerAdapter(){
150 | MessageListener listener =new MessageListenerAdapter(msgAdapterHandler,"receiveMessage");
151 | //MessageListener listener = new MessageListenerAdapter(msgAdapterHandler,serializerMessageConverter);
152 | msgListenerContainer = new SimpleMessageListenerContainer();
153 | msgListenerContainer.setConnectionFactory(rabbitConnectionFactory);
154 | msgListenerContainer.setAcknowledgeMode(AcknowledgeMode.AUTO);
155 | msgListenerContainer.setMessageListener(listener);
156 | msgListenerContainer.setErrorHandler(new MessageErrorHandler());
157 | msgListenerContainer.setPrefetchCount(config.getPrefetchSize()); // 设置每个消费者消息的预取值
158 | msgListenerContainer.setConcurrentConsumers(config.getEventMsgProcessNum()); //消费者数量
159 | msgListenerContainer.setTxSize(config.getPrefetchSize());//设置有事务时处理的消息数
160 | msgListenerContainer.setQueues(queues.values().toArray(new Queue[queues.size()]));
161 | msgListenerContainer.start();
162 | }
163 |
164 |
165 | public EventTemplate getEopEventTemplate() {
166 | return eventTemplate;
167 | }
168 |
169 |
170 | public EventController add(String queueName, String exchangeName,EventProcesser eventProcesser) {
171 | return add(queueName, exchangeName, eventProcesser, defaultCodecFactory,queueName);
172 | }
173 | public EventController add(String queueName, String exchangeName,
174 | String routingKey, EventProcesser eventProcesser) {
175 | return add(queueName, exchangeName, eventProcesser, defaultCodecFactory,routingKey);
176 | }
177 | public EventController add(String queueName, String exchangeName,EventProcesser eventProcesser,CodecFactory codecFactory,String routingKey) {
178 | msgAdapterHandler.add(queueName, exchangeName, eventProcesser, defaultCodecFactory,routingKey);
179 | if(isStarted.get()){
180 | initMsgListenerAdapter();
181 | }
182 | return this;
183 | }
184 |
185 | public EventController add(String queueName, String exchangeName,EventProcesserRPC eventProcesser) {
186 | return add(queueName, exchangeName, eventProcesser, defaultCodecFactory,queueName);
187 | }
188 | public EventController add(String queueName, String exchangeName,
189 | String routingKey, EventProcesserRPC eventProcesser) {
190 | return add(queueName, exchangeName, eventProcesser, defaultCodecFactory,routingKey);
191 | }
192 | public EventController add(String queueName, String exchangeName,EventProcesserRPC eventProcesser,CodecFactory codecFactory,String routingKey) {
193 | msgAdapterHandler.add(queueName, exchangeName, eventProcesser, defaultCodecFactory,routingKey);
194 | if(isStarted.get()){
195 | initMsgListenerAdapter();
196 | }
197 | return this;
198 | }
199 | public EventController add(Map bindings,
200 | EventProcesser eventProcesser) {
201 | return add(bindings, eventProcesser,defaultCodecFactory);
202 | }
203 |
204 | public EventController add(Map bindings,
205 | EventProcesser eventProcesser, CodecFactory codecFactory) {
206 | for(Map.Entry item: bindings.entrySet())
207 | msgAdapterHandler.add(item.getKey(),item.getValue(), eventProcesser,codecFactory,item.getKey());
208 | return this;
209 | }
210 |
211 | /**
212 | * exchange和queue是否已经绑定
213 | */
214 | protected boolean beBinded(String exchangeName, String queueName,String routingKey) {
215 | return binded.contains(exchangeName+"|"+queueName+"|"+routingKey);
216 | }
217 |
218 | /**
219 | * 声明exchange和queue已经它们的绑定关系
220 | */
221 | protected synchronized void declareBinding(String exchangeName, String queueName,String routingKey) {
222 | String bindRelation = exchangeName+"|"+queueName+"|"+routingKey;
223 | if (binded.contains(bindRelation)) return;
224 |
225 | boolean needBinding = false;
226 | DirectExchange directExchange = exchanges.get(exchangeName);
227 | if(directExchange == null) {
228 | /**
229 | * 声明direct模式的exchange
230 | * 如果要声明topic的 new TopicExchange(exchangeName, true, false, null);
231 | * 广播fanout: new FanoutExchange(name, durable, autoDelete)
232 | * 这里可以修改成更灵活的,但是也可以通过web中配置exchange的模式
233 | */
234 | directExchange = new DirectExchange(exchangeName, true, false, null);
235 |
236 | exchanges.put(exchangeName, directExchange);
237 | rabbitAdmin.declareExchange(directExchange);//声明exchange
238 | needBinding = true;
239 | }
240 |
241 | Queue queue = queues.get(queueName);
242 | if(queue == null) {
243 | /**
244 | * Queue(name, durable, exclusive, autoDelete)
245 | * durable是否持久化,exclusive:是否排外,autoDelete:是否自动删除
246 | * 持久的意思是:是否保存到erlang自带得数据库mnesia中,即重启服务是否消失
247 | * 排外的意思是:当前定义的队列是connection中的channel共享的,其他connection连接访问不到
248 | * 当connection.close时队列删除
249 | *
250 | * new Queue(name, durable, exclusive, autoDelete, arguments)
251 | * arguments是队列得一些特性
252 | * map.put("x-message-ttl",1000*8)
253 | */
254 | queue = new Queue(queueName, true, false, false);
255 | queues.put(queueName, queue);
256 | rabbitAdmin.declareQueue(queue); //声明queue
257 | needBinding = true;
258 | }
259 |
260 | if(needBinding) {
261 | /**
262 | * 绑定队列到exchange上,并且设置routingkey
263 | * to(directExchange),to(topicExchange),to(fanoutExchange)..
264 | */
265 | Binding binding = BindingBuilder.bind(queue).to(directExchange).with(routingKey);
266 | rabbitAdmin.declareBinding(binding);//声明绑定关系
267 | binded.add(bindRelation);
268 | }
269 | }
270 |
271 | }
272 |
--------------------------------------------------------------------------------
/src/main/java/org/cs/basic/mq/global/EventControlConfig.java:
--------------------------------------------------------------------------------
1 | package org.cs.basic.mq.global;
2 | /**
3 | * 专门配置和rabbitmq通信的一些信息,比如地址,端口等信息
4 | * @author Mr.Cheng
5 | *
6 | */
7 | public class EventControlConfig {
8 | /**
9 | * 默认端口号
10 | */
11 | private final static int DEFAULT_PORT = 5672;
12 | /**
13 | * 默认账号
14 | */
15 | private final static String DEFAULT_USERNAME = "guest";
16 | /**
17 | * 默认密码
18 | */
19 | private final static String DEFAULT_PASSWORD = "guest";
20 | /**
21 | * 多少个线程在消费 默认为为cpu核数*2
22 | */
23 | private final static int DEFAULT_PROCESS_THREAD_NUM = Runtime.getRuntime().availableProcessors() * 2;
24 | // private final static int DEFAULT_PROCESS_THREAD_NUM =1;
25 |
26 | /**
27 | * 每次从队列中取几条,只有等ack了才重新取
28 | */
29 | private static final int PREFETCH_SIZE = 1;
30 | /**
31 | * ip
32 | */
33 | private String serverHost ;
34 | /**
35 | * 端口号
36 | */
37 | private int port = DEFAULT_PORT;
38 | /**
39 | * 账号
40 | */
41 | private String username = DEFAULT_USERNAME;
42 | /**
43 | * 密码
44 | */
45 | private String password = DEFAULT_PASSWORD;
46 | /**
47 | * 虚拟主机,推荐不同模块不同虚拟主机,实验得知:虚拟主机数量越多会提高QPS(即处理性能)
48 | */
49 | private String virtualHost;
50 |
51 | /**
52 | * 和rabbitmq建立连接的超时时间
53 | */
54 | private int connectionTimeout = 0;
55 |
56 | /**
57 | * 事件消息处理线程数,对应,默认是 CPU核数 * 2
58 | */
59 | private int eventMsgProcessNum;
60 |
61 | /**
62 | * 每次消费消息的预取值
63 | */
64 | private int prefetchSize;
65 | /**
66 | *
67 | * @param serverHost ip
68 | */
69 | public EventControlConfig(String serverHost) {
70 | this(serverHost,DEFAULT_PORT,DEFAULT_USERNAME,DEFAULT_PASSWORD,null,0,DEFAULT_PROCESS_THREAD_NUM,PREFETCH_SIZE,new HessionCodecFactory());
71 | }
72 | /**
73 | *
74 | * @param serverHost ip
75 | * @param username
76 | * @param password
77 | */
78 | public EventControlConfig(String serverHost,String username,String password){
79 | this(serverHost,DEFAULT_PORT,username,password,null,0,DEFAULT_PROCESS_THREAD_NUM,PREFETCH_SIZE,new HessionCodecFactory());
80 | }
81 | /**
82 | *
83 | * @param serverHost ip
84 | * @param port 默认端口号:5672
85 | * @param username 默认:guest
86 | * @param password 默认:guest
87 | *
88 | */
89 | public EventControlConfig(String serverHost,int port,String username,String password){
90 | this(serverHost,port,username,password,null,0,DEFAULT_PROCESS_THREAD_NUM,PREFETCH_SIZE,new HessionCodecFactory());
91 | }
92 | /**
93 | *
94 | * @param serverHost
95 | * @param username
96 | * @param password
97 | * @param processThreadNum 线程处理数,默认cpu核数*2
98 | * @param prefetchSize 预取消息数量,默认为1
99 | */
100 | public EventControlConfig(String serverHost,String username,String password,int processThreadNum,int prefetchSize){
101 | this(serverHost,DEFAULT_PORT,username,password,null,0,processThreadNum,prefetchSize,new HessionCodecFactory());
102 | }
103 | /**
104 | *
105 | * @param serverHost
106 | * @param username
107 | * @param password
108 | * @param prefetchSize 预取消息数量,默认为1 ,个人推荐使用这个方法
109 | */
110 | public EventControlConfig(String serverHost,String username,String password,int prefetchSize){
111 | this(serverHost,DEFAULT_PORT,username,password,null,0,DEFAULT_PROCESS_THREAD_NUM,prefetchSize,new HessionCodecFactory());
112 | }
113 |
114 | public EventControlConfig(String serverHost, int port, String username,
115 | String password, String virtualHost, int connectionTimeout,
116 | int eventMsgProcessNum,int prefetchSize,CodecFactory defaultCodecFactory) {
117 | this.serverHost = serverHost;
118 | this.port = port>0?port:DEFAULT_PORT;
119 | this.username = username;
120 | this.password = password;
121 | this.virtualHost = virtualHost;
122 | this.connectionTimeout = connectionTimeout>0?connectionTimeout:0;
123 | this.eventMsgProcessNum = eventMsgProcessNum>0?eventMsgProcessNum:DEFAULT_PROCESS_THREAD_NUM;
124 | this.prefetchSize = prefetchSize>0?prefetchSize:PREFETCH_SIZE;
125 | }
126 |
127 | public String getServerHost() {
128 | return serverHost;
129 | }
130 |
131 | public int getPort() {
132 | return port;
133 | }
134 |
135 | public String getUsername() {
136 | return username;
137 | }
138 |
139 | public String getPassword() {
140 | return password;
141 | }
142 |
143 | public String getVirtualHost() {
144 | return virtualHost;
145 | }
146 |
147 | public int getConnectionTimeout() {
148 | return connectionTimeout;
149 | }
150 |
151 | public int getEventMsgProcessNum() {
152 | return eventMsgProcessNum;
153 | }
154 |
155 | public int getPrefetchSize() {
156 | return prefetchSize;
157 | }
158 |
159 | }
160 |
--------------------------------------------------------------------------------
/src/main/java/org/cs/basic/mq/global/EventController.java:
--------------------------------------------------------------------------------
1 | package org.cs.basic.mq.global;
2 |
3 | import java.util.Map;
4 |
5 | import org.cs.basic.mq.consumer.EventProcesser;
6 | import org.cs.basic.mq.producer.EventTemplate;
7 | /**
8 | * 管理控制和rabbitmq的通信
9 | * @author Mr.Cheng
10 | *
11 | */
12 | public interface EventController {
13 | /**
14 | * 控制器启动方法
15 | */
16 | void start();
17 |
18 | /**
19 | * 获取发送模版
20 | */
21 | EventTemplate getEopEventTemplate();
22 |
23 | /**
24 | * 绑定消费程序到对应的exchange和queue
25 | */
26 | EventController add(String queueName, String exchangeName, EventProcesser eventProcesser);
27 |
28 | /*in map, the key is queue name, but value is exchange name*/
29 | EventController add(Map bindings, EventProcesser eventProcesser);
30 |
31 |
32 | EventController add(String queueName,String exchangeName,String routingKey,EventProcesser eventProcesser);
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/org/cs/basic/mq/global/EventMessage.java:
--------------------------------------------------------------------------------
1 | package org.cs.basic.mq.global;
2 |
3 | import java.io.Serializable;
4 | import java.util.Arrays;
5 | /**
6 | * web和rabbitmq之间传递消息的持有对象
7 | * @author Mr.Cheng
8 | *
9 | */
10 | public class EventMessage implements Serializable{
11 | /**
12 | *
13 | */
14 | private static final long serialVersionUID = 1L;
15 |
16 | private String queueName;
17 |
18 | private String exchangeName;
19 |
20 | private String routingKey;
21 |
22 | private String consumerQueueName;
23 |
24 | private String consumerExchange;
25 |
26 | private byte[] eventData;
27 |
28 | private int type;
29 |
30 | public EventMessage(String queueName, String exchangeName, byte[] eventData) {
31 | this.queueName = queueName;
32 | this.exchangeName = exchangeName;
33 | this.eventData = eventData;
34 | this.type=0;
35 | }
36 |
37 |
38 | public EventMessage(String queueName, String exchangeName,
39 | byte[] eventData, int type) {
40 | super();
41 | this.queueName = queueName;
42 | this.exchangeName = exchangeName;
43 | this.eventData = eventData;
44 | this.type = type;
45 | }
46 |
47 |
48 |
49 | public EventMessage(String queueName, String exchangeName,
50 | String routingKey, byte[] eventData, int type) {
51 | super();
52 | this.queueName = queueName;
53 | this.exchangeName = exchangeName;
54 | this.routingKey = routingKey;
55 | this.eventData = eventData;
56 | this.type = type;
57 | }
58 |
59 |
60 | public EventMessage(String queueName, String exchangeName,
61 | String routingKey, String consumerQueueName,
62 | String consumerExchange, byte[] eventData, int type) {
63 | super();
64 | this.queueName = queueName;
65 | this.exchangeName = exchangeName;
66 | this.routingKey = routingKey;
67 | this.consumerQueueName = consumerQueueName;
68 | this.consumerExchange = consumerExchange;
69 | this.eventData = eventData;
70 | this.type = type;
71 | }
72 |
73 |
74 | public String getConsumerExchange() {
75 | return consumerExchange;
76 | }
77 |
78 |
79 | public EventMessage() {
80 | }
81 |
82 | public String getQueueName() {
83 | return queueName;
84 | }
85 |
86 | public String getExchangeName() {
87 | return exchangeName;
88 | }
89 |
90 | public byte[] getEventData() {
91 | return eventData;
92 | }
93 | public int getType() {
94 | return type;
95 | }
96 | public String getRoutingKey() {
97 | return routingKey;
98 | }
99 | public String getConsumerQueueName() {
100 | return consumerQueueName;
101 | }
102 |
103 |
104 | @Override
105 | public String toString() {
106 | return "EventMessage [queueName=" + queueName + ", exchangeName="
107 | + exchangeName + ", routingKey=" + routingKey + ", eventData="
108 | + Arrays.toString(eventData) + ", type=" + type + "]";
109 | }
110 |
111 |
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/src/main/java/org/cs/basic/mq/global/HessionCodecFactory.java:
--------------------------------------------------------------------------------
1 | package org.cs.basic.mq.global;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.IOException;
6 | import org.jboss.logging.Logger;
7 |
8 | import com.caucho.hessian.io.HessianInput;
9 | import com.caucho.hessian.io.HessianOutput;
10 | /**
11 | * 使用hessian序列化
12 | * @author Mr.Cheng
13 | *
14 | */
15 | public class HessionCodecFactory implements CodecFactory {
16 |
17 | private final Logger logger = Logger.getLogger(HessionCodecFactory.class);
18 |
19 | public byte[] serialize(Object obj) throws IOException {
20 | ByteArrayOutputStream baos = null;
21 | HessianOutput output = null;
22 | try {
23 | baos = new ByteArrayOutputStream(1024);
24 | output = new HessianOutput(baos);
25 | output.startCall();
26 | output.writeObject(obj);
27 | output.completeCall();
28 | } catch (final IOException ex) {
29 | throw ex;
30 | } finally {
31 | if (output != null) {
32 | try {
33 | baos.close();
34 | } catch (final IOException ex) {
35 | this.logger.error("Failed to close stream.", ex);
36 | }
37 | }
38 | }
39 | return baos != null ? baos.toByteArray() : null;
40 | }
41 |
42 | public Object deSerialize(byte[] in) throws IOException {
43 | Object obj = null;
44 | ByteArrayInputStream bais = null;
45 | HessianInput input = null;
46 | try {
47 | bais = new ByteArrayInputStream(in);
48 | input = new HessianInput(bais);
49 | input.startReply();
50 | obj = input.readObject();
51 | input.completeReply();
52 | } catch (final IOException ex) {
53 | throw ex;
54 | } catch (final Throwable e) {
55 | this.logger.error("Failed to decode object.", e);
56 | } finally {
57 | if (input != null) {
58 | try {
59 | bais.close();
60 | } catch (final IOException ex) {
61 | this.logger.error("Failed to close stream.", ex);
62 | }
63 | }
64 | }
65 | return obj;
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/org/cs/basic/mq/global/MessageAdapterHandler.java:
--------------------------------------------------------------------------------
1 | package org.cs.basic.mq.global;
2 |
3 | import java.io.IOException;
4 | import java.util.Set;
5 | import java.util.concurrent.ConcurrentHashMap;
6 | import java.util.concurrent.ConcurrentMap;
7 |
8 | import org.apache.commons.lang.StringUtils;
9 | import org.cs.basic.mq.consumer.EventProcesser;
10 | import org.cs.basic.mq.consumer.EventProcesserRPC;
11 | import org.cs.basic.mq.util.ObjectAndByte;
12 | import org.jboss.logging.Logger;
13 | import org.springframework.amqp.core.Message;
14 | import org.springframework.amqp.core.ReceiveAndReplyCallback;
15 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
16 |
17 | import com.rabbitmq.client.ConsumerCancelledException;
18 | import com.rabbitmq.client.ShutdownSignalException;
19 |
20 | /**
21 | * * MessageListenerAdapter的Pojo
22 | * 消息处理适配器,主要功能:
23 | * 1、将不同的消息类型绑定到对应的处理器并本地缓存,如将queue01+exchange01的消息统一交由A处理器来出来
24 | * 2、执行消息的消费分发,调用相应的处理器来消费属于它的消息
25 | * @author Mr.Cheng
26 | *
27 | */
28 | public class MessageAdapterHandler {
29 | private static final Logger logger = Logger.getLogger(MessageAdapterHandler.class);
30 |
31 | private ConcurrentMap epwMap;
32 |
33 | public MessageAdapterHandler() {
34 | this.epwMap = new ConcurrentHashMap();
35 | }
36 |
37 | /* public void handleMessage(EventMessage eem) throws ShutdownSignalException, ConsumerCancelledException, InterruptedException {
38 | logger.debug("Receive an EventMessage: [" + eem + "]");
39 | // 先要判断接收到的message是否是空的,在某些异常情况下,会产生空值
40 | if (eem == null) {
41 | logger.warn("Receive an null EventMessage, it may product some errors, and processing message is canceled.");
42 | return;
43 | }
44 | if (StringUtils.isEmpty(eem.getQueueName()) || StringUtils.isEmpty(eem.getExchangeName())) {
45 | logger.warn("The EventMessage's queueName and exchangeName is empty, this is not allowed, and processing message is canceled.");
46 | return;
47 | }
48 | // 解码,并交给对应的EventHandle执行
49 | EventProcessorWrap eepw = epwMap.get(eem.getQueueName()+"|"+eem.getExchangeName());
50 | if (eepw == null) {
51 | logger.warn("Receive an EopEventMessage, but no processor can do it.");
52 | return;
53 | }
54 | try {
55 | System.out.println(eem.getType());
56 | if(eem.getType()==0){
57 | eepw.process(eem.getEventData());
58 | }
59 |
60 | } catch (IOException e) {
61 | logger.error("Event content can not be Deserialized, check the provided CodecFactory.",e);
62 | return;
63 | }
64 | } */
65 | public Object receiveMessage(byte[] message) throws IOException{
66 | EventMessage eem=(EventMessage) ObjectAndByte.ByteToObject(message);
67 | if (eem == null) {
68 | logger.warn("Receive an null EventMessage, it may product some errors, and processing message is canceled.");
69 | return "error";
70 | }
71 | if (StringUtils.isEmpty(eem.getQueueName()) || StringUtils.isEmpty(eem.getExchangeName())) {
72 | logger.warn("The EventMessage's queueName and exchangeName is empty, this is not allowed, and processing message is canceled.");
73 | return "error";
74 | }
75 | System.out.println(eem.toString());
76 | // 解码,并交给对应的EventHandle执行
77 | EventProcessorWrap eepw=null;
78 | if(eem.getType()==2){
79 | eepw= epwMap.get(eem.getConsumerQueueName()+"|"+eem.getConsumerExchange()+"|"+eem.getRoutingKey());
80 | }else{
81 | eepw= epwMap.get(eem.getQueueName()+"|"+eem.getExchangeName()+"|"+eem.getRoutingKey());
82 | }
83 | if (eepw == null) {
84 | logger.warn("Receive an EopEventMessage, but no processor can do it.");
85 | return "error";
86 | }
87 | Object obj=null;
88 | if(eem.getType()==0|| eem.getType()==2){
89 | eepw.process(eem.getEventData());
90 | }else if(eem.getType()==1){
91 | obj=eepw.processRpc(eem.getEventData());
92 | }
93 | return obj;
94 | }
95 | public Object receiveMessage(EventMessage eem) throws IOException{
96 | if (eem == null) {
97 | logger.warn("Receive an null EventMessage, it may product some errors, and processing message is canceled.");
98 | return "error";
99 | }
100 | if (StringUtils.isEmpty(eem.getQueueName()) || StringUtils.isEmpty(eem.getExchangeName())) {
101 | logger.warn("The EventMessage's queueName and exchangeName is empty, this is not allowed, and processing message is canceled.");
102 | return "error";
103 | }
104 | System.out.println(eem.toString());
105 | // 解码,并交给对应的EventHandle执行
106 | EventProcessorWrap eepw=null;
107 | if(eem.getType()==2){
108 | eepw= epwMap.get(eem.getConsumerQueueName()+"|"+eem.getConsumerExchange()+"|"+eem.getRoutingKey());
109 | }else{
110 | eepw= epwMap.get(eem.getQueueName()+"|"+eem.getExchangeName()+"|"+eem.getRoutingKey());
111 | }
112 | if (eepw == null) {
113 | logger.warn("Receive an EopEventMessage, but no processor can do it.");
114 | return "error";
115 | }
116 | Object obj=null;
117 | if(eem.getType()==0|| eem.getType()==2){
118 | eepw.process(eem.getEventData());
119 | }else if(eem.getType()==1){
120 | obj=eepw.processRpc(eem.getEventData());
121 | }
122 | return obj;
123 | }
124 | protected void add(String queueName, String exchangeName, EventProcesser processor,CodecFactory codecFactory,String routingKey) {
125 | if (StringUtils.isEmpty(queueName) || StringUtils.isEmpty(exchangeName) || processor == null || codecFactory == null || routingKey==null) {
126 | throw new RuntimeException("queueName and exchangeName can not be empty,and processor or codecFactory can not be null. ");
127 | }
128 | EventProcessorWrap epw = new EventProcessorWrap(codecFactory,processor);
129 | EventProcessorWrap oldProcessorWrap = epwMap.putIfAbsent(queueName + "|" + exchangeName+"|"+routingKey, epw);
130 | if (oldProcessorWrap != null) {
131 | logger.warn("The processor of this queue and exchange exists, and the new one can't be add");
132 | }
133 | }
134 | protected void add(String queueName, String exchangeName, EventProcesserRPC processor,CodecFactory codecFactory,String routingKey) {
135 | if (StringUtils.isEmpty(queueName) || StringUtils.isEmpty(exchangeName) || processor == null || codecFactory == null) {
136 | throw new RuntimeException("queueName and exchangeName can not be empty,and processor or codecFactory can not be null. ");
137 | }
138 | EventProcessorWrap epw = new EventProcessorWrap(codecFactory,processor);
139 | EventProcessorWrap oldProcessorWrap = epwMap.putIfAbsent(queueName + "|" + exchangeName+"|"+routingKey, epw);
140 | if (oldProcessorWrap != null) {
141 | logger.warn("The processor of this queue and exchange exists, and the new one can't be add");
142 | }
143 | }
144 |
145 | protected Set getAllBinding() {
146 | Set keySet = epwMap.keySet();
147 | return keySet;
148 | }
149 |
150 | protected static class EventProcessorWrap {
151 |
152 | private CodecFactory codecFactory;
153 |
154 | private EventProcesser eep;
155 |
156 | private EventProcesserRPC rpc;
157 |
158 | protected EventProcessorWrap(CodecFactory codecFactory,
159 | EventProcesser eep) {
160 | this.codecFactory = codecFactory;
161 | this.eep = eep;
162 | }
163 | protected EventProcessorWrap(CodecFactory codecFactory,
164 | EventProcesserRPC rpc) {
165 | this.codecFactory = codecFactory;
166 | this.rpc=rpc;
167 | }
168 |
169 | public void process(byte[] eventData) throws IOException{
170 | Object obj = codecFactory.deSerialize(eventData);
171 | eep.process(obj);
172 | }
173 | public Object processRpc(byte[] eventData) throws IOException{
174 | Object obj = codecFactory.deSerialize(eventData);
175 | return rpc.process(obj);
176 | }
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/src/main/java/org/cs/basic/mq/global/MessageErrorHandler.java:
--------------------------------------------------------------------------------
1 | package org.cs.basic.mq.global;
2 |
3 | import org.jboss.logging.Logger;
4 | import org.springframework.util.ErrorHandler;
5 | /**
6 | * 消费类专门用来处理错误异常的消息
7 | * @author Mr.Cheng
8 | *
9 | */
10 | public class MessageErrorHandler implements ErrorHandler{
11 |
12 | private static final Logger logger = Logger.getLogger(MessageErrorHandler.class);
13 |
14 | public void handleError(Throwable t) {
15 | logger.error("RabbitMQ happen a error:" + t.getMessage(), t);
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/org/cs/basic/mq/producer/DefaultEventTemplate.java:
--------------------------------------------------------------------------------
1 | package org.cs.basic.mq.producer;
2 |
3 | import java.io.IOException;
4 |
5 | import org.apache.commons.lang.StringUtils;
6 | import org.cs.basic.mq.global.CodecFactory;
7 | import org.cs.basic.mq.global.EventMessage;
8 | import org.cs.basic.mq.util.ObjectAndByte;
9 | import org.jboss.logging.Logger;
10 | import org.springframework.amqp.AmqpException;
11 | import org.springframework.amqp.core.AmqpTemplate;
12 | import org.springframework.amqp.core.Message;
13 | import org.springframework.amqp.core.MessageProperties;
14 | /**
15 | * 默认消息模板
16 | * @author Mr.Cheng
17 | *
18 | */
19 | public class DefaultEventTemplate implements EventTemplate {
20 |
21 | private static final Logger logger = Logger.getLogger(DefaultEventTemplate.class);
22 |
23 | private AmqpTemplate eventAmqpTemplate;
24 |
25 | private CodecFactory defaultCodecFactory;
26 |
27 | // private DefaultEventController eec;
28 | //
29 | // public DefaultEventTemplate(AmqpTemplate eopAmqpTemplate,
30 | // CodecFactory defaultCodecFactory, DefaultEventController eec) {
31 | // this.eventAmqpTemplate = eopAmqpTemplate;
32 | // this.defaultCodecFactory = defaultCodecFactory;
33 | // this.eec = eec;
34 | // }
35 |
36 | public DefaultEventTemplate(AmqpTemplate eopAmqpTemplate,CodecFactory defaultCodecFactory) {
37 | this.eventAmqpTemplate = eopAmqpTemplate;
38 | this.defaultCodecFactory = defaultCodecFactory;
39 | }
40 |
41 | /**
42 | * 普通消费模式
43 | * @param queueName 队列名
44 | * @param exchangeName 转换器
45 | * @param eventContent 对象
46 | */
47 | public void send(String queueName, String exchangeName, Object eventContent)
48 | throws Exception {
49 | this.send(queueName, exchangeName, null,null,eventContent, defaultCodecFactory,0,queueName,0,0);
50 | }
51 | /**
52 | * 带路由的普通消费模式
53 | * @param queueName 队列
54 | * @param exchangeName 转换器
55 | * @param routing 路由
56 | * @param eventContent 对象
57 | */
58 | public void send(String queueName, String exchangeName, String routing,
59 | Object eventContent) throws Exception {
60 | this.send(queueName, exchangeName, null,null,eventContent, defaultCodecFactory, 0, routing,0,0);
61 | }
62 | /**
63 | * 普通消费模式,对message进行设置
64 | * @param queueName 队列名
65 | * @param exchangeName 转化器
66 | * @param eventContent 对象
67 | * @param expiration 过期时间 (毫秒) 0表示不过期
68 | * @param priority 优先级 0(默认,也是最低)
69 | * @author Mr.Cheng
70 | */
71 | public void send(String queueName, String exchangeName, Object eventContent,int expiration,int priority)
72 | throws Exception {
73 | this.send(queueName, exchangeName, null,null,eventContent, defaultCodecFactory,0,queueName,expiration,priority);
74 | }
75 |
76 | /**
77 | * 带路由的普通消费模式,对message进行设置
78 | * @param queueName 队列名
79 | * @param exchangeName 转换器
80 | * @param routing 路由
81 | * @param eventContent 对象
82 | * @param expiration 过期时间 (毫秒) 0表示不过期
83 | * @param priority 优先级 0(默认,也是最低)
84 | *
85 | */
86 | public void send(String queueName, String exchangeName, String routing,
87 | Object eventContent,int expiration,int priority) throws Exception {
88 | this.send(queueName, exchangeName, null,null,eventContent, defaultCodecFactory, 0, routing,expiration,priority);
89 | }
90 |
91 | /**
92 | * 队列延迟消费模式
93 | */
94 | public void send(String queueName, String exchangeName, String consumerQueueName,String consumerExchange,String routing,
95 | Object eventContent) throws Exception {
96 | this.send(queueName, exchangeName,consumerQueueName,consumerExchange,eventContent, defaultCodecFactory, 2, routing,0,0);
97 | }
98 | /**
99 | * 队列延迟消费模式
100 | * 消息过期时间
101 | */
102 | public void send(String queueName, String exchangeName, String consumerQueueName,String consumerExchange,String routing,
103 | Object eventContent,int expiration,int priority) throws Exception {
104 | this.send(queueName, exchangeName,consumerQueueName,consumerExchange,eventContent, defaultCodecFactory, 2, routing,expiration,priority);
105 | }
106 | /**
107 | * rpc模式
108 | * @param queueName 队列名
109 | * @param exchangeName 转换器
110 | * @param eventContent 对象
111 | */
112 | public Object sendAndReceive(String queueName, String exchangeName,
113 | Object eventContent) throws Exception {
114 | return this.send(queueName, exchangeName, null,null,eventContent, defaultCodecFactory,1,queueName,0,0);
115 | }
116 |
117 |
118 | private Object send(String queueName, String exchangeName, String consumerQueueName,String consumerExchange, Object eventContent,
119 | CodecFactory codecFactory,int type,String routingKey,int expiration,int priority) throws Exception {
120 | if (StringUtils.isEmpty(queueName) || StringUtils.isEmpty(exchangeName) || StringUtils.isEmpty(routingKey)) {
121 | throw new Exception("queueName exchangeName routingKey can not be empty.");
122 | }
123 |
124 | // if (!eec.beBinded(exchangeName, queueName))
125 | // eec.declareBinding(exchangeName, queueName);
126 |
127 | byte[] eventContentBytes = null;
128 | if (codecFactory == null) {
129 | if (eventContent == null) {
130 | logger.warn("Find eventContent is null,are you sure...");
131 | } else {
132 | throw new Exception(
133 | "codecFactory must not be null ,unless eventContent is null");
134 | }
135 | } else {
136 | try {
137 | eventContentBytes = codecFactory.serialize(eventContent);
138 | } catch (IOException e) {
139 | throw new Exception(e);
140 | }
141 | }
142 | Object obj=null;
143 | // 构造成Message
144 | EventMessage msg = new EventMessage(queueName, exchangeName,routingKey, consumerQueueName,consumerExchange,
145 | eventContentBytes,type);
146 | MessageProperties messageProperties=new MessageProperties();
147 | if(expiration>0){ //过期时间
148 | messageProperties.setExpiration(String.valueOf(expiration));
149 | }
150 | if(priority>0){ //消息优先级
151 | messageProperties.setPriority(Integer.valueOf(priority));
152 | }
153 | Message message=new Message(ObjectAndByte.ObjectToByte(msg),messageProperties);
154 | try {
155 | if(type==0 || type==2){ //普通
156 | // eventAmqpTemplate.convertAndSend(exchangeName, routingKey, msg);
157 | /**
158 | * 通过send方法发送的数据为message类型,主要是为了配合messageProperties可以对消息进行控制
159 | */
160 | eventAmqpTemplate.send(exchangeName, routingKey, message);
161 | }else if(type==1){ //rpc
162 | obj=eventAmqpTemplate.convertSendAndReceive(routingKey,msg);
163 | // obj=eventAmqpTemplate.sendAndReceive(routingKey,message);
164 | }
165 | } catch (AmqpException e) {
166 | logger.error("send event fail. Event Message : [" + eventContent + "]", e);
167 | throw new Exception("send event fail", e);
168 | }
169 | return obj;
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/src/main/java/org/cs/basic/mq/producer/EventTemplate.java:
--------------------------------------------------------------------------------
1 | package org.cs.basic.mq.producer;
2 |
3 |
4 | /**
5 | *
6 | * Description:发送接口
7 | * @type 接口
8 | * @author Mr.Cheng
9 | * @date 2017年2月17日
10 | * @time 上午10:21:55
11 | *
12 | */
13 | public interface EventTemplate {
14 | /**
15 | * 普通
16 | * @param queueName 队列名
17 | * @param exchangeName 交换机
18 | * @param eventContent 发送对象
19 | * @throws Exception
20 | */
21 | void send(String queueName,String exchangeName,Object eventContent) throws Exception;
22 | /**
23 | * rpc(远程调用)
24 | * @param queueName 队列名
25 | * @param exchangeName 交换机
26 | * @param eventContent 发送对象
27 | * @return
28 | * @throws Exception
29 | */
30 | Object sendAndReceive(String queueName,String exchangeName,Object eventContent) throws Exception;
31 |
32 | /**
33 | * 带路由的普通消费
34 | * @param queueName 队列名
35 | * @param exchangeName 交换机
36 | * @param routing 路由
37 | * @param eventContent 发送对象
38 | * @throws Exception
39 | */
40 | void send(String queueName,String exchangeName,String routing,Object eventContent) throws Exception;
41 |
42 | /**
43 | * 延迟消费
44 | * @param queueName 队列名
45 | * @param exchangeName 交换机
46 | * @param consumerQueueName 消费者队列
47 | * @param consumerExchange 消费交换机
48 | * @param routing 路由 生产者
49 | * @param eventContent 发送对象
50 | * @throws Exception
51 | */
52 | void send(String queueName,String exchangeName,String consumerQueueName,String consumerExchange,String routing,Object eventContent) throws Exception;
53 | /**
54 | * 延迟消费
55 | * @param queueName 队列名
56 | * @param exchangeName 交换机
57 | * @param consumerQueueName 消费者队列
58 | * @param consumerExchange 消费交换机
59 | * @param routing 路由 生产者
60 | * @param eventContent 发送对象
61 | * @param expiration 过期时间
62 | * @param priority 优先级
63 | * @throws Exception
64 | */
65 | void send(String queueName,String exchangeName,String consumerQueueName,String consumerExchange,String routing,Object eventContent,int expiration,int priority) throws Exception;
66 |
67 | /**
68 | * 普通消息,对消息进行过期设置
69 | * @param queueName 队列名
70 | * @param exchangeName 交换机
71 | * @param eventContent 发送对象
72 | * @param expiration 过期时间
73 | * @param priority 优先级
74 | * @throws Exception
75 | */
76 | void send(String queueName, String exchangeName, Object eventContent,int expiration,int priority) throws Exception;
77 | /**
78 | * 路由消息,对消息进行过期设置
79 | * @param queueName 队列名
80 | * @param exchangeName 交换机
81 | * @param routing 路由
82 | * @param eventContent 发送对象
83 | * @param expiration 过期时间
84 | * @param priority 优先级
85 | * @throws Exception
86 | */
87 | void send(String queueName, String exchangeName, String routing,Object eventContent,int expiration,int priority) throws Exception;
88 | }
89 |
--------------------------------------------------------------------------------
/src/main/java/org/cs/basic/mq/rpc/RPCClient.java:
--------------------------------------------------------------------------------
1 | package org.cs.basic.mq.rpc;
2 |
3 | import java.util.concurrent.Callable;
4 | import java.util.concurrent.ExecutorService;
5 | import java.util.concurrent.Executors;
6 | import java.util.concurrent.Future;
7 | import java.util.concurrent.TimeUnit;
8 | import java.util.concurrent.TimeoutException;
9 |
10 | import org.apache.log4j.Logger;
11 | import org.cs.basic.mq.global.CodecFactory;
12 | import org.cs.basic.mq.global.EventControlConfig;
13 | import org.cs.basic.mq.global.HessionCodecFactory;
14 | import org.cs.basic.mq.util.ConnectionUtil;
15 |
16 | import com.rabbitmq.client.AMQP.BasicProperties;
17 | import com.rabbitmq.client.Channel;
18 | import com.rabbitmq.client.QueueingConsumer;
19 | /**
20 | * RPC生产者
21 | * @author Mr.Cheng
22 | * @since 2016/11/29 15:53
23 | */
24 | public class RPCClient {
25 |
26 | private static Logger logger=Logger.getLogger(RPCClient.class);
27 | private ConnectionUtil connection;
28 | private Channel channel;
29 | private String replyQueueName;
30 | private QueueingConsumer consumer;
31 | final ExecutorService exec = Executors.newFixedThreadPool(1);
32 | private CodecFactory cf; //序列化工厂
33 | private String corrId="";
34 | public RPCClient(){};
35 | public RPCClient(EventControlConfig config) throws Exception {
36 | //• 先建立一个连接和一个通道,并为回调声明一个唯一的'回调'队列
37 | connection=new ConnectionUtil(config);
38 | channel=connection.getChannel();
39 | //• 注册'回调'队列,这样就可以收到RPC响应
40 | replyQueueName = channel.queueDeclare().getQueue();
41 | consumer = new QueueingConsumer(channel);
42 | channel.basicConsume(replyQueueName, true, consumer);
43 | cf=new HessionCodecFactory();
44 | }
45 |
46 | /**
47 | * 发送对象到rpc服务端
48 | * @param message //发送对象
49 | * @param requestQueueName //请求队列名
50 | * @param time //超时时间 单位秒
51 | * @return
52 | * @throws Exception
53 | */
54 | public Object callServer(Object message,String requestQueueName,int time) throws Exception {
55 | Object response = null;
56 | corrId = java.util.UUID.randomUUID().toString();
57 | //发送请求消息,消息使用了两个属性:replyto和correlationId
58 | BasicProperties props = new BasicProperties.Builder()
59 | .correlationId(corrId).replyTo(replyQueueName).build();
60 | channel.basicPublish("", requestQueueName, props, cf.serialize(message));
61 | //等待接收结果
62 | try {
63 | //超时处理
64 | Future