Master RabbitMQ with Spring AMQP: Install, Configure, and Implement 5 Core Messaging Patterns

This tutorial walks you through installing RabbitMQ on Windows and Linux, configuring it, and using Spring AMQP to implement five fundamental messaging patterns—simple, work, publish/subscribe, routing, and wildcard—complete with code examples and test endpoints.

macrozheng
macrozheng
macrozheng
Master RabbitMQ with Spring AMQP: Install, Configure, and Implement 5 Core Messaging Patterns

Introduction

RabbitMQ is one of the most popular open‑source message brokers, lightweight, easy to deploy, and supports multiple messaging protocols. It can be used in distributed systems to meet high‑availability and large‑scale requirements.

Related Concepts

We first introduce key RabbitMQ concepts using the routing pattern as an example.

Installation and Configuration

Windows Installation

Install Erlang from http://erlang.org/download/otp_win64_21.3.exe

Install RabbitMQ from https://dl.bintray.com/rabbitmq/all/rabbitmq-server/3.7.14/rabbitmq-server-3.7.14.exe

After installation, go to the sbin directory and enable the management plugin:

rabbitmq-plugins enable rabbitmq_management

Linux Installation

Pull the RabbitMQ Docker image: docker pull rabbitmq:3.7.15 Run the container exposing the default ports:

docker run -p 5672:5672 -p 15672:15672 --name rabbitmq \
-d rabbitmq:3.7.15

Enter the container and enable the management plugin:

docker exec -it rabbitmq /bin/bash
rabbitmq-plugins enable rabbitmq_management

Open the firewall for external access:

firewall-cmd --zone=public --add-port=15672/tcp --permanent
firewall-cmd --zone=public --add-port=5672/tcp --permanent
firewall-cmd --reload

Access and Configuration

Open http://localhost:15672/ and log in with the default credentials guest/guest.

Create a new user mall/mall with administrator role.

Create a virtual host /mall and assign permissions to the mall user.

Five Messaging Patterns

These patterns form the foundation of RabbitMQ‑based applications. Below we implement them with Spring AMQP.

Simple Pattern

A single producer, a single consumer, and one queue.

Spring AMQP Implementation

Add Spring AMQP dependency to pom.xml.

Configure connection in application.yml:

spring:
  rabbitmq:
    host: localhost
    port: 5672
    virtual-host: /mall
    username: mall
    password: mall
    publisher-confirms: true
    publisher-returns: true

Create queue simple.hello, a producer SimpleSender, and a consumer SimpleReceiver.

@Configuration
public class SimpleRabbitConfig {
    @Bean
    public Queue hello() { return new Queue("simple.hello"); }
    @Bean
    public SimpleSender simpleSender() { return new SimpleSender(); }
    @Bean
    public SimpleReceiver simpleReceiver() { return new SimpleReceiver(); }
}

public class SimpleSender {
    @Autowired private RabbitTemplate template;
    private static final String QUEUE = "simple.hello";
    public void send() { template.convertAndSend(QUEUE, "Hello World!"); }
}

@RabbitListener(queues = "simple.hello")
public class SimpleReceiver {
    @RabbitHandler
    public void receive(String in) { /* log */ }
}

Work Queue Pattern

Multiple consumers compete for messages from a single queue.

Spring AMQP Implementation

Create queue work.hello, a producer WorkSender, and two consumers WorkReceiver (instances 1 and 2).

@Configuration
public class WorkRabbitConfig {
    @Bean public Queue workQueue() { return new Queue("work.hello"); }
    @Bean public WorkSender workSender() { return new WorkSender(); }
    @Bean public WorkReceiver workReceiver1() { return new WorkReceiver(1); }
    @Bean public WorkReceiver workReceiver2() { return new WorkReceiver(2); }
}

public class WorkSender {
    @Autowired private RabbitTemplate template;
    private static final String QUEUE = "work.hello";
    public void send(int index) { /* build message with varying dots */ }
}

@RabbitListener(queues = "work.hello")
public class WorkReceiver {
    private final int instance;
    public WorkReceiver(int i) { this.instance = i; }
    @RabbitHandler
    public void receive(String in) { /* simulate work based on dot count */ }
}

Publish/Subscribe (Fanout) Pattern

Messages are broadcast to all bound queues.

Spring AMQP Implementation

Declare a FanoutExchange named exchange.fanout, two anonymous queues, and bind them.

@Configuration
public class FanoutRabbitConfig {
    @Bean public FanoutExchange fanout() { return new FanoutExchange("exchange.fanout"); }
    @Bean public Queue fanoutQueue1() { return new AnonymousQueue(); }
    @Bean public Queue fanoutQueue2() { return new AnonymousQueue(); }
    @Bean public Binding fanoutBinding1(FanoutExchange fanout, Queue fanoutQueue1) { return BindingBuilder.bind(fanoutQueue1).to(fanout); }
    @Bean public Binding fanoutBinding2(FanoutExchange fanout, Queue fanoutQueue2) { return BindingBuilder.bind(fanoutQueue2).to(fanout); }
    @Bean public FanoutSender fanoutSender() { return new FanoutSender(); }
    @Bean public FanoutReceiver fanoutReceiver() { return new FanoutReceiver(); }
}

