RabbitMQ入门demo
1 原生代码
创建新模块
- 引入依赖:spring-boot-starter-amqp
- 生产者代码
public class ProducerTest {
// 交换机名字
private String exchangeName = "exchange_lxy";
// 路由键
private String routingKey = "rout_lxy";
// 队列名字
private String queueName = "queue_lxy";
// host
private String host = "你的外网Ip";
// rabbitMQ端口号
private Integer port = 5672;
// 虚拟机
private String vHost = "my_vhost";
@Test
public void sendMsg() throws IOException, TimeoutException {
// 1.准备一个连接工厂
ConnectionFactory factory = new ConnectionFactory();
// 设置对应的连接参数
factory.setHost(host);
factory.setPort(port);
factory.setUsername("root");
factory.setPassword("1111");
factory.setVirtualHost(vHost);
// 2.获取连接对象
Connection connection = factory.newConnection();
// 3.获取channel
Channel channel = connection.createChannel();
// 4.声明一个交换机,type="direct",持久化,非自动删除的交换器
channel.exchangeDeclare(exchangeName, "direct", true, false, null);
// 5.声明一个持久化,非排他,非自动删除的队列
channel.queueDeclare(queueName,true,false,false,null);
// 6.将交换器和队列通过路由键绑定
channel.queueBind(queueName,exchangeName,routingKey);
// 7.发送持久化消息:hello rabbitmq
String message = "hello rabbitmq";
channel.basicPublish(exchangeName,routingKey, MessageProperties.PERSISTENT_TEXT_PLAIN,message.getBytes());
// 8.关闭资源
channel.close();
connection.close();
}
}
交换器根据不同路由键绑定不同队列,查看web管理器
- 消费者代码
public class ConsumerTest {
// 队列名字
private String queueName = "queue_lxy";
// host
private String ipAddress = "外网IP";
// rabbitMQ 端口号
private Integer port = 5672;
/**
* 生产者测试
*/
@Test
public void consumer() throws Exception {
// 1. 创建 Address 对象数组
Address[] addresses = new Address[] {
new Address(ipAddress,port)
};
// 2. 获取连接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setUsername("root");
factory.setPassword("1111");
// 设置 vhost
factory.setVirtualHost("my_vhost");
// 3. 建立连接
Connection connection = factory.newConnection(addresses);
// 4. 创建频道
Channel channel = connection.createChannel();
// 设置客户端最多接收未被 ack 的消息的个数
channel.basicQos(64);
// 创建消费者对象
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(
String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body) throws IOException {
// 获取消息
System.out.println("接收到:"+new String(body));
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
// 消费
channel.basicConsume(queueName,consumer);
//等待回调函数执行完毕之后 , 关闭资源
TimeUnit.SECONDS.sleep(5);
channel.close();
connection.close();
}
}
结果:
2 重点掌握Springboot写法
了解原生代码,重点掌握Springboot写法,不交给eureka管理
- 依赖:spring-boot-starter-amqp
- 配置
spring:
application:
name: ribbitmq-producer
rabbitmq:
host: 你的外网ip
virtual-host: my_vhost
username: root
password: 1111
port: 5672
connection-timeout: 6000
server:
port: 9527
- 配置类RabbitConfig.java
@Configuration
public class RabbitConfig {
// 操作rabbitmq的对象
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
return new RabbitTemplate(connectionFactory);
}
}
- 生产者,新建模块(上面原生代码测试用)rabbitmq-producer
@RestController
public class RabbitController {
@Autowired
private RabbitTemplate rabbitTemplate;
@GetMapping("/rabbit/send/{name}")
public String sendMsg(@PathVariable String name) {
rabbitTemplate.convertAndSend("exchange_lxy","rout_lxy",name);
return "success";
}
}
- 消费者,新建模块rabbitmq-consumer
配置文件:
spring:
application:
name: rabbit-consumer
rabbitmq:
host: 你的外网ip
virtual-host: my_vhost
username: root
password: 1111
port: 5672
connection-timeout: 6000
listener:
simple:
# 最小并发处理数
concurrency: 5
max-concurrency: 10
# 消费消息的模式
acknowledge-mode: auto
# 限流
prefetch: 1
server:
port: 9527
配置类:
@Configuration
public class RabbitConfig {
// 操作rabbitmq模板对象
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
return new RabbitTemplate(connectionFactory);
}
}
消费的方法:一旦队列有消息,自动获取消息出来,马上消费
@Component
public class RabbitMqListener {
@RabbitListener(queues = "queue_lxy")
@RabbitHandler
public void listen(String msg) {
System.out.println("接收到:" + msg);
}
@RabbitListener(queues = "queue_lxy2")
@RabbitHandler
public void listen2(String msg) {
System.out.println("接收到:" + msg);
}
}
3 Springboot rabbitMQ传递对象
依赖中加入pojo
生产者:RabbitController.java
@GetMapping("/rabbit/obj/{name}")
public String sendObj(@PathVariable String name) {
User user = new User();
user.setId(111);
user.setUserName(name);
user.setUserAge(1000);
// 发送
rabbitTemplate.convertAndSend("java502_obj_exchange","object",user);
return "success";
}
消费者:手动ACK(手动确认消息确认),实际开发必用
/**
* 自动接收对象的监听 : 自动生成队列, 交换机, 绑定
* @param user
*/
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue(name = "java502_obj_queue",durable = "true",autoDelete = "false"),
exchange = @Exchange(name = "java502_obj_exchange"),
key = "object"
)
})
@RabbitHandler
public void listenObj(@Payload User user){
System.out.println("接收到了:"+user);
}
// user:直接接收user 对象必须指定@PayLoad注解
// headers :需要用来获取手动ack的deliveryTag
// channeL :频道用来手动ack
结果:
4 不同交换机类型的路由案例
1. fanout
消费者:
@Component
public class FanoutLintener {
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue(name = "fanout_queue1",durable = "true",autoDelete = "false"),
exchange = @Exchange(name = "fanout_exchange",type = "fanout"),
key = "fanout_key"
)
})
@RabbitHandler
public void listenFanout1(String msg, @Headers Map<String, Object> headers, Channel channel) throws IOException {
long deliveryTag = (long) headers.get(AmqpHeaders.DELIVERY_TAG);
System.out.println("消费者1 消费了消息:"+msg);
channel.basicAck(deliveryTag,true);
}
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue(name = "fanout_queue2",durable = "true",autoDelete = "false"),
exchange = @Exchange(name = "fanout_exchange",type = "fanout"),
key = "fanout_key"
)
})
@RabbitHandler
public void listenFanout2(String msg, @Headers Map<String, Object> headers, Channel channel) throws IOException {
long deliveryTag = (long) headers.get(AmqpHeaders.DELIVERY_TAG);
System.out.println("消费者2 消费了消息:"+msg);
channel.basicAck(deliveryTag,true);
}
}
生产者RabbitController.java:
@GetMapping("/rabbit/fanout/{name}")
public String fanout(@PathVariable String name) {
rabbitTemplate.convertAndSend("fanout_exchange","fanout_key",name);
return "success";
}
访问 localhost:9527/rabbit/fanout/cc
2. direct
消费者:
@Component
public class DirectListener {
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue(name = "direct_queue1",durable = "true",autoDelete = "false"),
exchange = @Exchange(name = "direct_exchange"),
key = "direct_1"
)
})
@RabbitHandler
public void listenDirect1(String msg, @Headers Map<String, Object> headers, Channel channel) throws IOException {
long deliveryTag = (long) headers.get(AmqpHeaders.DELIVERY_TAG);
System.out.println("direct消费者1 消费了消息:"+msg);
channel.basicAck(deliveryTag,true);
}
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue(name = "direct_queue2",durable = "true",autoDelete = "false"),
exchange = @Exchange(name = "direct_exchange"),
key = "direct_2"
)
})
@RabbitHandler
public void listenDirect2(String msg, @Headers Map<String, Object> headers, Channel channel) throws IOException {
long deliveryTag = (long) headers.get(AmqpHeaders.DELIVERY_TAG);
System.out.println("direct消费者2 消费了消息:"+msg);
channel.basicAck(deliveryTag,true);
}
}
生产者:
@GetMapping("/rabbit/direct/{rout}")
public String sendDirect(@PathVariable String route) {
rabbitTemplate.convertAndSend("direct_exchange",route,route);
return "success";
}
完全匹配,两个队列,取决于用的是哪个routingkey,访问 localhost:9527/rabbit/direct/direct_1 ,这是访问的是第一个routingkey,结果:
3. topic模糊匹配
消费者:
@Component
public class TopicListener {
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue(name = "topic_queue1",durable = "true",autoDelete = "false"),
exchange = @Exchange(name = "topic_exchange",type = "topic"),
key = "com.*.*"
)
})
@RabbitHandler
public void listenTopic1(String msg, @Headers Map<String, Object> headers, Channel channel) throws IOException {
long deliveryTag = (long) headers.get(AmqpHeaders.DELIVERY_TAG);
System.out.println("topic消费者1 消费了消息:"+msg);
channel.basicAck(deliveryTag,true);
}
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue(name = "topic_queue2",durable = "true",autoDelete = "false"),
exchange = @Exchange(name = "topic_exchange",type = "topic"),
key = "*.hsj.*"
)
})
@RabbitHandler
public void listenTopic2(String msg, @Headers Map<String, Object> headers, Channel channel) throws IOException {
long deliveryTag = (long) headers.get(AmqpHeaders.DELIVERY_TAG);
System.out.println("topic消费者2 消费了消息:"+msg);
channel.basicAck(deliveryTag,true);
}
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue(name = "topic_queue3",durable = "true",autoDelete = "false"),
exchange = @Exchange(name = "topic_exchange",type = "topic"),
key = "com.#"
)
})
@RabbitHandler
public void listenTopic3(String msg, @Headers Map<String, Object> headers, Channel channel) throws IOException {
long deliveryTag = (long) headers.get(AmqpHeaders.DELIVERY_TAG);
System.out.println("topic消费者3 消费了消息:"+msg);
channel.basicAck(deliveryTag,true);
}
}
生产者
GetMapping("/rabbit/topic/{rout}")
public String sendTopic(@PathVariable String route) {
rabbitTemplate.convertAndSend("topic _exchange",route,route);
return "success";
}