1、导入pom
<!--引入 rabbit依赖 amqp 高级消息队列协议-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2、配置类
#配置rabbitmq的 主机、端口、用户名、密码
spring.rabbitmq.host=192.168.56.10
spring.rabbitmq.port=5672
spring.rabbitmq.virtual-host=/
#账号密码配置类默认都是guest,此处可不配置
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
#开启发送端确认
spring.rabbitmq.publisher-confirms=true
#开启发送端消息抵达队列的确认
spring.rabbitmq.publisher-returns=true
#只要抵达队列,以异步发送优先回调我们这个 returnConfirm
spring.rabbitmq.template.mandatory=true
#手动ack消息
spring.rabbitmq.listener.simple.acknowledge-mode=manual
3、主启动开启rabbit功能
/**
* 使用rabbitmq
* 1、引入amqp 场景pom,RabbitAutoConfiguration 自动生效
* 2、给容器中自动配置了
* RabbitTemplate、AmqpAdmin、CacheConnectionFactory
* 3、配置文件,所有的属性绑定
* @ConfigurationProperties(prefix = "spring.rabbitmq")
* 4、@EnableRabbit 开启功能
* 5、监听消息,使用 @RabbitListener,必须有 @EnableRabbit
* @RabbitListener:类+方法(监听哪些队列即可)
* @RabbitHandler:标在方法上(重载区分不同的消息)
*/
@EnableRabbit
@EnableDiscoveryClient
@MapperScan("com.lian.gulimall.order.dao")
@SpringBootApplication
public class GulimallOrderApplication {
public static void main(String[] args) {
SpringApplication.run(GulimallOrderApplication.class, args);
}
}
4、AmqpAdmin
创建交换机和队列,并将队列和交换机绑定
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class GulimallOrderApplicationTests {
@Autowired
AmqpAdmin amqpAdmin;
/**
* 1、如何创建 Exchange、Queue、Binding
* 使用AmqpAdmin 进行创建
* 2、如何收发消息
*/
@Test
public void createExchange(){
//创建一个 direct 直接交换机
DirectExchange directExchange = new DirectExchange("hello-java-exchange",true,false);
//声明一个交换机
amqpAdmin.declareExchange(directExchange);
log.info("exchange[{}]创建成功","hello-java-exchange");
//声明一个队列
Queue queue = new Queue("hello-java-queue",true,false,false,null);
amqpAdmin.declareQueue(queue);
log.info("queue[{}]创建成功","hello-java-queue");
//声明一个绑定器
/**
* String destination, 目的地
* Binding.DestinationType destinationType, 目的地类型
* String exchange, 交换机
* String routingKey, 路由键
* Map<String, Object> arguments) 自定义参数
*/
Binding binding = new Binding(
"hello-java-queue",
Binding.DestinationType.QUEUE,
"hello-java-exchange",
"hello.java",
null);
//队列绑定交换机
amqpAdmin.declareBinding(binding);
log.info("binding[{}]创建成功","hello-java-binding");
}
}
5、RabbitmqTemplate
发送消息
@Autowired
RabbitTemplate rabbitTemplate;
@Test
public void sendMessage(){
/**
* send:原生的send方法,需要发送一个Message类型的对象
* convertAndSend: 将对象转为字节流,传给rabbitmq(推荐)
*/
//String msg = "hello pidan";
//发送消息如果是对象,因为要将对象转为字节传输,对象必须实现序列化接口Serializable
OrderReturnReasonEntity msg = new OrderReturnReasonEntity();
msg.setId(1L);
msg.setCreateTime(new Date());
msg.setName("皮皮");
/**
* 1、交换机,生产者——broker(交换机绑定队列)——消费者
* 2、routingKey ,交换机和队列用 路由key绑定
* 3、要发送的消息
*/
rabbitTemplate.convertAndSend(
"hello-java-exchange",
"hello.java",
msg);
log.info("消息发送完成{}",msg);
}
返回结果
配置 MessageConverter 消息转换类
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyRabbitConfig {
//消息类型转换器,将对象转为json格式
@Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
}
6、RabbitListener和RabbitHandler
接收消息
/**
* rabbitmq 接收消息
* 只要这个队列里有消息,就可以收到消息
*/
@RabbitListener(queues = "hello-java-queue")
public void receiveMessage(Message message, OrderReturnReasonEntity content, Channel channel){
//消息体
byte[] body = message.getBody();
System.out.println("消息体为" +body);
Object msg = JSON.parseObject(body, OrderReturnReasonEntity.class);
System.out.println("msg 是:" +msg);
//参数里填写 OrderReturnReasonEntity类型的对象,和json自动转对象的功能一样
System.out.println("content 是,功能和json一样,spring自动生成" +content);
//消息体,包含消息头等内容
MessageProperties properties = message.getMessageProperties();
System.out.println("消息头信息"+ properties);
//类型为class org.springframework.amqp.core.Message
System.out.println("接收到的消息内容"+ message + "类型为"+message.getClass());
}
rabbitHandler
@RabbitListener(queues = "hello-java-queue")
@Service("orderItemService")
public class OrderItemServiceImpl extends ServiceImpl<OrderItemDao, OrderItemEntity> implements OrderItemService {
/**
* rabbitmq 接收消息
* 只要这个队列里有消息,就可以收到消息
*/
//@RabbitListener(queues = "hello-java-queue")
@RabbitHandler
public void receiveMessage(Message message, OrderReturnReasonEntity content, Channel channel){
//消息体
byte[] body = message.getBody();
System.out.println("消息体为" +body);
Object msg = JSON.parseObject(body, OrderReturnReasonEntity.class);
System.out.println("msg 是:" +msg);
//参数里填写 OrderReturnReasonEntity类型的对象,和json自动转对象的功能一样
System.out.println("content 是,功能和json一样,spring自动生成" +content);
//消息体,包含消息头等内容
MessageProperties properties = message.getMessageProperties();
System.out.println("消息头信息"+ properties);
//类型为class org.springframework.amqp.core.Message
System.out.println("接收到的消息内容"+ message + "类型为"+message.getClass());
}
}
7、发送端确认
保证消息不丢失,可靠抵达,可以使用事务消息,性能下降250倍,为此引入确认 机制
• publisher confirmCallback 确认模式
• publisher returnCallback 未投递到 queue 退回模式
• consumer ack机制
1、配置文件
#配置rabbitmq的 主机、端口、用户名、密码
spring.rabbitmq.host=192.168.56.10
spring.rabbitmq.port=5672
spring.rabbitmq.virtual-host=/
#账号密码配置类默认都是guest,此处可不配置
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
#开启发送端确认
spring.rabbitmq.publisher-confirms=true
#开启发送端消息抵达队列的确认
spring.rabbitmq.publisher-returns=true
#只要抵达队列,以异步发送优先回调我们这个 returnConfirm
spring.rabbitmq.template.mandatory=true
#手动ack消息
spring.rabbitmq.listener.simple.acknowledge-mode=manual
2、配置类
package com.lian.gulimall.order.config;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
@Configuration
public class MyRabbitConfig {
@Autowired
RabbitTemplate rabbitTemplate;
/**
* 使用json序列化机制,进行消息转换
* 消息类型转换器,将对象转为json格式
*/
@Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
/**
* MyRabbitConfig 对象创建完成之后,执行此方法
*/
@PostConstruct
public void initRabbitTemplate(){
//设置确认回调
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
/**
*
* @param correlationData 当前消息的唯一关联数据
* @param ack 消息是否成功收到
* @param cause 失败的原因
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
System.out.println("correlationData: "+correlationData+"ack: "+ack+"cause: "+cause);
}
});
/**
* 设置消息抵达队列的确认回调
*/
rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
/**
* down 下来源代码后,参数就有名字了,方便理解
* 回退消息例子是 交换机收到消息,但是队列没有收到消息,消费者无法接收到
* @param message 投递失败的消息详细信息
* @param replyCode 回复的状态码
* @param replyText 回复的文本内容
* @param exchange 当时这个消息发送给哪个交换机
* @param routingKey 当时这个消息用哪个路由键
*/
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
System.out.println("message: "+message+"replyCode: "+replyCode+"replyText: "+replyText+"exchange: "+exchange+"routingKey: "+routingKey);
}
});
}
}