一、rabbitMq异步消息机制
1、exchange和queue进行绑定,一个exchange可以绑定多个queue。
2、消息生产者produce,将消息发送至exchange,exchange将消息路由至多个queue。
3、exchange路由分为fanout、direct、topic三种模式。
4、消费者customer监听相应的queue,接收消息,触发异步方法。
二、springboot中的使用
1、引入依赖
org.springframework.boot
spring-boot-starter-amqp
2.2.5.RELEASE
2、application.properties中增加相关配置
spring.rabbitmq.virtual-host=lwt
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=admin
spring.rabbitmq.listener.simple.concurrency=10
spring.rabbitmq.listener.simple.max-concurrency=20
spring.rabbitmq.listener.simple.prefetch=50
3、配置rabbitMq
@Configuration
public class RabbitmqConfig {
private final Logger log = LoggerFactory.getLogger(this.getClass().getName());
@Autowired
private CachingConnectionFactory connectionFactory;
@Autowired
private SimpleRabbitListenerContainerFactoryConfigurer factoryConfigurer;
@Autowired
private Environment env;
/**
* 单一消费者
* @return
*/
@Bean(name = "singleListenerContainer")
public SimpleRabbitListenerContainerFactory listenerContainer(){
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setMessageConverter(new Jackson2JsonMessageConverter());
factory.setConcurrentConsumers(1);
factory.setMaxConcurrentConsumers(1);
factory.setPrefetchCount(1);
factory.setTxSize(1);
return factory;
}
/**
* 多个消费者
* @return
*/
@Bean(name = "multiListenerContainer")
public SimpleRabbitListenerContainerFactory multiListenerContainer(){
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factoryConfigurer.configure(factory,connectionFactory);
factory.setMessageConverter(new Jackson2JsonMessageConverter());
factory.setAcknowledgeMode(AcknowledgeMode.NONE);
factory.setConcurrentConsumers(env.getProperty("spring.rabbitmq.listener.simple.concurrency",int.class));
factory.setMaxConcurrentConsumers(env.getProperty("spring.rabbitmq.listener.simple.max-concurrency",int.class));
factory.setPrefetchCount(env.getProperty("spring.rabbitmq.listener.simple.prefetch",int.class));
return factory;
}
@Bean
public RabbitTemplate rabbitTemplate(){
connectionFactory.setPublisherConfirms(true);
connectionFactory.setPublisherReturns(true);
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMandatory(true);
//TODO:面向生产端
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
log.info("消息发送成功:correlationData({}),ack({}),cause({})",correlationData,ack,cause);
}
});
rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
log.info("消息丢失:exchange({}),route({}),replyCode({}),replyText({}),message:{}",exchange,routingKey,replyCode,replyText,message);
}
});
return rabbitTemplate;
}
//TODO:用户注册消息模型
@Bean
public Queue userRegisterQueue(){
return new Queue("rabbitmq.user.register.queue.name",true);
}
@Bean
public Exchange userRegisterExchange(){
return new DirectExchange("rabbitmq.user.register.exchange.name",true,false);
}
@Bean
public Binding subContractInvalidBinding(){
return BindingBuilder.bind(userRegisterQueue()).to(userRegisterExchange()).with("rabbitmq.user.register.routing.key.name").and(null);
}
3、消息发送
@Autowired
private AmqpTemplate amqpTemplate;
@Autowired
private ObjectMapper objectMapper;
@RequestMapping(value = "/helloSender",method = RequestMethod.POST)
public String HelloSender(@RequestBody String message) throws JsonProcessingException {
System.out.println(message);
byte[] byts = objectMapper.writeValueAsBytes(message);
Message msg= MessageBuilder.withBody(byts).setDeliveryMode(MessageDeliveryMode.PERSISTENT).build();
amqpTemplate.send("rabbitmq.user.register.exchange.name","rabbitmq.user.register.routing.key.name",msg);
return "succ";
}
4、消息接收
@Component
public class RabbitmqListener {
private final Logger log = LoggerFactory.getLogger(this.getClass().getName());
//监听某一个队列
@RabbitListener(queues = "rabbitmq.user.register.queue.name",containerFactory = "singleListenerContainer")
public void consume(Message msg){
try {
System.out.println("----------接收成功!!!-------");
String message = msg.toString();
log.info("监听到的消息: {} ",message);
}catch (Exception e){
e.printStackTrace();
}
}
}
三、问题与注意事项
1、发送字符串类型的数据信息时,反序列化报错。
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `[B` out of START_OBJECT token
at [Source: (String)"{"id":1,"userName":"jack","name":"lili"}"; line: 1, column: 1]
解决方案:使用ObjectMapper进行数据格式转换:byte[] byts = objectMapper.writeValueAsBytes(message);