尚融宝——整合RabbitMQ——实现短信通知

一、整合RabbitMQ

创建微服务:

添加依赖:

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

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

配置文件:

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest

 创建配置类:

 DeadLetterMqConfig配置类:

/**
 * 这是一个 Spring Boot 应用程序的 Java 配置类,用于配置 RabbitMQ 的死信队列(Dead Letter Queue)
 */
@Configuration
public class DeadLetterMqConfig {
    // 交换机名称
    public static final String exchange_dead = "exchange.dead";
    // 路由键
    public static final String routing_dead_1 = "routing.dead.1";
    public static final String routing_dead_2 = "routing.dead.2";
    // 队列名称
    public static final String queue_dead_1 = "queue.dead.1";
    public static final String queue_dead_2 = "queue.dead.2";

    /**
     * 其他队列可以在RabbitListener上面做绑定
     * 用于创建交换机
     * @return
     */
    @Bean
    public DirectExchange exchange() {

        return new DirectExchange(exchange_dead, true, false, null);
    }

    /**
     * 定义了一个队列 queue1(),并设置了它的属性
     * @return
     */
    @Bean
    public Queue queue1() {
        Map<String, Object> arguments = new HashMap<>();
        // x-dead-letter-exchange 和 x-dead-letter-routing-key,用于指定死信队列的交换机和路由键
        arguments.put("x-dead-letter-exchange", exchange_dead);
        arguments.put("x-dead-letter-routing-key", routing_dead_2);
        // 队列名称、是否持久化、是否是独占队列、是否自动删除
        return new Queue(queue_dead_1, true, false, false, arguments);
    }

    /**
     * 定义了一个 Binding Bean
     * @return
     */
    @Bean
    public Binding binding() {
        // 将 queue1() 和 exchange() 绑定在一起,使用了 routing_dead_1 路由键
        return BindingBuilder.bind(queue1()).to(exchange()).with(routing_dead_1);
    }

    /**
     * 定义了另一个队列 queue2()
     * @return
     */
    @Bean
    public Queue queue2() {
        // 只设置了队列名称和是否持久化
        return new Queue(queue_dead_2, true, false, false, null);
    }

    /**
     * 定义了一个死信绑定
     * @return
     */
    @Bean
    public Binding deadBinding() {
        // 将 queue2() 和 exchange() 绑定在一起,使用了 routing_dead_2 路由键
        return BindingBuilder.bind(queue2()).to(exchange()).with(routing_dead_2);
    }
}

MQConfig 配置类:

/**
 * 定义了一个名为messageConverter的bean,
 * 它是一个消息转换器,用于将消息对象转换为JSON格式的字符串或将JSON格式的字符串转换为消息对象。
 * 这里使用了Jackson库提供的Jackson2JsonMessageConverter类来实现转换功能。
 */
@Configuration
public class MQConfig {

    @Bean
    public MessageConverter messageConverter(){
        //json字符串转换器,用于将消息在JSON和Java对象之间进行转换
        return new Jackson2JsonMessageConverter();
    }
}

 MQConfirm 配置类:

/**
 * 该类实现了RabbitTemplate.ConfirmCallback和RabbitTemplate.ReturnCallback接口,
 * 分别用于消息发送确认和投递确认的回调处理
 */
@Component
public class MQConfirm implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnCallback {

    @Autowired
    RabbitTemplate rabbitTemplate;

    /**
     * @PostConstruct 表示该方法会在Bean初始化之后自动调用。
     * 在该方法中,rabbitTemplate(RabbitMQ的模板类)的确认回调和返回回调都被设置为当前对象(this)。
     */
    @PostConstruct
    public void init(){
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnCallback(this);
    }

    /**
     * confirm()方法是发送确认回调方法,
     * 当消息发送成功或失败时都会执行该方法,并传入相关的参数,
     * 可以在方法中根据返回的ack参数判断消息是否发送成功。
     * @param correlationData
     * @param ack
     * @param cause
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        System.out.println("发送确认,不管发送成功或者失败都会执行");

    }

    /**
     * returnedMessage()方法是投递确认回调方法,
     * 当消息投递失败时会执行该方法,并传入相关的参数,
     * 可以在方法中处理投递失败的情况。
     * @param message
     * @param replyCode
     * @param replyText
     * @param exchange
     * @param routingKey
     */
    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        System.out.println("投递确认,只有投递失败时才会回调");
    }
}

