通過前面的文章,我們學習了 RabbitMQ 的基本使用,及死信隊列和延遲隊列的使用
本章將結合前面的內容,完成一個完整的示例。
相關知識
延遲隊列實現可參考 https://blog.csdn.net/gongm24/article/details/103915040
目標
整合 RabbitMQ 利用延遲隊列的特性實現發送定時郵件
流程如下:
操作步驟
添加依賴
引入 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;
});
}
}