Getting Started with SpringBoot Integration of RabbitMQ

This article explains why RabbitMQ is essential for distributed systems, outlines its core functions and typical scenarios, and provides step‑by‑step instructions for setting up Docker or local installations, adding Maven dependencies, configuring SpringBoot, and implementing Direct, Fanout, and Topic exchange patterns with code examples and troubleshooting tips.

Java Tech Workshop
Java Tech Workshop
Java Tech Workshop
Getting Started with SpringBoot Integration of RabbitMQ

1. Why Learn RabbitMQ?

RabbitMQ is a widely used message middleware in distributed projects that solves the pain point of synchronous calls. In plain terms it provides decoupling, traffic shaping, and asynchronous processing, and can help achieve eventual consistency across services.

Business Decoupling : After an order is placed, payment, inventory, and logistics services can be invoked asynchronously, preventing a single service failure from collapsing the whole flow.

Traffic Shaping : In high‑concurrency scenarios such as flash sales, requests first enter a queue and are consumed gradually according to server capacity.

Asynchronous Processing : Sending SMS, logging, and other operations that do not require the user to wait are handled asynchronously, improving user experience.

Distributed Transaction (Eventual Consistency) : Cross‑service operations can be confirmed via messages to ensure data consistency (advanced topics are omitted for the introductory guide).

Typical Application Scenarios

E‑commerce : Order → Payment → Inventory → Logistics → SMS, all processed asynchronously.

Logging : Asynchronously collect logs to avoid blocking business logic.

Notification : Asynchronously send registration or order‑change emails/SMS.

High‑Concurrency : Buffer flash‑sale requests to prevent server overload.

2. Environment Preparation

Docker One‑Click Installation (recommended):

# Pull image with management UI
docker pull rabbitmq:3-management
# Run container with credentials
docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 \
  -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=123456 \
  --restart=always rabbitmq:3-management

Verify by visiting http://localhost:15672 and logging in with admin/123456.

Local Installation (no Docker) (Windows example):

