RabbitMq基础大全详解
首先创建一个maven项目
导入spring所依赖的jar包(略)
<dependency>
<groupId>org.springframework.amqpgroupId>
<artifactId>spring-rabbitartifactId>
<version>1.2.0.RELEASEversion>
dependency>
1.声明交换机,队列,绑定等操作(也就是为RabbitTemplate的使用提供服务)
我们使用配置类的方式(配置类比xml格式更加直观)
注意所倒的包
RabbitConfig.java
package com.storm.config;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Created by StormEnum on 2019/3/22.
*/
@Configuration
public class RabbitConfig {
@Bean
public ConnectionFactory connectionFactory(){
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setAddresses("192.168.50.129:5672");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
connectionFactory.setVirtualHost("/");
return connectionFactory;
}
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
rabbitAdmin.setAutoStartup(true); //开启(true),否则spring容器不会加载
return rabbitAdmin;
}
}
/**
* Created by StormEnum on 2019/3/22.
*/
@Controller
public class RabbitController {
@Autowired
private RabbitAdmin rabbitAdmin;
@RequestMapping("test")
@ResponseBody
public String rabbitTest(){
//第一种写法
rabbitAdmin.declareExchange(new DirectExchange("rabbit.Admin.Direct.Exchange"));
rabbitAdmin.declareQueue(new Queue("rabbit.Admin.Queue"));
rabbitAdmin.declareBinding(
new Binding(
"rabbit.Admin.Queue",
Binding.DestinationType.QUEUE,
"rabbit.Admin.Direct.Exchange",
"rabbit.Admin.Queue",
new HashMap<>()
)
);
//第二种写法,我看网上有人说此处不需要声明Queue和Exchange(new 出来就可以来),我感觉也是!,
//但我没试验成功,最后我还是老老实实的声明了一下
rabbitAdmin.declareExchange(new TopicExchange("rabbit.Admin.topic.Exchange"));
rabbitAdmin.declareQueue(new Queue("rabbit.Admin.Queue2"));
rabbitAdmin.declareBinding(
BindingBuilder.bind(new Queue("rabbit.Admin.Queue2",false))
.to(new TopicExchange("rabbit.Admin.topic.Exchange",false,false))
.with("rabbit.#")
);
//注意:fanout因为没有路由规则,因此不需要 with(routing-key)
return "那就这样吧";
}
}
1.RabbitTemplate:消息模版,
2.RabbitTemplate是RabbitMq和SpringAMQP整合时,发送消息的核心类
3.RabbitTemplate提供了丰富的发送消息方法:
可靠性投递消息方法
回调监听消息接口ConfirmCallback
返回值确认接口ReturnCallback
等······
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
return rabbitTemplate;
}
/**
* Created by StormEnum on 2019/3/22.
*/
@Controller
public class RabbitController {
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private RabbitTemplate rabbitTemplate;
@RequestMapping("test")
@ResponseBody
public String rabbitTest() throws Exception{
rabbitAdmin.declareExchange(new TopicExchange("rabbit.Admin.topic.Exchange"));
rabbitAdmin.declareQueue(new Queue("rabbit.Admin.Queue2"));
rabbitAdmin.declareBinding(
BindingBuilder.bind(new Queue("rabbit.Admin.Queue2",false))
.to(new TopicExchange("rabbit.Admin.topic.Exchange",false,false))
.with("rabbit.#")
);
//根据需要设置此参数,创建一个Message,并添加额外的参数(properties)
//在此回顾一下:message包含body和properties(properties可以不设置)
MessageProperties messageProperties = new MessageProperties();
messageProperties.getHeaders().put("闫","创业");
Message message = new Message("你好".getBytes(),messageProperties);
//发送消息
//rabbitTemplate.convertAndSend("rabbit.Admin.topic.Exchange", "rabbit.#", message);
rabbitTemplate.convertAndSend("rabbit.Admin.topic.Exchange", "rabbit.someThing", message, new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
//在此可以添加额外的设置,也可以修改之前的设置
System.out.println("添加额外的设置+也可以修改之前的设置");
message.getMessageProperties().getHeaders().put("闫","添加额外的信息");
return message;
}
});
return "那就这样吧";
}
}
1.简单消息监听容器
2.可以监听队列(支持多个队列)、自动启动、自动声明功能
3.可以设置事务特性、事务管理器、事务属性、事务容量、是否开启事务、消息回滚
4.可以设置消费者数量、最大最小数量、批量消费
5.设置消息确认模式、是否重回队列、异常捕获handler函数
6.设置消费者标签(deliveryTag)生成策略、是否独占模式、消费者模式等
7.设置具体的监听类、消息转换器等
8.SimpleMessageListenerContainer可以进行动态设置,比如在运行中的应用可以动态的修改其消费者的数量,接收消费的模式等
@Bean
public SimpleMessageListenerContainer simpleMessageListenerContainer(ConnectionFactory connectionFactory){
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
//可以监听多个队列
container.setQueues(queue001(),queue002(),queue003());
//当前消费者为 1 个(在SpringBoot中可以设置最大消费者数量)
container.setConcurrentConsumers(1);
//是否重回队列
container.setDefaultRequeueRejected(false);
//签收模式
container.setAcknowledgeMode(AcknowledgeMode.AUTO);
//监听
container.setMessageListener(new ChannelAwareMessageListener() {
@Override
public void onMessage(Message message, Channel channel) throws Exception {
String msg = new String(message.getBody());
System.out.println("接收到的消息是--------------"+msg);
}
});
return container;
}
或者使用MessageListenerAdapter自定义消息监听,使用委托类实现
@Bean
public SimpleMessageListenerContainer simpleMessageListenerContainer(ConnectionFactory connectionFactory){
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
container.setQueues(queue001(),queue002(),queue003());
container.setConcurrentConsumers(1);
//是否重回队列
container.setDefaultRequeueRejected(false);
//签收模式
container.setAcknowledgeMode(AcknowledgeMode.AUTO);
MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());
//adapter.setDefaultListenerMethod("consumerListener"); 对代理监听类中的默认方法进行更改
container.setMessageListener(adapter);
return container;
}
代理类:里面的方法名是在MessageListenerAdapter 底层定义的,参数列表也是底层定义。
当然了我们可以进行更改!
/**
* Created by StormEnum on 2019/3/23.
*/
public class MessageDelegate {
public void handlerMessage(byte[] messageBody){
System.out.println("默认的方法---消息内容---------"+new String(messageBody));
}
}
更改代理类中的默认方法:
//对代理监听类中的默认方法进行更改
adapter.setDefaultListenerMethod("consumerListener");
那么代理类就可以设置为:
/**
* Created by StormEnum on 2019/3/23.
*/
public class MessageDelegate {
public void consumerListener(byte[] messageBody){
System.out.println("默认的方法---消息内容---------"+new String(messageBody));
}
}
更改代理类中的参数:
//对代理监听类中的参数进行更改,StringmessageConverter是我们自己创建的类
adapter.setMessageConverter(new StringMessageConverter());
StringmessageConverter(自己创建的一个类)
实现 MessageConverter 接口,重写MessageConverter的方法
并对StringmessageConverter 转换类进行满足自己需求的改造
/**
* Created by StormEnum on 2019/3/23.
*/
public class StringMessageConverter implements MessageConverter {
/**
*TODO:java对象转换为message对象
*/
@Override
public Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException {
return new Message(object.toString().getBytes(),messageProperties);
}
/**
*TODO:message对象转换为java对象
*/
@Override
public Object fromMessage(Message message) throws MessageConversionException {
String contentType = message.getMessageProperties().getContentType();
if(contentType != null && contentType.contains("消息中的参数---根据消息进行设置")){
return new String(message.getBody());
}
return message.getBody();
}
}
在SpringBoot中:我们也可以通过适配器将队列和代理类中的方法进行 一 一(yi yi)绑定
在SimpleMessageListenerContainer中已经使用过了
我们在发送消息的时候,正常情况下,消息是已二进制的形式进行传输的,如果期望内部帮我们转换,或者指定自定义转换器,就需要使用MessageConverter
在SimpleMessageListenerContainer中进行了简单的使用(将message对象转换为String,将String转换为message),还支持有json(内部转换),file(自定义转换)······等格式转换,