前言
该示例使用的SpringBoot版本是2.2.2
添加依赖
引入amqp的依赖就行,AMQP即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。RabbitMQ就是对该协议的一种实现。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
编写配置
package com.example.demo.config;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.Binding.DestinationType;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.amqp.core.Queue;
@Configuration
public class RabbitMQConfig implements InitializingBean {
/**
* RabbitMQ的地址
*/
@Value("${rabbit.addresses}")
private String addresses;
/**
* RabbitMQ的登录名
*/
@Value("${rabbit.username}")
private String username;
/**
* RabbitMQ的登录密码
*/
@Value("${rabbit.password}")
private String password;
/**
* 虚拟消息服务器
*/
@Value("${rabbit.virtualhost}")
private String virtualHost;
@Value("${rabbit.queue1.name}")
private String queue1Name;
@Value("${rabbit.queue2.name}")
private String queue2Name;
@Value("${rabbit.exchange2.name}")
private String exchange2Name;
@Value("${rabbit.bindingKey2}")
private String bindingKey2;
/**
* 通过这种方式可以申明一个队列,
* 该队列使用跟队列名相同的bindingKey绑定了RabbitMQ默认的交换器
* @return 队列
*/
@Bean
public Queue queue1() {
return new Queue(queue1Name);
}
/**
* 创建连接工厂
* @return 连接工厂
*/
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
/*
addresses的格式为192.168.7.82:5672,192.168.7.81:5672,多个地址之间用","隔开
也可以用host和port来指定RabbitMQ地址
cachingConnectionFactory.setHost("192.168.7.82");
cachingConnectionFactory.setPort(5672);
*/
cachingConnectionFactory.setAddresses(addresses);
cachingConnectionFactory.setUsername(username);
cachingConnectionFactory.setPassword(password);
cachingConnectionFactory.setVirtualHost(virtualHost);
return cachingConnectionFactory;
}
/**
* 配置消费者容器工厂
* @return 消费者容器工厂
*/
@Bean
public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory() {
SimpleRabbitListenerContainerFactory listenerContainerFactory = new SimpleRabbitListenerContainerFactory();
listenerContainerFactory.setConnectionFactory(connectionFactory());
//手动ack
listenerContainerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
return listenerContainerFactory;
}
/**
* RabbitMQ的template,通过该类可以收发消息
* @return RabbitTemplate
*/
@Bean
public RabbitTemplate rabbitTemplate() {
return new RabbitTemplate(connectionFactory());
}
/**
* 消息中间件的管理控制台。可以声明队列、交换器,以及绑定队列和交换器
* @return AmqpAdmin
*/
@Bean
public AmqpAdmin amqpAdmin() {
return new RabbitAdmin(connectionFactory());
}
@Override
public void afterPropertiesSet() throws Exception {
AmqpAdmin amqpAdmin = amqpAdmin();
//声明一个队列
amqpAdmin.declareQueue(new Queue(queue2Name));
//声明一个交换器
amqpAdmin.declareExchange(new DirectExchange(exchange2Name));
//绑定交换器和队列
Binding binding = new Binding(queue2Name, DestinationType.QUEUE, exchange2Name, bindingKey2, null);
amqpAdmin.declareBinding(binding);
}
}
application.yml
server:
port: 8080
rabbit:
addresses: 192.168.7.82:5672
username: admin
password: 123456
virtualhost: /
queue1:
name: testQueue1
exchange2:
name: testExchange2
queue2:
name: testQueue2
bindingKey2: testBinding2
queue3:
name: testQueue3
exchange3:
name: testExchange3
bindingKey3: testBinding3
编写生产者
package com.example.demo.mq;
import java.io.UnsupportedEncodingException;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* RabbitMQ生产者
* @author LiHao
*/
@Component
public class RabbitMQProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送字符串消息到默认的交换器
* @param routingKey 路由键(这里为了测试方便将路由键当做参数)
* @param msg 消息
*/
public void send(String routingKey, String msg) {
this.rabbitTemplate.convertAndSend(routingKey, msg);
}
/**
* 发送字符串消息到指定的交换器
* @param exchange 交换器名称
* @param routingKey 路由键
* @param msg 消息
*/
public void send1(String exchange, String routingKey, String msg) {
this.rabbitTemplate.convertAndSend(exchange, routingKey, msg);
}
/**
* 发送字节数组消息到指定交换器
* @param exchange 交换器名称
* @param routingKey 路由键
* @param msg 消息
* @throws UnsupportedEncodingException
*/
public void sendByte(String exchange, String routingKey, String msg) throws UnsupportedEncodingException {
this.rabbitTemplate.convertAndSend(exchange, routingKey, msg.getBytes("utf-8"));
}
}
编写消费者
package com.example.demo.mq;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import com.rabbitmq.client.Channel;
/**
* RabbitMQ消费者
* @author LiHao
*
*/
@Component
public class RabbitMQConsumer {
/**
* 自动ack可以这样接收消息
* @param msg
*/
@RabbitListener(queues = "${rabbit.queue1.name}")
@RabbitHandler
public void receive1(String msg) {
System.out.println("消费者从队列1接收到的消息:" + msg);
}
@RabbitListener(queues = "${rabbit.queue2.name}")
@RabbitHandler
public void receive2(String msg, Channel channel, Message message) {
System.out.println("消费者从队列2接收到的消息:" + msg);
long deliveryTag = message.getMessageProperties().getDeliveryTag();
try {
//确认收到消息,RabbitMQ将删除该消息
channel.basicAck(deliveryTag, false);
} catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* 使用@QueueBinding组合注解可以声明队列、交换器,并绑定队列和交换器
* @param msg
* @param channel
* @param message
*/
@RabbitListener(bindings = {
@QueueBinding(value = @Queue(value = "${rabbit.queue3.name}"),
exchange = @Exchange(value = "${rabbit.exchange3.name}"),
key = "${rabbit.bindingKey3}")
})
@RabbitHandler
public void receive3(byte[] msg, Channel channel, Message message) {
try {
String str = new String(msg, "utf-8");
System.out.println("消费者从队列3接收到的消息:" + str);
} catch (UnsupportedEncodingException ex) {
ex.printStackTrace();
}
long deliveryTag = message.getMessageProperties().getDeliveryTag();
try {
channel.basicAck(deliveryTag, false);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
编写测试类
package com.example.demo.controller;
import java.io.UnsupportedEncodingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.mq.RabbitMQProducer;
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private RabbitMQProducer rabbitMQProducer;
@GetMapping("/mq/str")
public String test(String exchange, String routingKey, String msg) {
if (exchange != null) {
rabbitMQProducer.send1(exchange, routingKey, msg);
} else {
rabbitMQProducer.send(routingKey, msg);
}
return "ok";
}
@GetMapping("/mq/byte")
public String test1(String exchange, String msg, String routingKey) {
try {
rabbitMQProducer.sendByte(exchange, routingKey, msg);
} catch (UnsupportedEncodingException ex) {
ex.printStackTrace();
}
return "ok";
}
}