基于 Spring Boot 与 RabbitMQ 的邮件发送:确保 100%消息成功投递

RabbitMQ 犹如一位坚定的卫士,确保了邮件发送任务的可靠排队和精细处理;而 Spring Bo
首页 新闻资讯 行业资讯 基于 Spring Boot 与 RabbitMQ 的邮件发送:确保 100%消息成功投递

在当今的企业级应用开发中,邮件发送是一个常见且重要的功能需求。为了确保邮件能够稳定、高效且 100%成功投递,我们可以结合 Spring Boot 和 RabbitMQ 来实现这一目标。

技术选型与框架介绍

在构建邮件发送系统时,我们精心挑选了 Spring Boot 和 RabbitMQ 这两个强大的技术框架,并充分利用它们各自的优势来实现高效、可靠的邮件投递功能。

Spring Boot 作为一款出色的快速开发框架,为我们提供了诸多便利。它基于 Spring 框架,但极大地简化了项目的配置和部署流程。凭借其内置的自动配置机制,开发者无需繁琐地处理各种基础配置,能够迅速搭建起项目的基本架构。同时,Spring Boot 对各种主流技术和组件的良好集成性,使得我们能够轻松引入所需的依赖,快速构建功能丰富的应用。

RabbitMQ 则是一款卓越的消息代理和队列服务器,在分布式系统的消息传递中发挥着关键作用。其基于先进的消息队列机制,能够有效地应对高并发场景下的消息处理需求。通过将邮件发送任务转化为消息并放入队列中,RabbitMQ 确保了任务的有序处理和可靠传递,即使在系统面临高负载或出现故障的情况下,也能保证邮件发送不丢失、不重复,从而极大地提高了邮件投递的成功率和稳定性。

将 Spring Boot 和 RabbitMQ 相结合,能够充分发挥两者的优势。Spring Boot 提供了便捷的开发环境和高效的应用架构,而 RabbitMQ 则为邮件发送任务提供了可靠的排队和处理机制,共同保障了邮件发送的高效性和 100%投递成功率。

项目依赖配置(pom.xml)

<?xml version="1.0"encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.10</version><relativePath/><!-- lookup parent from repository --></parent><groupId>com.icoderoad</groupId><artifactId>mail-sender</artifactId><version>0.0.1-SNAPSHOT</version><name>MailSender</name><description>基于 Spring Boot 和 RabbitMQ 的邮件发送项目</description><properties><java.version>11</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency><dependency><groupId>org.springframework.amqp</groupId><artifactId>spring-rabbit</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

YAML 属性文件配置(application.yml)

spring:
  mail:
    host: smtp.example.com# 替换为您的 SMTP 服务器地址port:587# 端口username: your_email@example.com# 发件人邮箱password: your_password# 邮箱密码properties:
      mail.smtp.auth:truemail.smtp.starttls.enable:truerabbitmq:
  host: localhost# RabbitMQ 服务器地址port:5672# 端口username: guest
  password: guest

后端代码实现

邮件发送服务类(MailService.java)

importlombok.RequiredArgsConstructor;importorg.apache.commons.logging.Log;importorg.apache.commons.logging.LogFactory;importorg.springframework.amqp.rabbit.core.RabbitTemplate;importorg.springframework.mail.MailException;importorg.springframework.mail.SimpleMailMessage;importorg.springframework.mail.javamail.JavaMailSender;importorg.springframework.scheduling.annotation.EnableScheduling;importorg.springframework.scheduling.annotation.Scheduled;importorg.springframework.stereotype.Service;importjava.util.concurrent.ConcurrentHashMap;@EnableScheduling@Service@RequiredArgsConstructorpublicclass MailService {

    private final JavaMailSender mailSender;private final RabbitTemplate rabbitTemplate;private static finalintMAX_RETRY=3;// 最大重试次数private static final Log LOGGER=LogFactory.getLog(MailService.class);private ConcurrentHashMap<String,Integer>retryMap=new ConcurrentHashMap<>();publicbooleansendMail(Stringto,String subject,String content){
        SimpleMailMessage message=new SimpleMailMessage();message.setTo(to);message.setSubject(subject);message.setText(content);intretryCount=0;booleansentSuccessfully=false;Stringkey=to+"_"+subject;while(retryCount<MAX_RETRY&&!sentSuccessfully){
            try {
                mailSender.send(message);sentSuccessfully=true;retryMap.remove(key);} catch(MailException e){
                retryCount++;LOGGER.error("发送邮件失败,重试次数: "+retryCount+",收件人: "+to+",主题: "+subject,e);retryMap.put(key,retryCount);}
        }if(!sentSuccessfully){
            LOGGER.error("邮件发送最终失败,收件人: "+to+",主题: "+subject);}returnsentSuccessfully;}@Scheduled(fixedDelay=60000)// 每分钟执行一次publicvoid retryFailedMails(){for(Stringkey: retryMap.keySet()){
            String[]parts=key.split("_");Stringto=parts[0];String subject=parts[1];SimpleMailMessage message=new SimpleMailMessage();message.setTo(to);message.setSubject(subject);intretryCount=retryMap.get(key);booleansentSuccessfully=false;while(retryCount<MAX_RETRY&&!sentSuccessfully){
                try {
                    mailSender.send(message);sentSuccessfully=true;retryMap.remove(key);} catch(MailException e){
                    retryCount++;if(!sentSuccessfully){
                        rabbitTemplate.convertAndSend("retryQueue",key);LOGGER.error("重试邮件发送失败,已发送到队列,收件人: "+to+",主题: "+subject);}
                }
            }if(!sentSuccessfully){
                LOGGER.error("重试邮件发送最终失败,收件人: "+to+",主题: "+subject);}
        }
    }
}

