SpringBoot 使用 spring-boot-starter-amqp 起步依赖实现 RabbitMQ 代码示例(二)


RabbitMQ
本文是工作之余的随手记,记录在工作期间使用 RabbitMQ 的笔记。



1、实现方式说明

SpringBoot 使用 spring-boot-starter-amqp 起步依赖实现 RabbitMQ 代码示例(一)

本文是承接上文,使用以下方式实现 RabbitMQ 功能。

  • 发送消息有多种解决方式,本文使用注入 RabbitTemplate,直接调用 convertAndSend 方法发送消息,支持自动消息转换(如 JSON 序列化)。
  • 消费消息有多种解决方式,本文在方法上使用 @RabbitListener 注解监听队列,支持消息体自动反序列化为对象。

1、实现代码结构如下:

实现代码结构


2、交换机

交换机


3、队列和路由键绑定
队列和路由键绑定


2、配置文件:application.yml

server:
  port: 8089

#开发站
spring:
  rabbitmq:
    host: 10.106.18.54
    port: 5672
    username: root
    password: 123456789
    listener:
      type: direct
      direct:
        prefetch: 250
        concurrency: 16 # 消费线程池核心线程数
        max-concurrency: 32 # 消费线程池最大线程数
        acknowledge-mode: auto # 自动确认消息
    exchangeRjwTest: 'sync.ex.rjw.test'
    queueRjwTest: 'ha.queue.rjw.test'
    routeRjwTest: 'route.rjw.test'

3、依赖文件:pom.xml

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>3.4.1</version>
	<relativePath/> <!-- lookup parent from repository -->
</parent>

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-amqp</artifactId>
	</dependency>
</dependencies>

4、配置类:RabbitMQConfig

package com.wen.rabbit.config;

import lombok.Data;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author : rjw
 * @date : 2025-07-07
 */
@Configuration
@Data
public class RabbitMQConfig {

    @Value("${spring.rabbitmq.exchangeRjwTest}")
    private String exchangeRjwTest;

    @Value("${spring.rabbitmq.queueRjwTest}")
    private String queueRjwTest;

    @Value("${spring.rabbitmq.routeRjwTest}")
    private String routeRjwTest;

    @Bean
    public DirectExchange exchangeRjwTest() {
        return new DirectExchange(exchangeRjwTest);
    }

    @Bean
    public Queue queueRjwTest() {
        return new Queue(queueRjwTest);
    }

    @Bean
    public Binding bindingRjwTest01() {
        return BindingBuilder.bind(queueRjwTest()).to(exchangeRjwTest()).with(routeRjwTest);
    }

}

5、消息类:MQEntity

package com.wen.rabbit.model;

import com.alibaba.fastjson.JSONObject;
import lombok.Data;

/**
 * @author : rjw
 * @date : 2025-07-07
 */
@Data
public class MQEntity<T> {

    private String type;

    private long tm;

    private int crmId;

    private String who;

    private boolean requeue;

    private T data;

    private JSONObject attachments;

}

6、消息类:TestEntity

package com.wen.rabbit.model;

import lombok.Data;

/**
 * @author : rjw
 * @date : 2025-07-07
 */
@Data
public class TestEntity {

    private String name;

    private Integer age;

    private String sex;

}

7、MQ客户端:MQClient

package com.wen.rabbit.service;

import com.wen.rabbit.config.RabbitMQConfig;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

/**
 * @author : rjw
 * @date : 2025-07-07
 */
@Service
@Slf4j
public class MQClient {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private RabbitMQConfig rabbitMQConfig;

    public boolean send(String exchange, String routingKey, Object message) {
        try {
            rabbitTemplate.convertAndSend(exchange, routingKey, message);
            return true;
        } catch (AmqpException e) {
            log.error("fail, exchange:{}, routingKey:{}, message:{}, exception:{}",
                    exchange, routingKey, message, e.toString());
            return false;
        }
    }

}

8、事件抽象接口:MqEvent

package com.wen.rabbit.service;

import java.util.List;

/**
 * @author : rjw
 * @date : 2025-07-07
 */
public interface MqEvent<T> {

    /**
     * 获取MQ的路由主键
     * @return
     */
    public String getRoutingKey();

    /**
     * 获取数据
     * @return
     */
    public List<T> getData();

}

9、事件类:MqEventTest

package com.wen.rabbit.service;

import com.wen.rabbit.model.TestEntity;
import lombok.Getter;

import java.util.List;

/**
 * @author : rjw
 * @date : 2025-07-07
 */
@Getter
public class MqEventTest implements MqEvent {

    private String routeKey;

    private final List<TestEntity> data;

    public MqEventTest(String routeKey, List<TestEntity> data) {
        this.routeKey = routeKey;
        this.data = data;
    }

    @Override
    public String getRoutingKey() {
        return this.routeKey;
    }

    @Override
    public List<TestEntity> getData() {
        return this.data;
    }
}

10、发布者:MQPublisher

package com.wen.rabbit.service;

import com.alibaba.fastjson.JSON;
import com.wen.rabbit.config.RabbitMQConfig;
import com.wen.rabbit.model.MQEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author : rjw
 * @date : 2025-07-07
 */
@Component
public class MQPublisher {

    @Autowired
    private MQClient mqClient;

    @Autowired
    private RabbitMQConfig mqConfig;

    public void publish(MqEvent mqEvent) {
        MQEntity<List> mqEntity = new MQEntity<>();
        mqEntity.setTm(System.currentTimeMillis());
        mqEntity.setData(mqEvent.getData());
        mqEntity.setWho("one");
        mqEntity.setRequeue(false);
        mqClient.send(mqConfig.getExchangeRjwTest(), mqEvent.getRoutingKey(), JSON.toJSONBytes(mqEntity));
    }
}

