原文地址:
https://spring.io/guides/gs/messaging-rabbitmq/
如原作者发现有侵权行为可责令我在24小时之内删除,前提是你能看到。
翻译者:毛毛可
本指南会从头带着你设置RabbitMQ(AMQP)服务,来发布和订阅消息.
What you'll build
你将创建一个应用,使用Spring AMQP的RabbitTemplate
来发送消息,并使用MessageListenerAdapter
订阅消息到一个POJO上.
What you’ll need
- 大约15分钟的时间
- 一个喜欢的IDE或编辑器
- JDK 1.8或以上
- Gradle 4+ 或 Maven 3.2+
- 你也可以直接将代码导入到你的IDE中:
- RabbitMQ 服务器
How to complete this guide
就像大多数Spring的入门指南一样,你可以从头开始完成每个步骤,或者你已经对此非常熟悉,那么就直接跳过配置部分.再或者直接运行代码.
如想从头开始,请滚动到Build with Gradle处.
如想跳过基本知识,请执行下面的操作:
-
下载并解压本文的源码,你也可以使用Git
clone
命令:git clone https://github.com/spring-guides/gs-messaging-rabbitmq.git
进行下载 -
cd
命令进入gs-messaging-rabbitmq/initial
目录 - 跳转到Create a RabbitMQ message receiver标题
当你完成以后,你可以对照gs-messaging-rabbitmq/complete
目录下的源码来检查.
Build with Gradle
首先要设置一个基本的构建脚本.在使用Spring构建应用时,你可以使用任意你喜欢的构建系统.但是你需要包括Gradle和Maven所需要的代码.如果你并不熟悉它们,可以参考Building Java Projects with Gradle或Building Java Projects with Maven.
Create the directory structure
选择一个项目目录,创建以下子目录结构;例如,在*nix系统中使用mkdir -p src/main/java/hello
创建目录.
└── src
└── main
└── java
└── hello
Create a Gradle build file
以下是Gradle构建文件的初始化.
build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.5.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
bootJar {
baseName = 'gs-messaging-rabbitmq'
version = '0.1.0'
}
repositories {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile("org.springframework.boot:spring-boot-starter-amqp")
testCompile("junit:junit")
}
Spring Boot Gradle插件挺了许多方便的特性:
- 集合classpath下的所有jar包,构建成一个单独的可运行的"über-jar", 使其更方便的执行你的应用服务.
- 搜索
public static void main()
来标记为可运行类的方法. - 提供了一个内置构建的依赖解析器,设置了版本号来匹配Spring Boot的依赖.你可以覆盖任意的版本,否则将会选择Boot的默认版本号.
Build with Maven
选择一个项目目录,创建以下子目录结构;例如,在*nix系统中使用mkdir -p src/main/java/hello
创建目录.
└── src
└── main
└── java
└── hello
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>gs-messaging-rabbitmq</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Spring Boot Maven插件挺了许多方便的特性:
- 集合classpath下的所有jar包,构建成一个单独的可运行的"über-jar", 使其更方便的执行你的应用服务.
- 搜索
public static void main()
来标记为可运行类的方法. - 提供了一个内置构建的依赖解析器,设置了版本号来匹配Spring Boot的依赖.你可以覆盖任意的版本,否则将会选择Boot的默认版本号.
Build with your IDE
- 如何将本指南直接导入Spring Tool Suite.
- 如何使用IntelliJ IDEA来工作.
Set up RabbitMQ broker
在构建你自己的消息应用之前,你需要设置消息服务器,才能接收和发送消息.
RabbitMQ是一个AMQP协议的服务器.它是完全免费可用的.网址是http://www.rabbitmq.com/download.html.你可以手动下载它,或者如果你使用的是Mac电脑,医用homebrew来进行安装:
brew install rabbitmq
解压并使用默认配置启动.
rabbitmq-server
你将会看到类似以下:
RabbitMQ 3.1.3. Copyright (C) 2007-2013 VMware, Inc.
## ## Licensed under the MPL. See http://www.rabbitmq.com/
## ##
########## Logs: /usr/local/var/log/rabbitmq/rabbit@localhost.log
###### ## /usr/local/var/log/rabbitmq/rabbit@localhost-sasl.log
##########
Starting broker... completed with 6 plugins.
如果你本地有使用Docker,你也可以使用Docker Compose来快速启动一个RabbitMQ服务.下面是Github上的"完整"项目的根路径的docker-compose.yml文件.非常简单:
docker-compose.yml
rabbitmq:
image: rabbitmq:management
ports:
- "5672:5672"
- "15672:15672"
在当前的目录下使用这个文件,你可以执行docker-compose up
命令,在一个docker容器中运行RabbitMQ服务.
Create a RabbitMQ message receiver
任何基于消息的应用,都需要创建一个接收者来响应发送的消息.
src/main/java/hello/Receiver.java
package hello;
import java.util.concurrent.CountDownLatch;
import org.springframework.stereotype.Component;
@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;
}
}
接收者就是一个简单的POJO类,实现了一个接受消息的方法.当你将其注册来接收消息时,你可以随意给它命名.
为了方便,这个POJO会有一个CountDownLatch对象.这允许它发信号通知接收到消息.这种方式不太可能会出现生产环境的应用实现中.
Register the listener and send a message
Spring AMQP的 RabbitTemplate类提供了所有你使用RabbitMQ时的所有的发送和接收消息的功能.主要注意的是,你需要配置:
- 一个消息监听容器
- 声明一个队列,交换机,和它们之间的绑定关系
- 一个发送消息到监听者的component
Spring Boot 会自动创建一个
connection factory
和RabbitTemplate
,省去了不必要的代码量
你将使用RabbitTemplate
来返送消息,同时你将会注册一个接收者来接收消息监听容器接收到的消息.connection factory
会让它们连接到RabbitMQ服务.
src/main/java/hello/Application.java
package hello;
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 Application {
static final String topicExchangeName = "spring-boot-exchange";
static final String queueName = "spring-boot";
@Bean
Queue queue() {
return new Queue(queueName, false);
}
@Bean
TopicExchange exchange() {
return new TopicExchange(topicExchangeName);
}
@Bean
Binding binding(Queue queue, TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with("foo.bar.#");
}
@Bean
SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(queueName);
container.setMessageListener(listenerAdapter);
return container;
}
@Bean
MessageListenerAdapter listenerAdapter(Receiver receiver) {
return new MessageListenerAdapter(receiver, "receiveMessage");
}
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(Application.class, args).close();
}
}
@SpringBootApplication
是一个有多个功能的遍历注解:
-
@Configuration
标记此类为定义bean的应用上下文源. -
@EnableAutoConfiguration
告诉Spring Boot基于classpath设置,其它的bean,和各种属性设置来开始添加bean. - 通常情况下,你需要为Spring MAC应用添加
@EnableWebMvc
,但当在classpath下发现spring-webmvc依赖后自动添加此注解.这将应用标记为一个web应用,并激活关键的行为,如设置一个DispatcherServlet
. -
@ComponentScan
会告诉Spring在hello
package中,来发现其它的component,configuration和service,并允许找到controller.
main()
方法会调用 Spring Boot’s SpringApplication.run()
方法来启动应用.你是否发现了这里并没有一行XML语句,也没有web.xml文件.这个web应用就是一个100%纯Java应用,你并不要配置任何基础配置.
使用listenerAdapter()
方法定义的bean,会作为一个消息监听者被注册到消息监听容器中,该容器使用container()
方法定义.它将会监听"spring-boot"队列的消息.因为接收这是个一个POJO,它需要被封装到MessageListenerAdapter中,来指定调用receiveMessage
方法.
JMS队列和AMQP队列有一些不同的语法.比如,JMS只会发送队列消息到一个消费者.AMQP提供者不会讲消息直接发送到队列中.而是消息会被发送到交换机(exchange)上,然后可以被发送到单独的队列,或分发到多个队列中,很想JMS topics的概念.想要了解更多,请参阅Understanding AMQP
消息监听容器和接收者,是你需要监听消息的bean.要发送一个消息,你也需要一个RabbitTemplate
.
queue()
方法会创建一个AMQP队列.exchange()
方法会穿件一个topic类型的交换机.binding()
方法会将它们绑定一起,来定义RabbitTemplate发送消息到交换机时发生的行为.
Spring AMQP要求Queue,TopicExchange和Binding被声明为顶级Spring bean,为了能够设置他们的属性.
在本例中,我们使用路由keyfoo.bar.#
绑定topic交换机和队列,这意味着任何以foo.bar.
作为路由key的消息都会被路由到对应队列上.
Send a Test Message
通过CommandLineRunner
来发送文本消息,会等待接收者的latch之后关闭上下文:
src/main/java/hello/Runner.java
package hello;
import java.util.concurrent.TimeUnit;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class Runner implements CommandLineRunner {
private final RabbitTemplate rabbitTemplate;
private final Receiver receiver;
public Runner(Receiver receiver, RabbitTemplate rabbitTemplate) {
this.receiver = receiver;
this.rabbitTemplate = rabbitTemplate;
}
@Override
public void run(String... args) throws Exception {
System.out.println("Sending message...");
rabbitTemplate.convertAndSend(Application.topicExchangeName, "foo.bar.baz", "Hello from RabbitMQ!");
receiver.getLatch().await(10000, TimeUnit.MILLISECONDS);
}
}
注意template路由消息到交换机,指定的路由keyfoo.bar.baz
会binding的路由规则匹配.
runner可以在test中模拟,所以可以单独的测试接收者.
Run the Application
main()
方法开始会创建Spring应用上下文.消息监听容器会开始监听消息的到达.这时,Runner
bean会自动被执行: 它从上下文中接收RabbitTemplate
,并发送"Hello from RabbitMQ!"消息到"spring-boot"队列中.最后,关闭应用上下文并结束程序.
Build an executable JAR
你可以在命令行使用Gradle或Maven来运行应用.或者你可以构建一个单独的可执行的包含必须的依赖,class文件,资源文件的JAR文件,并运行.这使得在整个开发生命周期中,跨不同环境等将服务作为应用程序发布,版本和部署变得容易。
如果你使用Gradle, 可以使用./gradlew bootRun
运行应用.或者使用./gradlew build
构建JAR文件,然后运行JAR文件:
java -jar build/libs/gs-messaging-rabbitmq-0.1.0.jar
If you are using Maven, you can run the application using ./mvnw spring-boot:run. Or you can build the JAR file with ./mvnw clean package. Then you can run the JAR file:
如果你使用Maven,可以使用./mvnw spring-boot:run
运行应用.或者使用./mvnw clean package
构建JAR文件.然后运行JAR文件:
java -jar target/gs-messaging-rabbitmq-0.1.0.jar
上一步会创建一个可运行的JAR.你也可以构建一个WAR来代替.
你会看到以下输出:
Sending message...
Received <Hello from RabbitMQ!>
Summary
大功告成.你现在仅仅是使用Spring和RabbitMQ开发了一个简单的发送-订阅功能的应用.使用Spring和RabbitMQ可以做的比这里介绍的更多,不过这也是个好的开始.
网友评论