public class FanoutSender {
    @Autowired private RabbitTemplate template;
    private static final String EXCHANGE = "exchange.fanout";
    public void send(int index) { /* build message with dots */ template.convertAndSend(EXCHANGE, "", message); }
}

@RabbitListener(queues = "#{fanoutQueue1.name}")
public class FanoutReceiver {
    @RabbitHandler
    public void receive1(String in) { /* process */ }
    @RabbitListener(queues = "#{fanoutQueue2.name}")
    public void receive2(String in) { /* process */ }
}

Routing (Direct) Pattern

Messages are routed to queues based on a routing key.

Spring AMQP Implementation

Declare a DirectExchange named exchange.direct, two anonymous queues, and bind them with keys orange, black, green.

@Configuration
public class DirectRabbitConfig {
    @Bean public DirectExchange direct() { return new DirectExchange("exchange.direct"); }
    @Bean public Queue directQueue1() { return new AnonymousQueue(); }
    @Bean public Queue directQueue2() { return new AnonymousQueue(); }
    @Bean public Binding directBinding1a(DirectExchange direct, Queue directQueue1) { return BindingBuilder.bind(directQueue1).to(direct).with("orange"); }
    @Bean public Binding directBinding1b(DirectExchange direct, Queue directQueue1) { return BindingBuilder.bind(directQueue1).to(direct).with("black"); }
    @Bean public Binding directBinding2a(DirectExchange direct, Queue directQueue2) { return BindingBuilder.bind(directQueue2).to(direct).with("green"); }
    @Bean public Binding directBinding2b(DirectExchange direct, Queue directQueue2) { return BindingBuilder.bind(directQueue2).to(direct).with("black"); }
    @Bean public DirectSender directSender() { return new DirectSender(); }
    @Bean public DirectReceiver directReceiver() { return new DirectReceiver(); }
}

public class DirectSender {
    @Autowired private RabbitTemplate template;
    private static final String EXCHANGE = "exchange.direct";
    private final String[] keys = {"orange", "black", "green"};
    public void send(int index) { String key = keys[index % keys.length]; template.convertAndSend(EXCHANGE, key, "Hello " + key + " " + (index+1)); }
}

@RabbitListener(queues = "#{directQueue1.name}")
public class DirectReceiver {
    @RabbitHandler
    public void receive1(String in) { /* process */ }
    @RabbitListener(queues = "#{directQueue2.name}")
    public void receive2(String in) { /* process */ }
}

Wildcard (Topic) Pattern

Routing based on pattern matching with * and # wildcards.

Spring AMQP Implementation

Declare a TopicExchange named exchange.topic, two anonymous queues, and bind them with patterns *.orange.*, *.*.rabbit (queue 1) and lazy.# (queue 2).

@Configuration
public class TopicRabbitConfig {
    @Bean public TopicExchange topic() { return new TopicExchange("exchange.topic"); }
    @Bean public Queue topicQueue1() { return new AnonymousQueue(); }
    @Bean public Queue topicQueue2() { return new AnonymousQueue(); }
    @Bean public Binding topicBinding1a(TopicExchange topic, Queue topicQueue1) { return BindingBuilder.bind(topicQueue1).to(topic).with("*.orange.*"); }
    @Bean public Binding topicBinding1b(TopicExchange topic, Queue topicQueue1) { return BindingBuilder.bind(topicQueue1).to(topic).with("*.*.rabbit"); }
    @Bean public Binding topicBinding2a(TopicExchange topic, Queue topicQueue2) { return BindingBuilder.bind(topicQueue2).to(topic).with("lazy.#"); }
    @Bean public TopicSender topicSender() { return new TopicSender(); }
    @Bean public TopicReceiver topicReceiver() { return new TopicReceiver(); }
}

public class TopicSender {
    @Autowired private RabbitTemplate template;
    private static final String EXCHANGE = "exchange.topic";
    private final String[] keys = {"quick.orange.rabbit", "lazy.orange.elephant", "quick.orange.fox", "lazy.brown.fox", "lazy.pink.rabbit", "quick.brown.fox"};
    public void send(int index) { String key = keys[index % keys.length]; template.convertAndSend(EXCHANGE, key, "Hello " + key + " " + (index+1)); }
}

@RabbitListener(queues = "#{topicQueue1.name}")
public class TopicReceiver {
    @RabbitHandler
    public void receive1(String in) { /* process */ }
    @RabbitListener(queues = "#{topicQueue2.name}")
    public void receive2(String in) { /* process */ }
}

Reference

RabbitMQ Tutorials: https://www.rabbitmq.com/getstarted.html

Source Code

https://github.com/macrozheng/mall-learning/tree/master/mall-tiny-rabbit

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaDockerMessage QueuesRabbitMQMessaging Patternsspring-amqp
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.