要合理设置最大重试次数,避免过度重试导致资源浪费。同时,在重试间隔上也需要根据实际情况进行合理的设计,以平衡成功率和性能。还需要对重试过程中的异常情况进行更详细的记录和监控,将重试仍不成功的邮件发送信息发送到队列,方便后续进一步处理,提高了系统的灵活性和容错性。

RabbitMQ 配置类(RabbitMQConfig.java)

importorg.springframework.amqp.core.Queue;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;@Configurationpublicclass RabbitMQConfig {@BeanpublicQueue mailQueue(){returnnew Queue("mail_queue");}
}

RabbitMQ 消费者(MailConsumer.java)

importlombok.RequiredArgsConstructor;importorg.springframework.amqp.rabbit.annotation.RabbitListener;importorg.springframework.stereotype.Component;@Component@RequiredArgsConstructorpublicclass MailConsumer {

    private final MailService mailService;@RabbitListener(queues="mail_queue")publicvoid consumeMailMessage(String message){// 解析消息,提取收件人、主题和内容等信息String[]parts=message.split(";");Stringto=parts[0];String subject=parts[1];String content=parts[2];mailService.sendMail(to,subject,content);}
}

控制器类(MailController.java)

importorg.springframework.amqp.rabbit.core.RabbitTemplate;importorg.springframework.web.bind.annotation.PostMapping;importorg.springframework.web.bind.annotation.RequestBody;importorg.springframework.web.bind.annotation.RestController;@RestControllerpublicclass MailController {

    private final RabbitTemplate rabbitTemplate;publicMailController(RabbitTemplate rabbitTemplate){
        this.rabbitTemplate=rabbitTemplate;}@PostMapping("/sendMail")publicString sendMail(@RequestBodyMailRequest request){// 将邮件信息转换为字符串,发送到 RabbitMQ 队列String message=request.getTo()+";"+request.getSubject()+";"+request.getContent();// 发送到队列rabbitTemplate.convertAndSend("mail_queue",message);return"邮件发送请求已提交";}
}

前端页面实现

使用 Thymeleaf 模板和 JavaScript 实现前端页面:

<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><head><metacharset="UTF-8"><title>邮件发送</title><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script></head><body><h2>邮件发送</h2><form th:action="@{/sendMail}"method="post"><labelfor="to">收件人:</label><inputtype="text"id="to"name="to"><br><labelfor="subject">主题:</label><inputtype="text"id="subject"name="subject"><br><labelfor="content">内容:</label><textarea id="content"name="content"></textarea><br><buttontype="submit">发送</button></form><divid="result"></div><script>$(document).ready(function(){
            $("form").submit(function(event){
                event.preventDefault();varto=$("#to").val();var subject=$("#subject").val();var content=$("#content").val();$.ajax({
                    url: $(this).attr("action"),type:"POST",data: JSON.stringify({"to":to,"subject": subject,"content": content
                    }),contentType:"application/json",success:function(response){
                        $("#result").text(response);},error:function(){
                        $("#result").text("发送失败");}
                });});});</script></body></html>

通过以上精心设计的架构和精妙绝伦的代码实现,我们成功地借助 Spring Boot 和 RabbitMQ 的强大力量,构建出一个能够确保 100%消息成功投递的邮件发送系统。在此过程中,RabbitMQ 犹如一位坚定的卫士,确保了邮件发送任务的可靠排队和精细处理;而 Spring Boot 则宛如一位智慧的导师,提供了便捷的开发环境和丰富多样的功能支持。

44    2024-08-12 12:17:03    Spring RabbitMQ 系统