我们接着来编写Consumer,回到我们的代码当中,打开我们的topic-consumer,配置文件我们已经改完了,
先放到这里,看我们的代码,我们先改第一个InfoReceiver,InfoReceive这一块我们需要改什么呢,还是@RabbitListener这,
首先第一个,像队列的名称我们不需要动,队列名称我们还是叫log.info,我们给他准备了三个队列,log.info,log.error,
和全日志的队列,这两个我们都不要动,所以这里不用动,交换器我们也不用动,我们已经把后面的value改成log.topic了
mq.config.exchange=log.topic
但是这里得改,这个type得改
type=ExchangeTypes.TOPIC
现在这个type里面给定的还是direct交换器,我们要把它改成TOPIC,所以一定要注意,然后接下来就是key,我们用的是完全匹配
的路由key,那么我们在这个交换器,在这个队列当中,接收什么样的消息呢,只要是你log.info的,不管你是user的还是product的,
还是order的,只要是log.info的,都会进入到这里,那么前面的前缀,就得去匹配,所以我们这个key就是*.log.info
看到了吗,也就是我们这个路由key,其实给的就是*.log.info,能明白吧,这样消息队列就会根据后缀进行模糊匹配,只要是后缀
相同的,就把消息发送到这个队列当中,那么这个队列是谁呢,就是我们的log.info了,这样我们就把一个infoReceive就改好了,
接下来还有Error,Error也是这样的,首先我们要把交换器类型改成Topic,其次是这个key,这个key我们看一下,是*.log.error,
拥有log.error的key,就会进入到这个队列当中
key="*.log.error"
注意这一块我是直接写死到里面的,我之所以这么做的目的呢,就是可以直观的看到怎么去写他的通配,其实如果我们是在真正的
开发过程当中,这些也是可以放到properties文件当中的,这样我们就设置了第二个消息队列的这样的一个路由key,接下来我们
是不是还有一个全日志队列,我们再copy一个,这个我们叫LogsReceiver,然后打开他,这里我们有什么要改的呢,看一下,配置文件,
这个队列名称,是不是已经改了
mq.config.queue.logs=log.all
这个在原本拷贝的例子里是没有的,要换成这个队列名称,然后其次就是他的交换器,交换器不用动,还是Topic,然后就是这个路由key,
在全日志的处理当中,只要你路由key含有log的消息,是不是都会进入到这里,所以这块我们得改成*.log.*
key="*.log.*"
只要你的路由key中含有log,都会进入到我们的全队列当中,这样我们这块就改完了,然后我们还有什么需要改动,现在这一块,
这块到底打印的是什么信息,这块我们还得改一下,这个我们是叫all receiver
public class LogsReceiver {
/**
* 接收消息的方法。采用消息队列监听机制
* @param msg
*/
@RabbitHandler
public void process(String msg){
System.out.println("......All........receiver: "+msg);
}
}
这表示消息队列打印的前缀,再加后面的消息,我们把这个copy一下,我们把这几个改一下
public class ErrorReceiver {
/**
* 接收消息的方法。采用消息队列监听机制
* @param msg
*/
@RabbitHandler
public void process(String msg){
System.out.println("......Error........receiver: "+msg);
}
}
这个是error,然后info
public class InfoReceiver {
/**
* 接收消息的方法。采用消息队列监听机制
* @param msg
*/
@RabbitHandler
public void process(String msg){
System.out.println("......Info........receiver: "+msg);
}
}
这样我们的Consumer的代码就写好了,然后我们把它整理到笔记当中,这个是info里面的代码,然后这里需要注意的,
一个是这个,type=ExchangeTypes.TOPIC,还有一个是key="*.log.info"这个,然后第二个,ErrorReceiver,把它copy下来
放到我们的笔记当中,然后这里需要注意的是,type=ExchangeTypes.TOPIC,还有一个是key,key="*.log.error",然后最后
一个是LogsReceiver,这里也是type=ExchangeTypes.TOPIC,还有key="*.log.*",这样我们的consumer代码就写好了,
接下来我们就测试我们的是否可用,回到我们的Provider当中,我们要去修改一下我们的测试代码,现在我们的代码
就不用while循环了,我们直接发送消息就行了,现在这个是UserSender,我们还有OrderSender,还有ProductSender,
都得注入进来,
@Autowired
private UserSender usersender;
@Autowired
private ProductSender productsender;
@Autowired
private OrderSender ordersender;
我们需要把ProductSender注入进来,然后还有一个,OrderSender,然后我们让这三个服务都去发送消息,
@Test
public void test1(){
this.usersender.send("UserSender.....");
this.productsender.send("ProductSender....");
this.ordersender.send("OrderSender......");
}
这样是12条消息,应该是12条消息,每个里面有四个,然后我们三个都发一遍,接下来我们就来测试一下,代码是否可用,
我们把接收者启动,就是topic-consumer,然后我们再去运行我们的测试类,运行我们的测试代码,我们观察控制台,这个时候
我们可以看到,消息拿到了,我们先看info的,这是我的info Receiver,
......All........receiver: user.log.debug.....UserSender.....
......Info........receiver: user.log.info.....UserSender.....
......Error........receiver: user.log.error.....UserSender.....
......Info........receiver: product.log.info.....ProductSender....
......Error........receiver: product.log.error.....ProductSender....
......All........receiver: user.log.info.....UserSender.....
......Info........receiver: order.log.info.....OrderSender......
......Error........receiver: order.log.error.....OrderSender......
......All........receiver: user.log.warn.....UserSender.....
......All........receiver: user.log.error.....UserSender.....
......All........receiver: product.log.debug.....ProductSender....
......All........receiver: product.log.info.....ProductSender....
......All........receiver: product.log.warn.....ProductSender....
......All........receiver: product.log.error.....ProductSender....
......All........receiver: order.log.debug.....OrderSender......
......All........receiver: order.log.info.....OrderSender......
......All........receiver: order.log.warn.....OrderSender......
......All........receiver: order.log.error.....OrderSender......
由于我们ALL当中配的是什么,我们配的是key="*.log.*",那么也就意味着,只要你的路由key当中,含有log,是不是都会进入到这个
队列当中,是不是都会进入到这个队列当中,那么这里的信息肯定是最多的,应该有几个,12条信息就对了,所以说呢,在*.log.*里面,
他就是把所有的消息都放在全日志的级别当中,所以以上我们通过这个案例,就演示了对Topic的一个使用,topic最大的一个特点是什么呢,
可以节省我们的队列,是某一部分的消息,可以对应一个队列,这样可以降低我们队列的一个数量,其实你细想这个问题也是这样的,
我这个队列只是记录log.info的信息,我管你是用户的log.info,还是商品的log.info,还是订单的log.info,只要是你产生的
log.info的信息,都放到我这个队列里就可以了,所以对于这样的一个需求呢,我们就得通过topic交换器来实现了,
并且配置这种通配的路由key,所以说topic的交换器呢,他也叫规则匹配,那个星号就是规则,测试代码我们也加进去了,
那么对于topic的交换器我们就讲解完了
4.0.0
com.learn
rabbitmq-topic-consumer
0.0.1-SNAPSHOT
jar
org.springframework.boot
spring-boot-starter-parent
1.5.12.RELEASE
UTF-8
UTF-8
1.8
3.0.9.RELEASE
2.2.2
org.springframework.boot
spring-boot-starter-amqp
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
spring.application.name=rabbitmq-topic-consumer
spring.rabbitmq.host=59.110.158.145
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
mq.config.exchange=log.topic
mq.config.queue.info=log.info
mq.config.queue.error=log.error
mq.config.queue.logs=log.all
package com.learn;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* 消息接收者
* @author Administrator
* @RabbitListener bindings:绑定队列
* @QueueBinding value:绑定队列的名称
* exchange:配置交换器
*
* @Queue value:配置队列名称
* autoDelete:是否是一个可删除的临时队列
*
* @Exchange value:为交换器起个名称
* type:指定具体的交换器类型
*/
@Component
@RabbitListener(
bindings=@QueueBinding(
value=@Queue(value="${mq.config.queue.info}",autoDelete="true"),
exchange=@Exchange(value="${mq.config.exchange}",type=ExchangeTypes.TOPIC),
key="*.log.info"
)
)
public class InfoReceiver {
/**
* 接收消息的方法。采用消息队列监听机制
* @param msg
*/
@RabbitHandler
public void process(String msg){
System.out.println("......Info........receiver: "+msg);
}
}
package com.learn;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* 消息接收者
* @author Administrator
* @RabbitListener bindings:绑定队列
* @QueueBinding value:绑定队列的名称
* exchange:配置交换器
*
* @Queue value:配置队列名称
* autoDelete:是否是一个可删除的临时队列
*
* @Exchange value:为交换器起个名称
* type:指定具体的交换器类型
*/
@Component
@RabbitListener(
bindings=@QueueBinding(
value=@Queue(value="${mq.config.queue.error}",autoDelete="true"),
exchange=@Exchange(value="${mq.config.exchange}",type=ExchangeTypes.TOPIC),
key="*.log.error"
)
)
public class ErrorReceiver {
/**
* 接收消息的方法。采用消息队列监听机制
* @param msg
*/
@RabbitHandler
public void process(String msg){
System.out.println("......Error........receiver: "+msg);
}
}
package com.learn;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* 消息接收者
* @author Administrator
* @RabbitListener bindings:绑定队列
* @QueueBinding value:绑定队列的名称
* exchange:配置交换器
*
* @Queue value:配置队列名称
* autoDelete:是否是一个可删除的临时队列
*
* @Exchange value:为交换器起个名称
* type:指定具体的交换器类型
*/
@Component
@RabbitListener(
bindings=@QueueBinding(
value=@Queue(value="${mq.config.queue.logs}",autoDelete="true"),
exchange=@Exchange(value="${mq.config.exchange}",type=ExchangeTypes.TOPIC),
key="*.log.*"
)
)
public class LogsReceiver {
/**
* 接收消息的方法。采用消息队列监听机制
* @param msg
*/
@RabbitHandler
public void process(String msg){
System.out.println("......All........receiver: "+msg);
}
}
package com.learn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class RabbitTopicConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(RabbitTopicConsumerApplication.class, args);
}
}