示例说明
将主题交换机应用到我们的日志系统中。在开始工作前,我们假设日志的路由键由两个单词组成,路由键看起来是这样的:service.severity代码跟上一篇教程差不多
假设有 order,user,email 服务,日志级别有error,info,warning。
生产者:服务和日志级别的排列组合作为routing key(如 order.email,order.info,order.warning,user.error,user.info .....),分别发送3条日志。
消费者:定义消费者,A、接收所有error 级别日志( *.error);B、接收 order 服务的日志(order.*),C、接收user服务和info级别的日志(user.* *.info),D、接收所有的日志(#)
请参考 “rabbitmq 主题交换机java 实现”的示例说明( http://blog.csdn.net/convict_eva/article/details/52315474)
项目依赖:
<dependency> <groupId>org.springframework.amqpgroupId> <artifactId>spring-rabbitartifactId> <version>1.6.1.RELEASEversion> dependency> <dependency> <groupId>org.springframework.amqpgroupId> <artifactId>spring-amqpartifactId> <version>1.6.1.RELEASEversion> dependency> <dependency> <groupId>com.rabbitmqgroupId> <artifactId>amqp-clientartifactId> <version>3.6.1version> dependency>目录结构
MsgHandler 消息处理方法实现
Recv 启动消息接收
Send 消息发送
applicationContext-consumer-sync.xml 消息接收者配置
applicationContext-producer-sync.xml 消息发送者配置
rabbitmq.properties rabbitmq 的属性配置
代码说明
配置文件
rabbitmq.host=192.168.174.128 rabbitmq.port=5672 rabbitmq.username=convict_eva rabbitmq.password=convict_eva rabbitmq.virtualHost=/convict_eva #队列名 rabbitmq.queue.a=spring_queue_a rabbitmq.queue.b=spring_queue_b rabbitmq.queue.c=spring_queue_c rabbitmq.queue.d=spring_queue_d #队列对应的routing key rabbitmq.queue.a.routing=*.error rabbitmq.queue.b.routing=order.* rabbitmq.queue.c.routing=user.* rabbitmq.queue.c.routing_2=*.info rabbitmq.queue.d.routing=# #发送消息的路由 rabbitmq.msg.routing=user.error #交换机名称 rabbitmq.exchangeName=topic_exchage
消息发送者
加载配置文件
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /> <property name="ignoreResourceNotFound" value="true" /> <property name="locations"> <list> <value>classpath*:/rabbitmq.propertiesvalue> list> property> bean>定义连接工厂
<bean id="connectionFactory" class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory"> <property name="host" value="${rabbitmq.host}" /> <property name="port" value="${rabbitmq.port}" /> <property name="username" value="${rabbitmq.username}" /> <property name="password" value="${rabbitmq.password}" /> <property name="virtualHost" value="${rabbitmq.virtualHost}" /> <property name="cacheMode" value="CHANNEL"/> <property name="channelCacheSize" value="10"/> <property name="channelCheckoutTimeout" value="200"/> <property name="connectionLimit" value="50"/> bean>定义队列
<bean id="springQueueA" class="org.springframework.amqp.core.Queue"> <constructor-arg name="name" value="${rabbitmq.queue.a}"/> <property name="shouldDeclare" value="false"/> bean> <bean id="springQueueB" class="org.springframework.amqp.core.Queue"> <constructor-arg name="name" value="${rabbitmq.queue.b}"/> <property name="shouldDeclare" value="false"/> bean> <bean id="springQueueC" class="org.springframework.amqp.core.Queue"> <constructor-arg name="name" value="${rabbitmq.queue.c}"/> <property name="shouldDeclare" value="false"/> bean> <bean id="springQueueD" class="org.springframework.amqp.core.Queue"> <constructor-arg name="name" value="${rabbitmq.queue.d}"/> <property name="shouldDeclare" value="false"/> bean>定义exchange
<bean id="exchange" class="org.springframework.amqp.core.TopicExchange"> <constructor-arg name="name" value="${rabbitmq.exchangeName}"/> <constructor-arg name="durable" value="true"/> <constructor-arg name="autoDelete" value="false"/> bean>exchange 和队列的绑定
<bean id="arguments" class="java.util.HashMap"/> <bean id="bindingA" class="org.springframework.amqp.core.Binding"> <constructor-arg name="destination" value="${rabbitmq.queue.a}"/> <constructor-arg name="destinationType" value="QUEUE"/> <constructor-arg name="exchange" value="${rabbitmq.exchangeName}"/> <constructor-arg name="routingKey" value="${rabbitmq.queue.a.routing}"/> <constructor-arg name="arguments" ref="arguments"/> bean>rabbitmq 同步访问模板定义,用于发送和接收消息
<bean id="rabbitTemplate" class="org.springframework.amqp.rabbit.core.RabbitTemplate"> <constructor-arg name="connectionFactory" ref="connectionFactory"/> <property name="exchange" value="${rabbitmq.exchangeName}"/> <property name="routingKey" value="${rabbitmq.msg.routing}"/> bean>发送消息代码实现(Send)
public static void main(String[] args) throws Exception{ AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-producer-sync.xml"); RabbitTemplate template = ctx.getBean(RabbitTemplate.class); //可以设置发送消息的routing key // template.setRoutingKey("user.error"); String msg; for(int i=0;i<3;i++){ msg = "Hello World!"+i; template.convertAndSend(msg); System.out.println(msg); } ctx.destroy(); }
消费者
加载配置文件和定义连接工厂就不用说了,和生产者是一样的
<bean id="messageConverter"
class="org.springframework.amqp.support.converter.SimpleMessageConverter">
bean>
<bean id="receiveHandler" class="com.convict.rabbitmq.spring.sync.MsgHandler"/>
<bean id="receiveListenerAdapter"
class="org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter">
<constructor-arg ref="receiveHandler" />
<property name="messageConverter" ref="messageConverter"/>
bean>
<bean id="listenerContainer"
class="org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer">
<property name="queueNames" value="${rabbitmq.queue.a},${rabbitmq.queue.c}">property>
<property name="connectionFactory" ref="connectionFactory">property>
<property name="messageListener" ref="receiveListenerAdapter">property>
bean>
消息处理方法实现
@Override public void onMessage(Message message, Channel channel) throws Exception { System.out.println("consumer receive massage:" + new String(message.getBody())+"______routing key : "+message.getMessageProperties().getReceivedRoutingKey()); //channel.basicAck(message.getMessageProperties().getDeliveryTag(),false); } /** * MessageListenerAdapter: * * 如果返回的不是null,就把返回的值当着一个消息发送到接收到消息的exchange,并使用消息的replyTo属性作为routing key。 * 原文如下: * If a target listener method returns a non-null object (typically of a message content type such as *String or byte array), it will get wrapped in a Rabbit
Message and sent to the exchange of * the incoming message with the routingKey that comes from the Rabbit ReplyTo property or via * {setResponseRoutingKey(String) specified routingKey}). * */ public void handleMassage(String msg){ System.out.println("consumer receive massage:" + msg); }
完整代码:http://download.csdn.net/detail/convict_eva/9620260
注:在路由绑定队列时,不能同时绑定多个routing key