文章目录
一、引入springboot-amqp启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
二、查看配置类RabbitAutoConfiguration
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.boot.autoconfigure.amqp;
import com.rabbitmq.client.Channel;
import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionNameStrategy;
import org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitMessagingTemplate;
import org.springframework.amqp.rabbit.core.RabbitOperations;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties.Ssl;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties.Template;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties.Cache.Connection;
import org.springframework.boot.autoconfigure.amqp.RabbitRetryTemplateCustomizer.Target;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({RabbitTemplate.class, Channel.class})
@EnableConfigurationProperties({RabbitProperties.class})
@Import({RabbitAnnotationDrivenConfiguration.class})
public class RabbitAutoConfiguration {
public RabbitAutoConfiguration() {
}
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({RabbitMessagingTemplate.class})
@ConditionalOnMissingBean({RabbitMessagingTemplate.class})
@Import({RabbitAutoConfiguration.RabbitTemplateConfiguration.class})
protected static class MessagingTemplateConfiguration {
protected MessagingTemplateConfiguration() {
}
@Bean
@ConditionalOnSingleCandidate(RabbitTemplate.class)
public RabbitMessagingTemplate rabbitMessagingTemplate(RabbitTemplate rabbitTemplate) {
return new RabbitMessagingTemplate(rabbitTemplate);
}
}
@Configuration(
proxyBeanMethods = false
)
@Import({RabbitAutoConfiguration.RabbitConnectionFactoryCreator.class})
protected static class RabbitTemplateConfiguration {
protected RabbitTemplateConfiguration() {
}
@Bean
@ConditionalOnSingleCandidate(ConnectionFactory.class)
@ConditionalOnMissingBean({RabbitOperations.class})
public RabbitTemplate rabbitTemplate(RabbitProperties properties, ObjectProvider<MessageConverter> messageConverter, ObjectProvider<RabbitRetryTemplateCustomizer> retryTemplateCustomizers, ConnectionFactory connectionFactory) {
PropertyMapper map = PropertyMapper.get();
RabbitTemplate template = new RabbitTemplate(connectionFactory);
messageConverter.ifUnique(template::setMessageConverter);
template.setMandatory(this.determineMandatoryFlag(properties));
Template templateProperties = properties.getTemplate();
if (templateProperties.getRetry().isEnabled()) {
template.setRetryTemplate((new RetryTemplateFactory((List)retryTemplateCustomizers.orderedStream().collect(Collectors.toList()))).createRetryTemplate(templateProperties.getRetry(), Target.SENDER));
}
templateProperties.getClass();
map.from(templateProperties::getReceiveTimeout).whenNonNull().as(Duration::toMillis).to(template::setReceiveTimeout);
templateProperties.getClass();
map.from(templateProperties::getReplyTimeout).whenNonNull().as(Duration::toMillis).to(template::setReplyTimeout);
templateProperties.getClass();
map.from(templateProperties::getExchange).to(template::setExchange);
templateProperties.getClass();
map.from(templateProperties::getRoutingKey).to(template::setRoutingKey);
templateProperties.getClass();
map.from(templateProperties::getDefaultReceiveQueue).whenNonNull().to(template::setDefaultReceiveQueue);
return template;
}
private boolean determineMandatoryFlag(RabbitProperties properties) {
Boolean mandatory = properties.getTemplate().getMandatory();
return mandatory != null ? mandatory : properties.isPublisherReturns();
}
@Bean
@ConditionalOnSingleCandidate(ConnectionFactory.class)
@ConditionalOnProperty(
prefix = "spring.rabbitmq",
name = {"dynamic"},
matchIfMissing = true
)
@ConditionalOnMissingBean
public AmqpAdmin amqpAdmin(ConnectionFactory connectionFactory) {
return new RabbitAdmin(connectionFactory);
}
}
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnMissingBean({ConnectionFactory.class})
protected static class RabbitConnectionFactoryCreator {
protected RabbitConnectionFactoryCreator() {
}
@Bean
public CachingConnectionFactory rabbitConnectionFactory(RabbitProperties properties, ObjectProvider<ConnectionNameStrategy> connectionNameStrategy) throws Exception {
PropertyMapper map = PropertyMapper.get();
CachingConnectionFactory factory = new CachingConnectionFactory((com.rabbitmq.client.ConnectionFactory)this.getRabbitConnectionFactoryBean(properties).getObject());
properties.getClass();
map.from(properties::determineAddresses).to(factory::setAddresses);
properties.getClass();
map.from(properties::isPublisherReturns).to(factory::setPublisherReturns);
properties.getClass();
map.from(properties::getPublisherConfirmType).whenNonNull().to(factory::setPublisherConfirmType);
org.springframework.boot.autoconfigure.amqp.RabbitProperties.Cache.Channel channel = properties.getCache().getChannel();
channel.getClass();
map.from(channel::getSize).whenNonNull().to(factory::setChannelCacheSize);
channel.getClass();
map.from(channel::getCheckoutTimeout).whenNonNull().as(Duration::toMillis).to(factory::setChannelCheckoutTimeout);
Connection connection = properties.getCache().getConnection();
connection.getClass();
map.from(connection::getMode).whenNonNull().to(factory::setCacheMode);
connection.getClass();
map.from(connection::getSize).whenNonNull().to(factory::setConnectionCacheSize);
connectionNameStrategy.getClass();
map.from(connectionNameStrategy::getIfUnique).whenNonNull().to(factory::setConnectionNameStrategy);
return factory;
}
private RabbitConnectionFactoryBean getRabbitConnectionFactoryBean(RabbitProperties properties) throws Exception {
PropertyMapper map = PropertyMapper.get();
RabbitConnectionFactoryBean factory = new RabbitConnectionFactoryBean();
properties.getClass();
map.from(properties::determineHost).whenNonNull().to(factory::setHost);
properties.getClass();
map.from(properties::determinePort).to(factory::setPort);
properties.getClass();
map.from(properties::determineUsername).whenNonNull().to(factory::setUsername);
properties.getClass();
map.from(properties::determinePassword).whenNonNull().to(factory::setPassword);
properties.getClass();
map.from(properties::determineVirtualHost).whenNonNull().to(factory::setVirtualHost);
properties.getClass();
map.from(properties::getRequestedHeartbeat).whenNonNull().asInt(Duration::getSeconds).to(factory::setRequestedHeartbeat);
Ssl ssl = properties.getSsl();
if (ssl.determineEnabled()) {
factory.setUseSSL(true);
ssl.getClass();
map.from(ssl::getAlgorithm).whenNonNull().to(factory::setSslAlgorithm);
ssl.getClass();
map.from(ssl::getKeyStoreType).to(factory::setKeyStoreType);
ssl.getClass();
map.from(ssl::getKeyStore).to(factory::setKeyStore);
ssl.getClass();
map.from(ssl::getKeyStorePassword).to(factory::setKeyStorePassphrase);
ssl.getClass();
map.from(ssl::getTrustStoreType).to(factory::setTrustStoreType);
ssl.getClass();
map.from(ssl::getTrustStore).to(factory::setTrustStore);
ssl.getClass();
map.from(ssl::getTrustStorePassword).to(factory::setTrustStorePassphrase);
ssl.getClass();
map.from(ssl::isValidateServerCertificate).to((validate) -> {
factory.setSkipServerCertificateValidation(!validate);
});
ssl.getClass();
map.from(ssl::getVerifyHostname).to(factory::setEnableHostnameVerification);
}
properties.getClass();
map.from(properties::getConnectionTimeout).whenNonNull().asInt(Duration::toMillis).to(factory::setConnectionTimeout);
factory.afterPropertiesSet();
return factory;
}
}
}
往容器中自动配置了RabbitMessagingTemplate、RabbitTemplate、AmqpAdmin、CachingConnectionFactory四个组件。
三、AmqpAdmin
AmqpAdmin配置spring和RabbitMQ连接信息,从配置文件中读取,以spring.rabbitmq开头
1.配置gulimall-order模块的yml文件
添加RabbitMQ连接信息
2.在启动类添加@EnableRabbit注解
开启RabbitMQ服务
3.使用AmqpAdmin创建Exchange交换器
@Slf4j
@SpringBootTest
@RunWith(SpringRunner.class)
class GulimallOrderApplicationTests {
@Autowired
AmqpAdmin amqpAdmin;
//创建交换器
@Test
public void createExchange(){
//创建Direct类型交换器
DirectExchange directExchange = new DirectExchange("java-direct-exchange", true, false);
amqpAdmin.declareExchange(directExchange);
log.info("交换器创建成功");
}
}
创建成功:
4.使用AmqpAdmin创建Queue队列
public void createQueue(){
//创建Queue
Queue queue = new Queue("java-queue", true, false,false);
amqpAdmin.declareQueue(queue);
log.info("队列创建成功");
}
创建成功:
5.使用AmqpAdmin创建Binding绑定
//创建绑定
@Test
public void createBinding(){
//创建Queue
//String destination, 需要绑定的Queue/Exchange名称
// Binding.DestinationType destinationType, 需要绑定类型:Queue/Exchange
// String exchange, 需要绑定的Exchange名称
// String routingKey, 路由键
// @Nullable Map<String, Object> arguments 参数
Binding binding = new Binding("java-queue",
Binding.DestinationType.QUEUE,
"java-direct-exchange",
"hello-java",
null);
amqpAdmin.declareBinding(binding);
log.info("绑定成功");
}
绑定成功:
四、RabbitTemplate
1.发送字符串纯文本消息
@Autowired
RabbitTemplate rabbitTemplate;
@Test
public void sendMessageTest(){
/**
* 发送消息
*/
rabbitTemplate.convertAndSend("java-direct-exchange","hello-java","第一条消息");
}
消息发送成功:
2.发送对象消息
@Autowired
RabbitTemplate rabbitTemplate;
@Test
public void sendMessageTest(){
/**
* 发送消息
*/
OrderReturnApplyEntity orderReturnApplyEntity = new OrderReturnApplyEntity();
orderReturnApplyEntity.setId(1L);
orderReturnApplyEntity.setCreateTime(new Date());
orderReturnApplyEntity.setSkuName("iPhone");
rabbitTemplate.convertAndSend("java-direct-exchange","hello-java",orderReturnApplyEntity);
log.info("发送成功");
}
对象必须实现Serializable接口。
1.默认序列化机制是jdk字节流
获取消息:
2.修改RabbitMQ序列化机制为JSON序列化
新建RabbitConfig配置类,在容器中重启注入自定义的messageConverter
package com.simon.gulimall.order.config;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyRabbitConfig {
@Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
}
MessageConverter 接口的实现,其中就有JacksonMessageConverter
3.再次发送对象消息
结果:变为JSON格式了。
五、监听消息RabbitListener、RabbitHandler
使用 @RabbitListener @RabbitHandler必须在启动类上加@EnableRabbit
1.@RabbitListener
//监听消息 进行消费
@RabbitListener(queues = "java-queue")
public void recivedMessage(Message msg){
byte[] body = msg.getBody();
MessageProperties messageProperties = msg.getMessageProperties();
System.out.println("body:"+new String(body));
System.out.println("messageProperties:"+messageProperties);
}
此时获取的body就是对象转成的json。可以直接使用对象进行接收,spring自动转换:
2.@RabbitHandler
如果监听同一个队列的两种或多种消息,进行不同逻辑的处理,这时就需要@RabbitListener和@RabbitHandler组合使用。
@RabbitListener(queues = “java-queue”)放在类上进行标注
@RabbitHandler放在方法上标注,表明监听
@Service("orderItemService")
@RabbitListener(queues = "java-queue")
public class OrderItemServiceImpl extends ServiceImpl<OrderItemDao, OrderItemEntity> implements OrderItemService {
//监听消息 进行消费
/**
* 监听java-queue队列中OrderReturnApplyEntity的消息
* @param msg
* @param orderReturnApplyEntity
*/
@RabbitHandler
public void recivedMessage(Message msg, OrderReturnApplyEntity orderReturnApplyEntity){
System.out.println("orderReturnApplyEntity:"+orderReturnApplyEntity);
}
/**
* 监听java-queue队列中OrderEntity的消息
* @param msg
* @param OrderEntity
*/
@RabbitHandler
public void recivedMessage2(Message msg, OrderEntity orderEntity){
System.out.println("orderEntity:"+orderEntity);
}
}