SpringBoot2.0實戰 | 第二十章:整合RabbitMQ實現定時郵件發送

通過前面的文章,我們學習了 RabbitMQ 的基本使用,及死信隊列和延遲隊列的使用

本章將結合前面的內容,完成一個完整的示例。

相關知識

延遲隊列實現可參考 https://blog.csdn.net/gongm24/article/details/103915040

目標

整合 RabbitMQ 利用延遲隊列的特性實現發送定時郵件

流程如下:

Created with Raphaël 2.2.0客戶端發送郵件是否定時發送定時郵件延遲郵件隊列(EmailDelayQueue)是否到期郵件隊列(MailQueue)消費消息發送即時郵件yesnoyes

操作步驟

添加依賴

引入 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章