service层:

public interface MqService {

    void sendMessage(String exchange,String routing,Object o);

}
@Service
public class MqServiceImpl implements MqService {

    @Autowired
    RabbitTemplate rabbitTemplate;

    /**
     * 调用者只需要提供交换机、路由和消息即可实现消息的发送。
     * @param exchange
     * @param routing
     * @param o
     */
    @Override
    public void sendMessage(String exchange, String routing, Object o) {
        // 发送的消息(o)转换并发送到指定的交换机和路由上
        rabbitTemplate.convertAndSend(exchange,routing,o);
    }
}

在service-sms微服务中进行RabbitMQ操作:

添加依赖:

        <dependency>
            <groupId>com.atguigu</groupId>
            <artifactId>rabbit-mq</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

添加配置文件:

#spring
  rabbitmq:
    # 发送消息时确认类型为简单模式,即只确认消息是否已经到达交换机
    publisher-confirm-type: simple
    # 设置消息发送失败时,消息会被退回到生产者(publisher)那里,以便后续处理
    publisher-returns: true
    host: localhost
    port: 5672
    username: guest
    password: guest

添加监听器:

 SmsReceiver 消息监听器:

@Component
public class SmsReceiver {

    @Autowired
    SmsService smsService;

    /**
     * 该方法是一个RabbitMQ消息队列的消费者。
     * 该方法监听名为"recharge.routing"的路由键。
     * @param channel
     * @param message
     * @param smsDTO
     * @throws IOException
     */
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = "recharge.exchange",durable = "true"),  //  声明交换机名称和持久化
            key = {"recharge.routing"},
            value = @Queue(value = "recharge.queue",durable = "true") //  声明队列名称和持久化
    ))
    public void a(Channel channel, Message message, SmsDTO smsDTO) throws IOException {
        byte[] body = message.getBody(); // 获取消息体
        String jsonStr = new String(body); // 将消息体转成字符串格式
        // int i = 1/0;
        System.out.println(jsonStr);
        System.out.println("消费监听");

        // 发短信
        smsService.sendRechargeMessage();

        // 提交消息:手动确认消息已经被消费,并提交确认信号给RabbitMQ服务器
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);

        // 回滚消息:回滚或拒绝消息,放回队列等待重新消费
        // channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);
    }
}

 SmsDeadReceiver 监听器:

/**
 * 它包含了两个方法a和b,
 * 分别监听名为"queue.dead.1"和"queue.dead.2"的RabbitMQ队列。
 * 当有消息进入队列时,这两个方法将被调用。
 */
@Component
public class SmsDeadReceiver {

    /**
     * 声明监听名为"queue.dead.1"的队列
     * @param channel 用于与RabbitMQ通信
     * @param message 表示收到的消息
     * @param o 可选的,通常用于传递附加信息
     * @throws IOException
     */
    @RabbitListener(queues = "queue.dead.1")
    public void a(Channel channel, Message message, Object o) throws IOException {
        byte[] body = message.getBody(); //  获取消息的body
        String jsonStr = new String(body);  //  将body转换为String类型

        // 回滚消息后进入死信队列:第二个表示是否重新投递,第三个表示是否将消息投递到当前消费者之前的所有消费者中
        channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);
    }

    /**
     * 声明监听名为"queue.dead.2"的队列
     * @param channel 用于与RabbitMQ通信
     * @param message 表示收到的消息
     * @param o 可选的,通常用于传递附加信息
     * @throws IOException
     */
    @RabbitListener(queues = "queue.dead.2")
    public void b(Channel channel, Message message, Object o) throws IOException {
        byte[] body = message.getBody();
        String jsonStr = new String(body);

        // 回滚消息:第二个表示是否将确认应用于多个消息
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值