springboot集成RabbitMQ非常简单,如果只是简单的使用配置非常少,springboot提供了spring-boot-starter-amqp项目对消息各种支持
1、配置pom包,主要是添加spring-boot-starter-amqp的支持
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2、配置文件
配置rabbitmq的安装地址、端口以及账户信息(红色部分没有用)
spring.rabbitmq.host=192.168.0.86spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=123456
spring.rabbitmq.virtual-host=/
spring.rabbitmq.publisher-confirms=true
spring.rabbitmq.publisher-returns=true
spring.rabbitmq.template.mandatory=true
3.队列配置(生产端、消费端都需要此配置)
@Configuration
public class RabbitConfig {
//hello是队列的名称。可以定义多个队列
@Beanpublic Queue Queue() {
return new Queue("hello");
}
@Bean
public Queue Queue() {
return new Queue("world");
}
}
3、发送者(字符串)
rabbitTemplate是springboot 提供的默认实现
public class HelloSender {@Autowired
private AmqpTemplate rabbitTemplate;
public void send() {
String context = "hello " + new Date();
this.rabbitTemplate.convertAndSend("hello", context); //第一个参数是队列,第二个参数是信息。可以使字符串或者对象
}
}
4、接收者 注意RabbitListener在方法上
@Component
public class HelloReceiver {
@RabbitListener(queues = "hello")
@RabbitHandler
public void process(String hello) {
System.out.println("Receiver : " + hello);
}
@RabbitListener(queues = "world")
@RabbitHandler
public void process(String world){
System.out.println("Receiver : " + world
}
}
注意,发送者和接收者的queue name必须一致,不然不能接收
5. 对象的支持
//发送者
public void send(User user) {
System.out.println("Sender object: " + user.toString());
this.rabbitTemplate.convertAndSend("object", user); //object 是队列名称
}
//接受者
@RabbitListener(queues = "object")
@RabbitHandler
public void process(User user) {
System.out.println("Receiver object : " + user);
}
6. Topic Exchange
topic 是RabbitMQ中最灵活的一种方式,可以根据routing_key自由的绑定不同的队列
首先对topic规则配置,这里使用两个队列来测试
1> 配置类:
@Configuration
public class TopicRabbitConfig {
final static String message = "topic.message";
final static String messages = "topic.messages";
public Queue queueMessage() {
return new Queue(TopicRabbitConfig.message);
}
@Bean
public Queue queueMessages() {
return new Queue(TopicRabbitConfig.messages);
}
@Bean
TopicExchange exchange() {
return new TopicExchange("exchange");
}
@Bean
Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {
return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");
}
@Bean
Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) {
return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");
}
}
使用queueMessages同时匹配两个队列,queueMessage只匹配"topic.message"队列
2> 发送
public void send1() {
String context = "hi, i am message 1";System.out.println("Sender : " + context);
this.rabbitTemplate.convertAndSend("exchange", "topic.message", context);
}
public void send2() {
String context = "hi, i am messages 2";
System.out.println("Sender : " + context);
this.rabbitTemplate.convertAndSend("exchange", "topic.messages", context);
}
发送send1会匹配到topic.#和topic.message 两个Receiver都可以收到消息,发送send2只有topic.#可以匹配所有只有Receiver2监听到消息
7. Fanout Exchange
Fanout 就是我们熟悉的广播模式或者订阅模式,给Fanout交换机发送消息,绑定了这个交换机的所有队列都收到这个消息。
1> 配置类
@Configuration
public class FanoutRabbitConfig {
@Bean
public Queue AMessage() {
return new Queue("fanout.A");
}
@Bean
public Queue BMessage() {
return new Queue("fanout.B");
}
@Bean
public Queue CMessage() {
return new Queue("fanout.C");
}
@Bean
FanoutExchange fanoutExchange() {
return new FanoutExchange("fanoutExchange");
}
@Bean
Binding bindingExchangeA(Queue AMessage,FanoutExchange fanoutExchange) {
return BindingBuilder.bind(AMessage).to(fanoutExchange);
}
@Bean
Binding bindingExchangeB(Queue BMessage, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(BMessage).to(fanoutExchange);
}
@Bean
Binding bindingExchangeC(Queue CMessage, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(CMessage).to(fanoutExchange);
}
}
这里使用了A、B、C三个队列绑定到Fanout交换机上面,发送端的routing_key写任何字符都会被忽略:
public void send() {
String context = "hi, fanout msg ";
System.out.println("Sender : " + context);
this.rabbitTemplate.convertAndSend("fanoutExchange","", context);
}
结果说明,绑定到fanout交换机上面的队列都收到了消息
8. 传对象的情况的优化
使用上面的方式传的对象的问题:
1. 生产者的对象A 和消费者的对象B 必须完全一样,在同一个包里面,里面的字段也一样,一旦改了对象里面的属性,就会出错
2. web界面上,显示的消息是乱码
如何解决以上的问题??
将对象转成json字符串....
手动新增了转化
在配置文件中加上:
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
template.setMessageConverter(new Jackson2JsonMessageConverter());
return template;
}
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setMessageConverter(new Jackson2JsonMessageConverter());
return factory;
}
然后在生产和消费信息的地方使用他们:
@RabbitListener(queues = "merchant", containerFactory="rabbitListenerContainerFactory")
public void process(@Payload UpdateMerchant request) {
UpdateMerchantResponse response = new UpdateMerchantResponse();
logger.info(request.getMerchantId() + "->" + response.getReturnCode());
}
就可以啦