Spring Boot入门教程:第八章:使用RabbitMQ进行消息传递

本章带你设置一个RabbitMQ AMQP服务器来发布和订阅消息,创建一个Spring Boot应用和RabbitMQ服务器进行交互。

本文目标

用Spring Boot构建一个应用,使用Spring AMQP的RabbitTemplate发布消息,使用MessageListenerAdapter订阅消息。

你需要

  • 15分钟左右
  • IntelliJ IDEA
  • JDK 1.8+
  • Maven 3.2+
  • RabbitMQ服务器

设置一个RabbitMQ服务器

在创建一个消息应用之前,我们需要配置一个负责接收信息和发送信息的服务器。

Redis是一个AMQP服务器。

安装方法可以参照这篇文章RabbitMQ安装教程(Windows/Linux都有)

用Spring Initializr生成项目代码

对于所有的Spring应用,你都可以使用Spring Initializr生成基本的项目代码。Initializr提供了一个快速的方式去引入所有你需要的依赖,并且为你做了很多设置。当前例子需要Spring for RabbitMQ依赖。

具体设置如下图:
在这里插入图片描述
如上图所示,我们选择了Maven作为编译工具。你也可以选择Gradle来进行编译。然后我们分别把Group和Artifact设置为“com.hansy”和“messaging-rabbitmq”。

生成的pom.xml文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.2.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.hansy</groupId>
	<artifactId>messaging-rabbitmq</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>messaging-rabbitmq</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-amqp</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.amqp</groupId>
			<artifactId>spring-rabbit-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

创建一个RabbitMQ消息接收器

在任何的基于消息的应用中,都需要一个消息接收器,拥有一个可以响应消息的方法。代码如下:

package com.hansy.messagingrabbitmq;

import org.springframework.stereotype.Component;

import java.util.concurrent.CountDownLatch;

@Component
public class Receiver {
    
    

    private CountDownLatch latch = new CountDownLatch(1);

    public void receiveMessage(String message) {
    
    
        System.out.println("Received <" + message + ">");
        latch.countDown();
    }

    public CountDownLatch getLatch() {
    
    
        return latch;
    }
}

Receiver是一个定义了接收消息的方法的POJO类。当你注册了一个Receiver作为消息监听器的话,消息处理方法的命名可以随意。

为了方便,这个POJO类还有一个CountDownLatch对象。用来标志接收到了信息。这么做这是只是为了测试,实际生产环境不太可能这么使用。

注册监听器和发送消息

Spring AMQP的RabbitTemplate提供了使用RabbitMQ来发送和接收消息的所有功能。

我们需要配置如下元素:

  • 一个消息监听器的容器
  • 定义Queue,Exchange和用于他们之间的Binding
  • 配置一个组件去发送一些消息去测试监听器

Spring Boot会自动创建一个连接工厂和一个RabbitTemplate,减少了额外的代码。

我们使用RabbitTemplate发送消息,注册一个Receiver到消息监听器的容器里面来接收消息。连接工厂驱动他们连接到RabbitMQ服务器。代码如下:

package com.hansy.messagingrabbitmq;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class MessagingRabbitmqApplication {
    
    

    public static final String TOPIC_EXCHANGE_NAME = "spring-boot-exchange";
    public static final String QUEUE_NAME = "spring-boot";

    @Bean
    Queue queue() {
    
    
        return new Queue(QUEUE_NAME, false);
    }

    @Bean
    TopicExchange exchange() {
    
    
        return new TopicExchange(TOPIC_EXCHANGE_NAME);
    }

    @Bean
    Binding binding(Queue queue, TopicExchange exchange) {
    
    
        return BindingBuilder.bind(queue).to(exchange).with("foo.bar.#");
    }

    @Bean
    MessageListenerAdapter listenerAdapter(Receiver receiver) {
    
    
        return new MessageListenerAdapter(receiver, "receiveMessage");
    }

    @Bean
    SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
                                             MessageListenerAdapter listenerAdapter) {
    
    
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames(QUEUE_NAME);
        container.setMessageListener(listenerAdapter);
        return container;
    }

    public static void main(String[] args) {
    
    
        SpringApplication.run(MessagingRabbitmqApplication.class, args).close();
    }

}

receiver()方法返回一个简单的Receiver对象,这个Receiver对象会被包装到listenerAdapter()方法返回的MessageListenerAdapter里面。再通过addMessageListener()方法添加到RedisMessageListenerContainer里面,对“spring-boot”队列里面的消息进行监听。当消息到达时,会调用Receiver对象的receiveMessage()方法。

JMS队列和AMQP队列的处理方式并不相同。例如,JMS发送排队的消息给单个消费者。但是,如果是AMQP队列的话,AMQP生产者不会直接把消息发到队列。相应的,消息会被发送给Exchange,然后可能进入单个队列,也可能划到多个队列,类似于JMS主题。

监听消息需要消息监听容器和接收器等一些类。而发送消息,则需要RabbitTemplate。

queue()方法创建了AMQP队列。exchange()方法创建了TopicExchange。binding()方法把两者绑定到一起。

为了能被正确地配置,Spring AMQP需要Queue、TopicExchange和Binding必须定义为顶级的Spring Bean。

本例中,TopicExchange和队列用一个路由关键字“foo.bar.#”绑定到了一起。消息的路由关键字如果以“foo.bar.”开头,都会被发送到我们指定的队列。

发送测试消息

首先发送测试消息,然后receiver中的锁存器进行等待,最后关闭程序。
代码如下:

package com.hansy.messagingrabbitmq;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class Runner implements CommandLineRunner {
    
    

    private final RabbitTemplate template;
    private final Receiver receiver;

    public Runner(Receiver receiver, RabbitTemplate template) {
    
    
        this.receiver = receiver;
        this.template = template;
    }

    @Override
    public void run(String... args) throws Exception {
    
    
        System.out.println("Sending message...");
        template.convertAndSend(MessagingRabbitmqApplication.TOPIC_EXCHANGE_NAME, "foo.bar.baz",
                "Hello from RabbitMQ!");
        receiver.getLatch().await(10000, TimeUnit.MILLISECONDS);
    }
}

RabbitTemplate发送消息时,路由键为“foo.bar.baz”,匹配了Binding中设置的规则。

运行程序

main()方法首先创建一个SpringApplication上下文。然后Application上下文启动一个消息监听容器,而消息监听容器开始监听消息。然后定义了一个可以自动运行Runner类。 接着从上下文中取出一个RabbitTemplate对象,然后在“spring-boot”队列上发送一条消息“Hello from RabbitMQ!”。最后,关闭SpringApplication上下文,程序结束。

运行程序,结果如下:

Sending message...
Received <Hello from RabbitMQ!>

小结

你已经用Spring Boot开发了一个利用RabbitMQ完成发布与订阅的程序。

源码下载

messaging-rabbitmq

参考资料

https://spring.io/guides/gs/messaging-rabbitmq/

猜你喜欢

转载自blog.csdn.net/hanshiying007/article/details/107706116