├── 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 future = exec.submit(call); 65 | if(time<1) time=1; 66 | response = future.get(1000*time, TimeUnit.MILLISECONDS); //任务处理超时时间默认设为 1 秒 67 | } catch (TimeoutException ex) { 68 | response="服务端处理超时!"; 69 | logger.error(ex.getMessage()); 70 | } catch (Exception e) { 71 | response="处理失败"; 72 | logger.error(e.getMessage()); 73 | } 74 | // 关闭线程池 75 | exec.shutdown(); 76 | return response; 77 | } 78 | //处理函数 79 | Callable call = new Callable() { 80 | public Object call() throws Exception { 81 | QueueingConsumer.Delivery delivery = consumer.nextDelivery(); 82 | //检查它的correlationId是否是我们所要找的那个 83 | if (delivery.getProperties().getCorrelationId().equals(corrId)) { 84 | return cf.deSerialize(delivery.getBody()); 85 | } 86 | return "correlationId不对"; 87 | } 88 | }; 89 | /** 90 | * 关闭 91 | * @throws Exception 92 | */ 93 | public void close() throws Exception { 94 | if(connection!=null){ 95 | connection.close(); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/org/cs/basic/mq/rpc/RPCServer.java: -------------------------------------------------------------------------------- 1 | package org.cs.basic.mq.rpc; 2 | 3 | import java.io.IOException; 4 | 5 | import org.apache.log4j.Logger; 6 | import org.cs.basic.mq.consumer.EventProcesserRPC; 7 | import org.cs.basic.mq.global.CodecFactory; 8 | import org.cs.basic.mq.global.EventControlConfig; 9 | import org.cs.basic.mq.global.HessionCodecFactory; 10 | import org.cs.basic.mq.util.ConnectionUtil; 11 | 12 | import com.rabbitmq.client.AMQP.BasicProperties; 13 | import com.rabbitmq.client.Channel; 14 | import com.rabbitmq.client.ConsumerCancelledException; 15 | import com.rabbitmq.client.QueueingConsumer; 16 | import com.rabbitmq.client.ShutdownSignalException; 17 | /** 18 | * RPC消费者 19 | * @author Mr.Cheng 20 | * @since 2016/11/29 15:54 21 | */ 22 | public class RPCServer { 23 | private static Logger logger=Logger.getLogger(RPCServer.class); 24 | private Channel channel; 25 | private CodecFactory cf; 26 | private BasicProperties props; 27 | private BasicProperties replyProps; 28 | private QueueingConsumer.Delivery delivery; 29 | private QueueingConsumer consumer; 30 | private EventProcesserRPC ephandle; 31 | public RPCServer(){}; 32 | public RPCServer(EventControlConfig config) throws IOException{ 33 | ConnectionUtil connection=new ConnectionUtil(config); 34 | channel=connection.getChannel(); 35 | cf=new HessionCodecFactory(); 36 | } 37 | /** 38 | * 接受并回调 39 | * @param RPC_QUEUE_NAME 40 | * @param ep 41 | * @throws IOException 42 | * @throws ShutdownSignalException 43 | * @throws ConsumerCancelledException 44 | * @throws InterruptedException 45 | */ 46 | public void recAndCallBack(String RPC_QUEUE_NAME,EventProcesserRPC ep) throws IOException, ShutdownSignalException, ConsumerCancelledException, InterruptedException{ 47 | 48 | channel.queueDeclare(RPC_QUEUE_NAME, true, false, false, null); 49 | channel.basicQos(1); 50 | consumer = new QueueingConsumer(channel); 51 | //打开应答机制autoAck=false 52 | channel.basicConsume(RPC_QUEUE_NAME, false, consumer); 53 | logger.info("[x] Awaiting RPC requests..."); 54 | ephandle=ep; 55 | Runnable main=new Runnable(){ 56 | public void run() { 57 | // TODO Auto-generated method stub 58 | try { 59 | delivery = consumer.nextDelivery(); 60 | props = delivery.getProperties(); 61 | replyProps = new BasicProperties.Builder() 62 | .correlationId(props.getCorrelationId()).build(); 63 | Object message = cf.deSerialize(delivery.getBody()); 64 | Object remessage=ephandle.process(message); 65 | //返回处理结果队列 66 | channel.basicPublish("", props.getReplyTo(), replyProps, 67 | cf.serialize(remessage)); 68 | //发送应答 69 | channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false); 70 | } catch (Exception e) { 71 | e.printStackTrace(); 72 | } 73 | System.out.println("11"); 74 | } 75 | 76 | }; 77 | new Thread(main).start(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/org/cs/basic/mq/rpc/RPCServerListener.java: -------------------------------------------------------------------------------- 1 | package org.cs.basic.mq.rpc; 2 | 3 | import org.springframework.amqp.core.Message; 4 | import org.springframework.amqp.core.MessageListener; 5 | 6 | public class RPCServerListener implements MessageListener{ 7 | 8 | public void onMessage(Message message) { 9 | 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/cs/basic/mq/topic/TopicConsumer.java: -------------------------------------------------------------------------------- 1 | package org.cs.basic.mq.topic; 2 | 3 | import java.io.IOException; 4 | 5 | import org.apache.log4j.Logger; 6 | import org.cs.basic.mq.consumer.EventProcesserTopic; 7 | import org.cs.basic.mq.global.CodecFactory; 8 | import org.cs.basic.mq.global.EventControlConfig; 9 | import org.cs.basic.mq.global.HessionCodecFactory; 10 | import org.cs.basic.mq.util.ConnectionUtil; 11 | 12 | import com.rabbitmq.client.Channel; 13 | import com.rabbitmq.client.ConsumerCancelledException; 14 | import com.rabbitmq.client.QueueingConsumer; 15 | import com.rabbitmq.client.ShutdownSignalException; 16 | 17 | /** 18 | * 主题订阅消费者 19 | * @author Mr.Cheng 20 | * 21 | */ 22 | public class TopicConsumer { 23 | private static Logger logger=Logger.getLogger(TopicConsumer.class); 24 | private Channel channel; 25 | private CodecFactory cf; 26 | private ConnectionUtil connection; 27 | public TopicConsumer(){}; 28 | public TopicConsumer(EventControlConfig config) throws IOException{ 29 | connection=new ConnectionUtil(config); 30 | channel=connection.getChannel(); 31 | cf=new HessionCodecFactory(); 32 | } 33 | /** 34 | * 消费方法 35 | * @param exchagnes 转换器 36 | * @param routingkey 路由 37 | * @param ept 处理类 38 | * @throws IOException 39 | * @throws ShutdownSignalException 40 | * @throws ConsumerCancelledException 41 | * @throws InterruptedException 42 | */ 43 | public void receive(String exchagnes,String routingkey,EventProcesserTopic ept) throws IOException, ShutdownSignalException, ConsumerCancelledException, InterruptedException{ 44 | // 声明转发器 45 | channel.exchangeDeclare(exchagnes, "topic"); 46 | // 随机生成一个队列 47 | String queueName = channel.queueDeclare().getQueue(); 48 | //接收所有与kernel相关的消息 49 | channel.queueBind(queueName, exchagnes, routingkey); 50 | logger.info("[*] Waiting for messages about topic. To exit press CTRL+C"); 51 | QueueingConsumer consumer = new QueueingConsumer(channel); 52 | channel.basicConsume(queueName, true, consumer); 53 | while (true) { 54 | QueueingConsumer.Delivery delivery = consumer.nextDelivery(); 55 | Object message = cf.deSerialize(delivery.getBody()); 56 | ept.process(message); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/cs/basic/mq/topic/TopicProducter.java: -------------------------------------------------------------------------------- 1 | package org.cs.basic.mq.topic; 2 | 3 | import java.io.IOException; 4 | 5 | import org.cs.basic.mq.global.CodecFactory; 6 | import org.cs.basic.mq.global.EventControlConfig; 7 | import org.cs.basic.mq.global.HessionCodecFactory; 8 | import org.cs.basic.mq.util.ConnectionUtil; 9 | 10 | import com.rabbitmq.client.Channel; 11 | 12 | /** 13 | * 主题订阅生产者 14 | * @author Mr.Cheng 15 | * @since 2016/11/29 15:57 16 | * 17 | */ 18 | public class TopicProducter { 19 | private Channel channel; 20 | private CodecFactory cf; 21 | public TopicProducter(){}; 22 | private ConnectionUtil connection; 23 | public TopicProducter(EventControlConfig config) throws IOException{ 24 | connection=new ConnectionUtil(config); 25 | channel=connection.getChannel(); 26 | cf=new HessionCodecFactory(); 27 | } 28 | /** 29 | * 发送方法 30 | * @param exchanges 31 | * @param routingkey 32 | * @param obj 对象 33 | * @throws IOException 34 | */ 35 | public void send(String exchanges,String routingkey,Object obj) throws IOException{ 36 | // 声明转发器 37 | channel.exchangeDeclare(exchanges, "topic"); 38 | byte[] msg=cf.serialize(obj); 39 | channel.basicPublish(exchanges, routingkey, null, msg); 40 | channel.close(); 41 | connection.close(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/cs/basic/mq/util/ConnectionUtil.java: -------------------------------------------------------------------------------- 1 | package org.cs.basic.mq.util; 2 | 3 | import java.io.IOException; 4 | 5 | import org.cs.basic.mq.global.EventControlConfig; 6 | 7 | import com.rabbitmq.client.Channel; 8 | import com.rabbitmq.client.Connection; 9 | import com.rabbitmq.client.ConnectionFactory; 10 | /** 11 | * 连接工具类 12 | * @author Mr.Cheng 13 | * @since 2016/11/29 15:55 14 | */ 15 | public class ConnectionUtil { 16 | private ConnectionFactory factory; 17 | private Connection connection; 18 | public ConnectionUtil(EventControlConfig config){ 19 | if(factory==null){ 20 | synchronized (ConnectionUtil.class){ 21 | if(null == factory){ 22 | factory = new ConnectionFactory(); 23 | factory.setHost(config.getServerHost()); 24 | factory.setUsername(config.getUsername()); 25 | factory.setPassword(config.getPassword()); 26 | factory.setPort(config.getPort()); 27 | } 28 | } 29 | } 30 | } 31 | public Connection getConnection() throws IOException{ 32 | if(connection==null){ 33 | synchronized (ConnectionUtil.class){ 34 | if(connection==null){ 35 | connection=factory.newConnection(); 36 | } 37 | } 38 | } 39 | return connection; 40 | } 41 | public Channel getChannel() throws IOException{ 42 | if(connection==null){ 43 | getConnection(); 44 | } 45 | return connection.createChannel(); 46 | } 47 | 48 | public void close() throws IOException{ 49 | if(connection!=null){ 50 | connection.close(); 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/cs/basic/mq/util/ObjectAndByte.java: -------------------------------------------------------------------------------- 1 | package org.cs.basic.mq.util; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.ObjectInputStream; 6 | import java.io.ObjectOutputStream; 7 | 8 | public class ObjectAndByte { 9 | public static Object ByteToObject(byte[] bytes) { 10 | Object obj = null; 11 | try { 12 | // bytearray to object 13 | ByteArrayInputStream bi = new ByteArrayInputStream(bytes); 14 | ObjectInputStream oi = new ObjectInputStream(bi); 15 | 16 | obj = oi.readObject(); 17 | bi.close(); 18 | oi.close(); 19 | } catch (Exception e) { 20 | System.out.println("translation" + e.getMessage()); 21 | e.printStackTrace(); 22 | } 23 | return obj; 24 | } 25 | public static byte[] ObjectToByte(java.lang.Object obj) { 26 | byte[] bytes = null; 27 | try { 28 | // object to bytearray 29 | ByteArrayOutputStream bo = new ByteArrayOutputStream(); 30 | ObjectOutputStream oo = new ObjectOutputStream(bo); 31 | oo.writeObject(obj); 32 | 33 | bytes = bo.toByteArray(); 34 | 35 | bo.close(); 36 | oo.close(); 37 | } catch (Exception e) { 38 | System.out.println("translation" + e.getMessage()); 39 | e.printStackTrace(); 40 | } 41 | return bytes; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/org/cs/basic/mq/test/People.java: -------------------------------------------------------------------------------- 1 | package org.cs.basic.mq.test; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | public class People implements Serializable { 7 | private int id; 8 | private String name; 9 | private boolean male; 10 | private People spouse; 11 | private List friends; 12 | public int getId() { 13 | return id; 14 | } 15 | public void setId(int id) { 16 | this.id = id; 17 | } 18 | public String getName() { 19 | return name; 20 | } 21 | public void setName(String name) { 22 | this.name = name; 23 | } 24 | public boolean isMale() { 25 | return male; 26 | } 27 | public void setMale(boolean male) { 28 | this.male = male; 29 | } 30 | public People getSpouse() { 31 | return spouse; 32 | } 33 | public void setSpouse(People spouse) { 34 | this.spouse = spouse; 35 | } 36 | public List getFriends() { 37 | return friends; 38 | } 39 | public void setFriends(List friends) { 40 | this.friends = friends; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | // TODO Auto-generated method stub 46 | return "People[id="+id+",name="+name+",male="+male+"]"; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/org/cs/basic/mq/test/RabbitMqMessageTest.java: -------------------------------------------------------------------------------- 1 | package org.cs.basic.mq.test; 2 | 3 | import java.io.IOException; 4 | 5 | import org.cs.basic.mq.consumer.EventProcesser; 6 | import org.cs.basic.mq.consumer.EventProcesserRPC; 7 | import org.cs.basic.mq.global.DefaultEventController; 8 | import org.cs.basic.mq.global.EventControlConfig; 9 | import org.cs.basic.mq.producer.EventTemplate; 10 | import org.junit.Before; 11 | import org.junit.Test; 12 | 13 | /** 14 | * 15 | * Description: 对消息进行设置测试 16 | * @type Test 17 | * @author Mr.Cheng 18 | * @date 2017年2月17日 19 | * @time 上午10:26:48 20 | * 21 | */ 22 | public class RabbitMqMessageTest { 23 | private String defaultExchange = "EXCHANGE_DIRECT_YOTIME"; 24 | private String timeExchange="EXCHANGE_TIME_YOTIME"; 25 | private DefaultEventController controller; 26 | private EventTemplate eventTemplate; 27 | 28 | 29 | 30 | @Before 31 | public void init() throws IOException{ 32 | //如果要队列一个一个出必须设置为1,1 33 | EventControlConfig config2 = new EventControlConfig("192.168.0.19","admin","admin",1,1); 34 | controller = DefaultEventController.getInstance(config2); 35 | eventTemplate = controller.getEopEventTemplate(); 36 | // controller.add("Q_T_Message_Expiration", defaultExchange,new MessagePriority()); 37 | // controller.start(); 38 | } 39 | 40 | @Test 41 | public void testPrintln(){ 42 | while(true){ 43 | 44 | } 45 | } 46 | /** 47 | * 测试消息过期时间 48 | * @throws Exception 49 | */ 50 | @Test 51 | public void testExpiration() throws Exception{ 52 | eventTemplate.send("Q_T_Message_Expiration", defaultExchange, "hello world!", 8000, 0); 53 | } 54 | 55 | @Test 56 | public void testPriority() throws Exception{ 57 | for(int i=10;i>0;i--){ 58 | eventTemplate.send("Q_T_Message_Expiration", defaultExchange, "我的优先级为:"+i,0,i); 59 | } 60 | } 61 | 62 | @Test 63 | public void testDelay() throws Exception{ 64 | eventTemplate.send("Q_T_Message_Delay", defaultExchange, "Q_T_Message_Delay_C", timeExchange, "Q_T_Message_Delay", "你好",8000,0); 65 | } 66 | /** 67 | * 68 | * Description:消息优先级测试 69 | * @type 70 | * @author Mr.Cheng 71 | * @date 2017年2月17日 72 | * @time 上午10:50:05 73 | * 74 | */ 75 | class MessagePriority implements EventProcesser{ 76 | public void process(Object e) { 77 | try { 78 | Thread.sleep(1000); 79 | System.out.println(e); 80 | } catch (InterruptedException e1) { 81 | e1.printStackTrace(); 82 | } 83 | 84 | } 85 | 86 | } 87 | 88 | public RabbitMqMessageTest() { 89 | // TODO Auto-generated constructor stub 90 | } 91 | 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/test/java/org/cs/basic/mq/test/RabbitMqTest.java: -------------------------------------------------------------------------------- 1 | package org.cs.basic.mq.test; 2 | 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import org.cs.basic.mq.consumer.EventProcesser; 8 | import org.cs.basic.mq.consumer.EventProcesserRPC; 9 | import org.cs.basic.mq.global.DefaultEventController; 10 | import org.cs.basic.mq.global.EventControlConfig; 11 | import org.cs.basic.mq.producer.EventTemplate; 12 | import org.junit.After; 13 | import org.junit.Assert; 14 | import org.junit.Before; 15 | import org.junit.Test; 16 | import org.springframework.amqp.core.ReceiveAndReplyCallback; 17 | 18 | public class RabbitMqTest { 19 | private String defaultHost = "192.168.0.19"; 20 | 21 | private String defaultExchange = "EXCHANGE_DIRECT_YOTIME"; 22 | 23 | private String defaultQueue = "QUEUE_TEST1"; 24 | 25 | private DefaultEventController controller; 26 | 27 | private EventTemplate eventTemplate; 28 | 29 | @Before 30 | public void init() throws IOException{ 31 | // EventControlConfig config = new EventControlConfig(defaultHost); 32 | // EventControlConfig config2 = new EventControlConfig("192.168.0.19","admin","admin"); 33 | 34 | controller = DefaultEventController.getInstance(config2); 35 | eventTemplate = controller.getEopEventTemplate(); 36 | // controller.add("QUEUE_TEST2", "EXCHANGE_TIME_YOTIME","Q_TIME_TEST",new ApiProcessEventProcessor2()); 37 | // controller.add("QUEUE_TEST1", defaultExchange, new ApiProcessEventProcessorRPC()); 38 | // controller.add("QUEUE_TEST4", defaultExchange,"routingKey",new ApiProcessEventProcessor2()); 39 | // controller.add("QUEUE_TEST5", defaultExchange,new ApiProcessEventProcessor2()); 40 | // controller.add("Q_TEST", defaultExchange,new ApiProcessEventProcessor2()); 41 | // controller.start(); 42 | } 43 | 44 | @Test 45 | public void sendString() throws Exception{ 46 | // System.out.println("test异步"); 47 | // Object obj=eventTemplate.sendAndReceive("QUEUE_TEST1", defaultExchange, "hello world"); 48 | // eventTemplate.send("Q_TIME_TEST", defaultExchange,"QUEUE_TEST2","EXCHANGE_TIME_YOTIME","Q_TIME_TEST","hello world"); 49 | // eventTemplate.send("QUEUE_TEST4", defaultExchange,"routingKey","hello world"); 50 | eventTemplate.send("QUEUE_TEST5", defaultExchange, "hello world",8000); 51 | int i=0; 52 | // while(true){ 53 | // i++; 54 | // eventTemplate.send("Q_TEST", defaultExchange, i+":hello world"); 55 | // Thread.sleep(1000); 56 | // } 57 | // System.out.println("test异步"); 58 | // System.out.println("返回"+obj); 59 | } 60 | 61 | @Test 62 | public void sendObject() throws Exception{ 63 | // eventTemplate.send(defaultQueue, defaultExchange, mockObj()); 64 | } 65 | 66 | /* @Test 67 | public void sendTemp() throws Exception, InterruptedException{ 68 | String tempExchange = "EXCHANGE_DIRECT_TEST_TEMP";//以前未声明的exchange 69 | String tempQueue = "QUEUE_TEST_TEMP";//以前未声明的queue 70 | eventTemplate.send(tempQueue, tempExchange, mockObj()); 71 | //发送成功后此时不会接受到消息,还需要绑定对应的消费程序 72 | controller.add(tempQueue, tempExchange, new ApiProcessEventProcessor()); 73 | } */ 74 | 75 | @After 76 | public void end() throws InterruptedException{ 77 | Thread.sleep(2000); 78 | } 79 | 80 | private People mockObj(){ 81 | People jack = new People(); 82 | jack.setId(1); 83 | jack.setName("JACK"); 84 | jack.setMale(true); 85 | 86 | List friends = new ArrayList(); 87 | friends.add(jack); 88 | People hanMeiMei = new People(); 89 | hanMeiMei.setId(1); 90 | hanMeiMei.setName("韩梅梅"); 91 | hanMeiMei.setMale(false); 92 | hanMeiMei.setFriends(friends); 93 | 94 | People liLei = new People(); 95 | liLei.setId(2); 96 | liLei.setName("李雷"); 97 | liLei.setMale(true); 98 | liLei.setFriends(friends); 99 | liLei.setSpouse(hanMeiMei); 100 | hanMeiMei.setSpouse(liLei); 101 | return hanMeiMei; 102 | } 103 | 104 | class ApiProcessEventProcessorRPC implements EventProcesserRPC{ 105 | public Object process(Object e) { 106 | System.out.println("我进自定义rpc方法咯"); 107 | People cs = new People(); 108 | cs.setName("cs"); 109 | return mockObj(); 110 | } 111 | } 112 | class ApiProcessEventProcessor2 implements EventProcesser{ 113 | public void process(Object e) { 114 | try { 115 | Thread.sleep(100); 116 | System.out.println("我进自定义方法咯:"+e); 117 | } catch (InterruptedException e1) { 118 | // TODO Auto-generated catch block 119 | e1.printStackTrace(); 120 | } 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | ### set log levels ### 2 | log4j.rootLogger =ERROR, stdout 3 | 4 | ### \u8F93\u51FA\u5230\u63A7\u5236\u53F0 ### 5 | log4j.appender.stdout = org.apache.log4j.ConsoleAppender 6 | log4j.appender.stdout.Target = System.out 7 | log4j.appender.stdout.layout = org.apache.log4j.PatternLayout 8 | log4j.appender.stdout.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n 9 | 10 | ### \u8F93\u51FA\u5230\u65E5\u5FD7\u6587\u4EF6 ### 11 | log4j.appender.D = org.apache.log4j.DailyRollingFileAppender 12 | log4j.appender.D.File = logs/error.log \#\# \u5F02\u5E38\u65E5\u5FD7\u6587\u4EF6\u540D 13 | log4j.appender.D.Append = true 14 | log4j.appender.D.Threshold = ERROR \#\# \u53EA\u8F93\u51FAERROR\u7EA7\u522B\u4EE5\u4E0A\u7684\u65E5\u5FD7\!\!\! 15 | log4j.appender.D.layout = org.apache.log4j.PatternLayout 16 | log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n 17 | --------------------------------------------------------------------------------