Original title: Spring certified China Education Management Center - learn how to use spring and rabbit MQ to create a simple publish and subscribe application. (content source: Spring China Education Management Center)
This guide will guide you through the process of setting up a RabbitMQ AMQP server that publishes and subscribes to messages and creating a Spring Boot application to interact with the RabbitMQ server.
What will you build
You will build an application that publishes the message RabbitTemplate using Spring AMQP and uses the messagelistener adapter
What do you need?
- About 15 minutes
- Favorite text editor or IDE
- JDK 11 or later
- Gradle 4 + or Maven 3.2+
- You can also import the code directly into the IDE: spring tool kit (STS)IntelliJ IDEA sets up the RabbitMQ server. See setting up the RabbitMQ agent.
How to complete this guide
Like most Spring getting started guides, you can start from scratch and complete each step, or you can bypass the basic setup steps you are already familiar with. Either way, you'll end up with working code.
To start from scratch, continue setting up the RabbitMQ proxy.
To skip the basics:
- Download and unzip the source code base of this guide, or clone it with Git: git clone https://github.com/spring-guides/gs-messaging-rabbitmq.git
- The CD goes to GS messaging rabbitmq / initial
- Jump to start with Spring Initializr.
When you are finished, you can check the results against the code in gs-messaging-rabbitmq/complete.
Setting up RabbitMQ proxy
Before building a messaging application, you need to set up a server to handle receiving and sending messages.
RabbitMQ is an AMQP server. The server can be https://www.rabbitmq.com/download.html Free. You can download it manually, or if you use a Mac with Homebrew, you can run the following command in the terminal window:
brew install rabbitmq
Unzip the server and start it with default settings by running the following command in the terminal window:
rabbitmq-server
You should see output similar to the following:
RabbitMQ 3.1.3. Copyright (C) 2007-2013 VMware, Inc. ## ## Licensed under the MPL. See https://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.
If you run Docker locally, you can also use Docker Compose to quickly start the RabbitMQ server. Github project Docker Compose There is one in the root directory of YML. complete this is very simple, as shown in the following listing:
rabbitmq: image: rabbitmq:management ports: - "5672:5672" - "15672:15672"
Using this file in the current directory, you can run docker compose up to make RabbitMQ run in the container.
Start with Spring Initializr
You can use this pre initialized project and click Generate to download the ZIP file. This project is configured to fit the examples in this tutorial.
Manually initialize the project:
- Navigate to https://start.spring.io . The service extracts all the dependencies required by the application and completes most of the settings for you.
- Select Gradle or Maven and the language you want to use. This guide assumes that you have chosen Java.
- Click Dependencies and select Spring for rabbit MQ.
- Click generate.
- Download the generated ZIP file, which is an archive of the Web application configured according to your choice.
If your IDE has spring initializer integration, you can complete this process from your IDE.
You can also fork the project from Github and open it in your IDE or other editor.
Create a RabbitMQ message sink
For any messaging based application, you need to create a receiver that responds to published messages. The following list (from src/main/java/com.example.messagingrabbitmq/Receiver.java) shows how to do this:
package com.example.messagingrabbitmq; 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; } }
The Receiver is a POJO, which defines the method of receiving messages. When you register it to receive messages, you can name it whatever you want.
For convenience, this POJO also has a CountDownLatch This lets it signal that a message has been received. This is something you are unlikely to implement in a production application.
Register listeners and send messages
Spring AMQPRabbitTemplate provides everything you need to send and receive messages using RabbitMQ. However, you need to:
- Configure the message listener container.
- Declare queues, switches, and bindings between them.
- Configure a component to send some messages to test the listener.
Spring Boot automatically creates connection factories and rabbittemplates, reducing the amount of code you have to write.
You will use the RabbitTemplate to send messages, and you will register a Receiver with the message listener container to receive messages. Connect the factory drivers and connect them to the RabbitMQ server. The following list (from src/main/java/com.example.messagingrabbitmq/MessagingRabbitApplication.java) shows how to create an application class:
package com.example.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 { 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(MessagingRabbitmqApplication.class, args).close(); } }
@SpringBootApplication is a convenient annotation that adds all of the following:
- @Configuration: marks the class as the bean definition source of the application context.
- @EnableAutoConfiguration: Tell Spring Boot to start adding beans according to classpath settings, other beans and various property settings. For example, if spring webmvc is on the classpath, this annotation marks the application as a Web application and activates key behaviors, such as setting DispatcherServlet
- @ComponentScan: Tell Spring to find other components, configurations and services com/example in the package and let it find the controller.
The main() method uses springapplication. Of Spring Boot Run () method to start the application. Have you noticed that there is no single line of XML? There is no Web XML file. This Web application is 100% pure Java, and you don't have to deal with any pipeline or infrastructure configuration.
The beanlistenerAdapter() defined in the method is registered as a message listener in the container (defined in container()). It listens for messages in the spring boot queue. Because the Receiver class is a POJO, it needs to be wrapped in a MessageListenerAdapter, where you can specify it to call receiveMessage
JMS queues and AMQP queues have different semantics. For example, JMS sends queued messages to only one consumer. Although the AMQP queue does the same thing, the AMQP producer does not send messages directly to the queue. Instead, a message is sent to a switch that can send to a single queue or fan out to multiple queues, simulating the concept of JMS topics.
The message listener container and receiver bean s are all you need to listen for messages. To send a message, you also need a Rabbit template.
This queue() method creates an AMQP queue. This exchange() method creates a topic exchange. This method binds the two together and defines the behavior that occurs when publishing to exchange binding(). RabbitTemplate
Spring AMQP requires that Queue, TopicExchange, and Binding be declared as top-level spring beans for proper setup.
In this case, we use topic switching, and the queue is bound to the routing key foo bar.#, This means that any message sent by a routing key that begins with a will be foo bar. Is routed to the queue.
Send test message
In this example, the test message is sent by a to the CommandLineRunner, which also waits for a latch in the receiver and closes the application context. The following list (from src/main/java/com.example.messagingrabbitmq/Runner.java) shows how it works:
package com.example.messagingrabbitmq; 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(MessagingRabbitmqApplication.topicExchangeName, "foo.bar.baz", "Hello from RabbitMQ!"); receiver.getLatch().await(10000, TimeUnit.MILLISECONDS); } }
foo.bar.baz note that the template routes messages to the switch using routing keys that match the binding.
In testing, you can simulate the runner so that you can test the receiver separately.
Run the application
The main() method starts the process by creating a spring application context. This starts the message listener container, which starts listening for messages. There is a runner bean and it will run automatically. It retrieves from the application context and sends Hello from RabbitMQ in the queue RabbitTemplate! News. Spring boot finally, it closes the spring application context and the application ends.
Build an executable JAR
You can run the application from the command line using Gradle or Maven. You can also build and run a single executable jar file that contains all the necessary dependencies, classes, and resources. Building executable jars can easily deliver, versione and deploy services as applications throughout the development life cycle, across different environments, and so on.
If you use Gradle, you can use/ gradlew bootRun. Alternatively, you can use to build JAR files/ gradlew build, and then run the} JAR file as follows:
java -jar build/libs/gs-messaging-rabbitmq-0.1.0.jar
If you use Maven, you can use/ mvnw spring-boot:run. Alternatively, you can use the build JAR file/ mvnw clean package and run the JAR file as follows:
java -jar target/gs-messaging-rabbitmq-0.1.0.jar
The steps described here create a runnable JAR. You can also build classic WAR files.
You should see the following output:
Sending message... Received <Hello from RabbitMQ!>copy
summary
congratulations! You just developed a simple publish and subscribe application using Spring and rabbit MQ. You can do more with Spring and rabbit MQ than here, but this guide should provide a good start.