StringAMQP入门
-
导入依赖
<!--AMQP依赖,包含RabbitMQ--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>
-
消息提供者(publisher)
-
在application.yml中添加相关配置
spring: rabbitmq: host: 121.199.23.164 #主机名 port: 5672 # 端口 virtual-host: / # 虚拟主机 username: itcast # 用户名 password: 123321 # 密码
-
测试
/** * StringAMQP的测试 */ @RunWith(SpringRunner.class) @SpringBootTest public class SpringAmqpTest { @Autowired private RabbitTemplate rabbitTemplate; @Test public void testSimpleQueue(){ String queueName = "simple.queue"; String message = "hello, spring amqp!"; rabbitTemplate.convertAndSend(queueName,message); System.out.println("发送成功!"); } }
-
-
消息消费者(comsumer)
-
在application.yml中添加相关配置
spring: rabbitmq: host: 121.199.23.164 #主机名 port: 5672 # 端口 virtual-host: / # 虚拟主机 username: itcast # 用户名 password: 123321 # 密码
-
书写配置类,编辑消费逻辑
@Component public class StringRabbitListener { @RabbitListener( queues = "simple.queue") public void listenerSimpleQueue(String msg){ System.out.println("接收到消息:【" + msg + "】"); } }
-
启动spring boot 启动类,测试。
-
注意:消息一旦消费就会从队列删除,RabbmitMQ没有消息回溯功能。
发布订阅-FanoutExchange
FanoutExchange会将接收到的消息路由到每一个跟其绑定的queue
- 在consumer 中创建配置类
@Configuration
public class FanoutConfig {
/**
* 声明交换机 itcast.fanout
* @return
*/
@Bean
public FanoutExchange fanoutExchange(){
return new FanoutExchange("itcast.fanout");
}
/**
* 声明 队列1 fanout.queue1
* @return
*/
@Bean
public Queue fanoutQueue1(){
return new Queue("fanout.queue1");
}
/**
* 绑定 队列1 到交换机
* @param fanoutQueue1
* @param fanoutExchange
* @return
*/
@Bean
public Binding binding(Queue fanoutQueue1,FanoutExchange fanoutExchange){
return BindingBuilder
.bind(fanoutQueue1)
.to(fanoutExchange);
}
/**
* 声明 队列1 fanout.queue2
* @return
*/
@Bean
public Queue fanoutQueue2(){
return new Queue("fanout.queue2");
}
/**
* 绑定 队列2 到交换机
* @param fanoutQueue2
* @param fanoutExchange
* @return
*/
@Bean
public Binding binding2(Queue fanoutQueue2,FanoutExchange fanoutExchange){
return BindingBuilder
.bind(fanoutQueue2)
.to(fanoutExchange);
}
}
- 在consumer 中监听两个队列
@Component
public class StringRabbitListener {
@RabbitListener( queues = "fanout.queue1")
public void listenerFanoutQueue1(String msg){
System.out.println("接收到消息1:【" + msg + "】");
}
@RabbitListener( queues = "fanout.queue2")
public void listenerFanoutQueue2(String msg){
System.out.println("接收到消息2:【" + msg + "】");
}
}
- 在publisher 中编写消息提供
@Test
public void testSendFanoutExchange() throws InterruptedException {
// 交换机名称
String exchangeName = "itcast.fanout";
String message = "fanout.queue";
// 消息
rabbitTemplate.convertAndSend(exchangeName,"",message);
}
发布订阅-DirectExchange
DirectExchange 会将接收到的消息根据规则路由到指定的 queue ,因此成为路由模式(routes)
- 每一个Queue 都与Exchange 设置一个BindingKey
- 发布者发送消息时,指定消息的RoutingKey
- Exchange 将消息路由到BindingKey 与消息RoutingKey一致的队列
基于@RabbitListener注解来声明队列和交换机的方式:
- 在consumer 编写listener类
@Component
public class StringRabbitListener {
@RabbitListener(bindings = @QueueBinding(
value = @Queue("direct.queue1"),
exchange = @Exchange("itcast.direct"),
key = {"red","blue"}
))
public void testDirectQueue1(String msg){
System.out.println("接收到消息direct.queue1为:【" + msg + "】");
}
@RabbitListener(bindings = @QueueBinding(
value = @Queue("direct.queue2"), //交换机名字
exchange = @Exchange(value = "itcast.direct",type = ExchangeTypes.DIRECT), //队列名称; 默认就是direct
key = {"red","yellow"} //指定的key名
))
public void testDirectQueue2(String msg){
System.out.println("接收到消息direct.queue2为:【" + msg + "】");
}
}
- 在publisher 中编写测试
@Test
public void testSendDirectExchange() throws InterruptedException {
// 交换机名称
String exchangeName = "itcast.direct";
String message = "hello , red";
// 消息 //red 就是指定的key名称
rabbitTemplate.convertAndSend(exchangeName,"red",message);
}
发布订阅-TopicExchange
TopicExchange和DirectExchange类似,区别在于routingkey必须是多个单词的列表,并且以 . 分割
Queue与Exchange指定BindingKey时可以使用通配符:
- # 代指0个或多个单词
- * 代值一个单词
在consumer 编写listener类
@Component
public class StringRabbitListener {
@RabbitListener(bindings = @QueueBinding(
value = @Queue("direct.topic1"), //交换机名字
exchange = @Exchange(value = "itcast.topic",type = ExchangeTypes.TOPIC), //队列名称
key = "china.#" //指定的key名
))
public void testTopicQueue1(String msg){
System.out.println("接收到消息topic.topic1为:【" + msg + "】");
}
@RabbitListener(bindings = @QueueBinding(
value = @Queue("direct.topic2"), //交换机名字
exchange = @Exchange(value = "itcast.topic",type = ExchangeTypes.TOPIC), //队列名称
key = "#.news" //指定的key名
))
public void testTopicQueue2(String msg){
System.out.println("接收到消息topic.topic2为:【" + msg + "】");
}
}
在publisher测试
@Test
public void testSendTopicExchange() throws InterruptedException {
// 交换机名称
String exchangeName = "itcast.topic";
String message = "qinqin公司上市了!";
// 消息
rabbitTemplate.convertAndSend(exchangeName,"china.news",message);
}
消息转换器
Spring的对消息对象的处理是由org.springframeworkamqp.support.converter.MessageConverter来处理的。而默认实现是SimpleMessageConverter,基于JDK的ObjectOutputStream完成序列化。
如果要修改只需要定义一个MessageConverter 类型的Bean即可。推荐用SON方式序列化,步骤如下:
- 在publisher 的pom导入依赖:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.9.10</version>
</dependency>
-
在 启动类中加入声明MessageConverter
注意:导入的包为import org.springframework.amqp.support.converter.MessageConverter
@Bean
public MessageConverter MessageConverter(){
return new Jackson2JsonMessageConverter();
}
- 编写消息提供者
@Test
public void testSendObjctQueue() throws InterruptedException {
// 交换机名称
String exchangeName = "itcast.object";
Map<String, Object> msg = new HashMap<>();
msg.put("name","柳岩");
msg.put("age","18");
// 消息
rabbitTemplate.convertAndSend(exchangeName,msg);
}
- 在consumer 中导入依赖:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.9.10</version>
</dependency>
-
在 启动类中加入声明MessageConverter
注意:导入的包为import org.springframework.amqp.support.converter.MessageConverter
@Bean
public MessageConverter MessageConverter(){
return new Jackson2JsonMessageConverter();
}
- 定义消费者,监听消息
@RabbitListener( queues = "itcast.object")
public void listenerObjectQueue(Map<String,Object> msg){ //注意消费者的类型
System.out.println("接收到消息itcast.object为::【" + msg + "】");
}