Install Erlang (download from https://www.erlang.org/downloads, recommended 25.x). Add ERLANG_HOME to PATH and verify with erl -version.

Install RabbitMQ (download from https://www.rabbitmq.com/download.html).

Enable management plugin: rabbitmq-plugins enable rabbitmq_management Start service: rabbitmq-service start and access http://localhost:15672 with guest/guest.

3. Maven Dependencies

<?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.7.18</version>
        <relativePath/>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springboot-rabbitmq-intro</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!-- Web for testing APIs -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- RabbitMQ core -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <!-- Lombok (optional) -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

4. SpringBoot Basic Configuration

Add the following application.yml (copy directly):

spring:
  rabbitmq:
    host: localhost # service address, use IP in production
    port: 5672 # messaging port
    username: admin # Docker account, default is guest locally
    password: 123456 # Docker password, default is guest locally
    virtual-host: / # default virtual host
    listener:
      simple:
        acknowledge-mode: auto # auto‑acknowledge to simplify
        concurrency: 1 # consumer concurrency for introductory use
        publisher-confirm-type: none # disable publisher confirms for simplicity
        publisher-returns: false # disable returns for simplicity

5. Direct Exchange (Point‑to‑Point)

5.1 Configuration (Queue + Exchange + Binding)

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DirectConfig {
    // Declare a durable queue
    @Bean
    public Queue directQueue() {
        return QueueBuilder.durable("direct.queue").autoDelete(false).exclusive(false).build();
    }
    // Declare a direct exchange
    @Bean
    public DirectExchange directExchange() {
        return DirectExchange.directExchange("direct.exchange").durable(true).autoDelete(false).build();
    }
    // Bind with routing key "direct.key"
    @Bean
    public Binding directBinding(Queue directQueue, DirectExchange directExchange) {
        return BindingBuilder.bind(directQueue).to(directExchange).with("direct.key");
    }
}

5.2 Producer (Send Message)

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DirectProducer {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    // Test URL: http://localhost:8080/send/direct/{msg}
    @GetMapping("/send/direct/{msg}")
    public String sendDirect(@PathVariable String msg) {
        String message = "【Direct消息】" + msg;
        rabbitTemplate.convertAndSend("direct.exchange", "direct.key", message);
        return "发送成功:" + message;
    }
}

5.3 Consumer (Listen Message)

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component // must be managed by Spring
public class DirectConsumer {
    @RabbitListener(queues = "direct.queue")
    public void consumeDirect(String msg) {
        System.out.println("Direct消费者接收:" + msg);
    }
}

5.4 Test Steps

Start RabbitMQ and the SpringBoot application.

Visit http://localhost:8080/send/direct/HelloRabbitMQ.

Observe the console output of the consumer confirming receipt.

5.5 Pitfalls

Routing key must exactly match the binding key; otherwise the message is lost.

Queue and exchange should be durable to survive broker restarts.

Consumer class must be annotated with @Component to be detected.

6. Fanout Exchange (Broadcast)

6.1 Configuration (Two Queues + Fanout Exchange)

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FanoutConfig {
    @Bean
    public Queue fanoutQueue1() { return QueueBuilder.durable("fanout.queue1").build(); }
    @Bean
    public Queue fanoutQueue2() { return QueueBuilder.durable("fanout.queue2").build(); }
    @Bean
    public FanoutExchange fanoutExchange() {
        return FanoutExchange.fanoutExchange("fanout.exchange").durable(true).build();
    }
    @Bean
    public Binding fanoutBinding1(Queue fanoutQueue1, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
    }
    @Bean
    public Binding fanoutBinding2(Queue fanoutQueue2, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);
    }
}

6.2 Producer (Broadcast Message)

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FanoutProducer {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    // Test URL: http://localhost:8080/send/fanout/{msg}
    @GetMapping("/send/fanout/{msg}")
    public String sendFanout(@PathVariable String msg) {
        String message = "【Fanout广播消息】" + msg;
        rabbitTemplate.convertAndSend("fanout.exchange", "", message); // routing key ignored
        return "广播发送成功:" + message;
    }
}

6.3 Consumers (Two Listeners)

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class FanoutConsumer {
    @RabbitListener(queues = "fanout.queue1")
    public void consumeFanout1(String msg) {
        System.out.println("Fanout消费者1接收:" + msg);
    }
    @RabbitListener(queues = "fanout.queue2")
    public void consumeFanout2(String msg) {
        System.out.println("Fanout消费者2接收:" + msg);
    }
}

6.4 Test & Pitfalls

After calling the API, both consumers receive the message. The fanout exchange does not require a routing key; any provided key is ignored.

7. Topic Exchange (Pattern Matching)

7.1 Wildcard Rules

#

: matches one or more words (e.g., order.# matches order.create and order.pay.success). *: matches exactly one word (e.g., order.* matches order.create but not order.pay.success).

7.2 Configuration (Three Queues + Topic Exchange)

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TopicConfig {
    @Bean public Queue topicQueue1() { return QueueBuilder.durable("topic.queue1").build(); }
    @Bean public Queue topicQueue2() { return QueueBuilder.durable("topic.queue2").build(); }
    @Bean public Queue topicQueue3() { return QueueBuilder.durable("topic.queue3").build(); }
    @Bean public TopicExchange topicExchange() {
        return TopicExchange.topicExchange("topic.exchange").durable(true).build();
    }
    @Bean public Binding topicBinding1(Queue topicQueue1, TopicExchange topicExchange) {
        return BindingBuilder.bind(topicQueue1).to(topicExchange).with("order.#");
    }
    @Bean public Binding topicBinding2(Queue topicQueue2, TopicExchange topicExchange) {
        return BindingBuilder.bind(topicQueue2).to(topicExchange).with("order.pay.*");
    }
    @Bean public Binding topicBinding3(Queue topicQueue3, TopicExchange topicExchange) {
        return BindingBuilder.bind(topicQueue3).to(topicExchange).with("*.login");
    }
}

7.3 Producer (Different Routing Keys)

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TopicProducer {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    // 1. order.create → matches queue1
    @GetMapping("/send/topic/order/create")
    public String sendTopic1() {
        String msg = "订单创建:10001";
        rabbitTemplate.convertAndSend("topic.exchange", "order.create", msg);
        return "发送成功:" + msg;
    }
    // 2. order.pay.success → matches queue1 and queue2
    @GetMapping("/send/topic/order/pay/success")
    public String sendTopic2() {
        String msg = "订单支付:10001,99元";
        rabbitTemplate.convertAndSend("topic.exchange", "order.pay.success", msg);
        return "发送成功:" + msg;
    }
    // 3. user.login → matches queue3
    @GetMapping("/send/topic/user/login")
    public String sendTopic3() {
        String msg = "用户登录:admin";
        rabbitTemplate.convertAndSend("topic.exchange", "user.login", msg);
        return "发送成功:" + msg;
    }
}

7.4 Consumers & Test

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class TopicConsumer {
    @RabbitListener(queues = "topic.queue1")
    public void consumeTopic1(String msg) {
        System.out.println("Topic消费者1(order.#):" + msg);
    }
    @RabbitListener(queues = "topic.queue2")
    public void consumeTopic2(String msg) {
        System.out.println("Topic消费者2(order.pay.*):" + msg);
    }
    @RabbitListener(queues = "topic.queue3")
    public void consumeTopic3(String msg) {
        System.out.println("Topic消费者3(*.login):" + msg);
    }
}

Calling the three APIs in order prints the expected messages on the console. Remember to use dot‑separated routing keys; otherwise the wildcard rules do not apply and the message is dropped.

8. Comparison of Exchange Types

Direct

Core Feature: One‑to‑one precise routing.

Routing Rule: Routing key must exactly match the binding key.

Typical Scenario: Point‑to‑point communication such as order processing or personal notifications.

Fanout

Core Feature: One‑to‑many broadcast.

Routing Rule: No routing key needed; messages are sent to all bound queues.

Typical Scenario: System announcements, activity notifications.

Topic

Core Feature: Many‑to‑many with pattern matching.

Routing Rule: Uses # and * wildcards for flexible matching.

Typical Scenario: Complex routing such as module‑based message distribution.

9. Common Issues and Solutions (FAQ)

Message sent but consumer does not receive it?

Cause: Incorrect binding, missing @Component on consumer, or non‑durable queue.

Solution: Verify binding relationships, add the annotation, and ensure durability.

Management UI login fails?

Cause: Wrong credentials or the default guest user not allowed remote login.

Solution: Check username/password and add loopback_users = none to rabbitmq.conf, then restart.

Application cannot connect to RabbitMQ?

Cause: RabbitMQ not started, configuration errors, or ports 5672/15672 blocked.

Solution: Start RabbitMQ, verify application.yml settings, and open the required ports.

Learning is a long‑term accumulation; there are no shortcuts. Use the above practical guide to integrate RabbitMQ with SpringBoot, experiment with the three exchange patterns, and apply the knowledge to real projects.

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.

JavaIntegrationMessage QueueDirect ExchangeFanout ExchangeTopic Exchange
Java Tech Workshop
Written by

Java Tech Workshop

Focused on Java backend technologies, sharing fundamentals, multithreading, JVM, the Spring ecosystem, microservices, distributed systems, high concurrency, source‑code analysis, and practical experience. Continuously delivers high‑quality original content, interview guides, and learning roadmaps to help Java developers progress from beginner to advanced, enhancing technical skills and core competitiveness.

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.