SpringBoot2.0实战 | 第二十章:整合RabbitMQ实现发送定时邮件

相关知识

延迟队列实现可参考 https://blog.csdn.net/gongm24/article/details/103915040

目标

整合 RabbitMQ 利用延迟队列的特性实现发送定时邮件

流程如下:

Created with Raphaël 2.2.0 客户端发送邮件 是否定时 发送定时邮件 延迟邮件队列(EmailDelayQueue) 是否到期 邮件队列(MailQueue) 消费消息 发送即时邮件 yes no yes

操作步骤

添加依赖

引入 Spring Boot Starter 父工程

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.5.RELEASE</version>
</parent>

添加 RabbitMQ 及 Mail 的依赖

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

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

添加后的整体依赖如下

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

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <scope>provided</scope>
    </dependency>

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

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

编码(消费方)

消费方监听队列 EmailQueue,实现发送邮件

配置
spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: admin
    password: admin
    listener:
      type: simple
      simple:
        acknowledge-mode: manual
  mail:
    host: smtp.126.com
    username: [email protected]
    password: hmily52mg@2014
    properties:
      mail:
        smtp:
          auth: true
定义队列
@Configuration
public class MqConfig {

    @Bean
    public Queue emailQueue() {
        return new Queue("EmailQueue",true);
    }
}
监听队列实现邮件发送
@AllArgsConstructor
@Component
public class EmailConsumer {

    private MailProperties properties;
    private JavaMailSender mailSender;

    @RabbitListener(queues = "EmailQueue")
    @RabbitHandler
    public void process(Channel channel, Message message) throws IOException {
        try {
            Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter();
            Email email = (Email) converter.fromMessage(message);
            doSend(email);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            e.printStackTrace();
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
        }
    }

    public void doSend(Email mail) throws Exception {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(properties.getUsername());
        message.setTo(mail.getTo());
        message.setSubject(mail.getSubject());
        message.setText(mail.getContent());
        mailSender.send(message);
    }

}

编码(发送方)

配置
spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: admin
    password: admin
定义队列

定义一个邮件队列,消费端监听该队列,实现邮件异步发送
定义一个延迟邮件队列,该队列中的消息到期则自动转入邮件队列。

@Configuration
public class MqConfig {

    @Bean
    public Queue emailQueue() {
        return new Queue("EmailQueue",true);
    }

    @Bean
    DirectExchange emailExchange() {
        return new DirectExchange("EmailExchange");
    }

    @Bean
    Binding bindingEmailQueue() {
        return BindingBuilder.bind(emailQueue()).to(emailExchange()).with("EmailRouting");
    }

    @Bean
    public Queue emailDelayQueue() {
        Map<String, Object> params = new HashMap<>(2);
        params.put("x-dead-letter-exchange", "EmailExchange");
        params.put("x-dead-letter-routing-key", "EmailRouting");
        return new Queue("EmailDelayQueue",true, false, false, params);
    }

    @Bean
    DirectExchange emailDelayExchange() {
        return new DirectExchange("EmailDelayExchange");
    }

    @Bean
    Binding bindingEmailDelayQueue() {
        return BindingBuilder.bind(emailDelayQueue()).to(emailDelayExchange()).with("EmailDelayRouting");
    }

}
Service 层代码
@AllArgsConstructor
@Service
public class MailService {

    private RabbitTemplate rabbitTemplate;
    // 即时发送
    public void send(String to, String subject, String content) {
        Email mail = new Email();
        mail.setTo(to);
        mail.setSubject(subject);
        mail.setContent(content);
        rabbitTemplate.convertAndSend("EmailExchange", "EmailRouting", mail);
    }
    // 定时发送
    public void send(String to, String subject, String content, LocalDateTime time) {
        Email mail = new Email();
        mail.setTo(to);
        mail.setSubject(subject);
        mail.setContent(content);
        rabbitTemplate.convertAndSend("EmailDelayExchange", "EmailDelayRouting", mail, msg -> {
            Duration duration = Duration.between(LocalDateTime.now(), time);
            msg.getMessageProperties().setExpiration(String.valueOf(duration.toMillis()));
            return msg;
        });
    }

}

源码地址

本章源码 : https://gitee.com/gongm_24/spring-boot-tutorial.git

发布了153 篇原创文章 · 获赞 22 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/gongm24/article/details/103918180