11、监听者(消费者):DataListener

package com.wen.rabbit;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.TypeReference;
import com.rabbitmq.client.Channel;
import com.wen.rabbit.model.MQEntity;
import com.wen.rabbit.model.TestEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @author : rjw
 * @date : 2025-07-07
 */
@Component
@Slf4j
public class DataListener {

    @RabbitListener(queues = {"${spring.rabbitmq.queueRjwTest}"}, concurrency = "1", ackMode = "MANUAL")
    public void dataListenerEvent(Message message, Channel channel) throws IOException {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        String consumerQueue = message.getMessageProperties().getConsumerQueue();

        try {
            byte[] body = message.getBody();
            String jsonBody = new String(body, StandardCharsets.UTF_8);
            MQEntity<List<TestEntity>> mqEntity = JSON.parseObject(jsonBody, new TypeReference<>() {
            });
            log.info("接收到的MQ消息是: {}", mqEntity.toString());
            channel.basicAck(deliveryTag, false);
        } catch (JSONException e) {
            log.error("parse mq msg exception, queue:{}, deliveryTag:{}", consumerQueue, deliveryTag, e);
            channel.basicReject(deliveryTag, false);
        } catch (RuntimeException e) {
            log.error("handle mq msg exception, queue:{}, deliveryTag:{}", consumerQueue, deliveryTag, e);
            channel.basicReject(deliveryTag, false);    //为true会重新放回队列
        }
    }
    
}

12、生产者:DataProducer

package com.wen.rabbit;

import com.alibaba.fastjson.JSON;
import com.wen.rabbit.config.RabbitMQConfig;
import com.wen.rabbit.model.TestEntity;
import com.wen.rabbit.service.MQPublisher;
import com.wen.rabbit.service.MqEventTest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author : rjw
 * @date : 2025-07-07
 */
@Slf4j
@Component
@EnableScheduling
public class DataProducer {

    @Autowired
    private MQPublisher publisher;

    @Autowired
    private RabbitMQConfig mqConfig;

    @Scheduled(cron = "0 0/1 * * * ?")
    public void createDataJob() {
        log.info("生产者生成数据开始-----");
        for (int i = 0; i < 20; i++) {
            TestEntity testEntity = new TestEntity();
            testEntity.setName("Jack" + i);
            testEntity.setAge(20 + i);
            testEntity.setSex(i % 2 == 0 ? "man" : "woman");
            publisher.publish(new MqEventTest(mqConfig.getRouteRjwTest(), List.of(testEntity)));
            log.info("消息数据:{}", JSON.toJSONString(new MqEventTest(mqConfig.getRouteRjwTest(), List.of(testEntity))));
        }
        log.info("生产者生成数据结束=====");
    }

}

注意:本文是使用 SpringBoot 项目为核心进行开发,所使用的依赖和类都如上展示,可以应用于基本业务逻辑。

### 区别与关系 `spring-boot-starter-amqp`、`amqp-client` 和 `spring-amqp` 是在使用 AMQP(Advanced Message Queuing Protocol)协议进行消息传递时常见的三个组件,它们在功能和使用场景上有明确的分工和依赖关系。 `amqp-client` 是 RabbitMQ 官方提供的底层 Java 客户端库,用于与 RabbitMQ 服务器进行通信。它提供了基础的连接、通道、发布和消费消息的 API,适用于直接操作 RabbitMQ 的场景,但需要手动管理连接和资源[^1]。 `spring-amqp` 是 Spring 框架对 AMQP 协议的抽象和封装,提供了一套高层次的 API,简化了与 RabbitMQ 的集成。它基于 `amqp-client`,并提供了诸如 `RabbitTemplate`、消息监听容器等高级功能,使得开发者可以更方便地发送和接收消息[^1]。 `spring-boot-starter-amqp` 是 Spring Boot 提供的一个启动器依赖,集成了 `spring-amqp` 和 `amqp-client`,并提供了自动配置功能。通过简单的配置,即可快速构建基于 RabbitMQ 的消息生产者和消费者,极大地简化了开发流程[^1]。 ### 依赖关系示例 以下是一个典型的 `pom.xml` 配置片段,展示了 `spring-boot-starter-amqp` 如何集成其他两个库: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> ``` 此依赖会自动引入 `spring-amqp` 和 `amqp-client`,无需额外添加。 ### 功能对比 | 组件名称 | 功能描述 | 是否需要手动管理资源 | |------------------------|--------------------------------------------------------------------------|----------------------| | `amqp-client` | RabbitMQ 官方提供的基础客户端库,支持直接与 RabbitMQ 进行通信 | 是 | | `spring-amqp` | SpringAMQP 的封装,提供高层次的 API,简化消息操作 | 否 | | `spring-boot-starter-amqp` | Spring Boot 启动器,集成 `spring-amqp` 和 `amqp-client`,提供自动配置功能 | 否 | ### 使用场景 - **`amqp-client`**:适用于需要精细控制 RabbitMQ 连接和消息传递的场景,适合对 RabbitMQ 有深入了解的开发者。 - **`spring-amqp`**:适用于希望在 Spring 项目中快速集成 RabbitMQ,但不需要 Spring Boot 自动配置功能的场景。 - **`spring-boot-starter-amqp`**:适用于 Spring Boot 项目,希望快速集成 RabbitMQ 并利用自动配置功能简化开发流程的场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值