美文网首页JAVA
Messaging with RabbitMQ

Messaging with RabbitMQ

作者: 毛毛可 | 来源:发表于2018-12-12 17:25 被阅读4次

原文地址:
https://spring.io/guides/gs/messaging-rabbitmq/
如原作者发现有侵权行为可责令我在24小时之内删除,前提是你能看到。
翻译者:毛毛可

本指南会从头带着你设置RabbitMQ(AMQP)服务,来发布和订阅消息.

What you'll build

你将创建一个应用,使用Spring AMQP的RabbitTemplate来发送消息,并使用MessageListenerAdapter订阅消息到一个POJO上.

What you’ll need

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构建应用时,你可以使用任意你喜欢的构建系统.但是你需要包括GradleMaven所需要的代码.如果你并不熟悉它们,可以参考Building Java Projects with GradleBuilding 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

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 factoryRabbitTemplate,省去了不必要的代码量

你将使用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在hellopackage中,来发现其它的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可以做的比这里介绍的更多,不过这也是个好的开始.

相关文章

网友评论

    本文标题:Messaging with RabbitMQ

    本文链接:https://www.haomeiwen.com/subject/jrzpxqtx.html