SpringBoot實(shí)現(xiàn)郵件推送的詳細(xì)代碼
SpringBoot實(shí)現(xiàn)郵件推送
在項(xiàng)目中經(jīng)常會(huì)遇到SpringBoot推送消息的業(yè)務(wù),除了站內(nèi)推送通知,郵件推送也是一種常見的方式,本次小編就帶大家實(shí)現(xiàn)郵件推送。
引入依賴
<!-- spring mail --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <!-- thymeleaf --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
spring-boot-starter-mail
:- 作用:提供了使用Spring Framework的郵件發(fā)送功能的起步依賴。
- 功能:使得在Spring Boot應(yīng)用中可以輕松地配置和使用郵件發(fā)送功能,包括發(fā)送簡(jiǎn)單文本郵件、HTML郵件、附件郵件等。
- 使用:結(jié)合Spring的郵件模塊,你可以方便地在你的應(yīng)用程序中集成郵件發(fā)送功能,無(wú)論是用于發(fā)送通知、驗(yàn)證郵件還是其他目的。
spring-boot-starter-thymeleaf
:- 作用:提供了使用Thymeleaf模板引擎的起步依賴。
- 功能:Thymeleaf是一種流行的Java模板引擎,用于在Web應(yīng)用中創(chuàng)建動(dòng)態(tài)HTML模板。
- 使用:結(jié)合Spring Boot和Thymeleaf,你可以使用Thymeleaf的模板語(yǔ)言來(lái)生成動(dòng)態(tài)內(nèi)容,比如渲染服務(wù)器端數(shù)據(jù)到HTML頁(yè)面上,以便在Web應(yīng)用中更靈活地展示數(shù)據(jù)。
在項(xiàng)目中,使用第二個(gè)依賴再結(jié)合靜態(tài)的html文件就可以實(shí)現(xiàn),將郵件以預(yù)定義模板的形式發(fā)送出去。
在實(shí)際中只需要將對(duì)應(yīng)的值以Map的方式填入到對(duì)應(yīng)字段中即可,別急~接下來(lái)會(huì)帶大家實(shí)現(xiàn)的。
配置
在項(xiàng)目配置中加入如下配置
yml格式如下:
spring: # 郵箱配置 mail: host: smtp.qq.com # 用戶名 替換成你實(shí)際的用戶名 username: test@foxmail.com # 授權(quán)碼 可以去官方申請(qǐng) 不是個(gè)人郵箱密碼 password: xxxxxxxxxx
application.properties文件格式如下:
# 需要開啟 smtp qq郵箱為例 spring.mail.host=smtp.qq.com spring.mail.port=465 # 發(fā)件人的郵箱 spring.mail.username=xxxxx # qq 郵箱的第三方授權(quán)碼 并非個(gè)人密碼 spring.mail.password=xxxx #開啟ssl 否則 503 錯(cuò)誤 但是實(shí)際測(cè)試發(fā)現(xiàn)其實(shí)不加也不會(huì)報(bào)錯(cuò) 但是最好還是加上 spring.mail.properties.mail.smtp.ssl.enable=true
代碼具體實(shí)現(xiàn)
創(chuàng)建郵件實(shí)體封裝類
package com.ican.model.dto; ? import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; ? import java.util.Map; ? /** * 郵箱DTO * @author xiayexiaolu */ @Data @Builder @NoArgsConstructor @AllArgsConstructor @ApiModel(description = "郵箱DTO") public class MailDTO { ? /** * 接收者郵箱號(hào) */ @ApiModelProperty(value = "接收者郵箱號(hào)") private String toEmail; ? /** * 主題 */ @ApiModelProperty(value = "主題") private String subject; ? /** * 內(nèi)容 */ @ApiModelProperty(value = "內(nèi)容") private String content; ? /** * 內(nèi)容信息 */ @ApiModelProperty(value = "內(nèi)容信息") private Map<String, Object> contentMap; ? /** * 郵件模板 */ @ApiModelProperty(value = "郵件模板") private String template; } ?
創(chuàng)建郵件服務(wù)接口并實(shí)現(xiàn)
package com.ican.service; ? import com.ican.model.dto.MailDTO; ? /** * 郵件服務(wù)接口 * * @author xiaoyexiaolu **/ public interface EmailService { ? /** * 發(fā)送簡(jiǎn)單郵件 * * @param mailDTO 郵件信息 */ void sendSimpleMail(MailDTO mailDTO); ? /** * 發(fā)送HTML郵件 * * @param mailDTO 郵件信息 */ void sendHtmlMail(MailDTO mailDTO); } ?
對(duì)接口進(jìn)行實(shí)現(xiàn),下面為模板代碼,可直接使用:
package com.ican.service.impl; ? import com.ican.model.dto.MailDTO; import com.ican.service.EmailService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Service; import org.thymeleaf.TemplateEngine; import org.thymeleaf.context.Context; ? import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; ? /** * 郵件服務(wù)接口實(shí)現(xiàn)類 * * @author xiayexiaolu **/ @Service public class EmailServiceImpl implements EmailService { ? /** * 郵箱號(hào) */ @Value("${spring.mail.username}") private String email; ? @Autowired private JavaMailSender javaMailSender; ? @Autowired private TemplateEngine templateEngine; ? @Override public void sendSimpleMail(MailDTO mailDTO) { SimpleMailMessage simpleMail = new SimpleMailMessage(); simpleMail.setFrom(email); simpleMail.setTo(mailDTO.getToEmail()); simpleMail.setSubject(mailDTO.getSubject()); simpleMail.setText(mailDTO.getContent()); javaMailSender.send(simpleMail); } ? @Override public void sendHtmlMail(MailDTO mailDTO) { try { MimeMessage mimeMessage = javaMailSender.createMimeMessage(); MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage); Context context = new Context(); context.setVariables(mailDTO.getContentMap()); String process = templateEngine.process(mailDTO.getTemplate(), context); mimeMessageHelper.setFrom(email); mimeMessageHelper.setTo(mailDTO.getToEmail()); mimeMessageHelper.setSubject(mailDTO.getSubject()); mimeMessageHelper.setText(process, true); javaMailSender.send(mimeMessage); } catch (MessagingException e) { e.printStackTrace(); } } }
其實(shí)到這里發(fā)送郵件就已經(jīng)能用了,但是如果使用原生發(fā)送郵件的方式可能會(huì)有少許缺點(diǎn)。使用消息隊(duì)列有以下好處
- 異步處理:通過(guò)消息隊(duì)列,你可以將郵件發(fā)送操作異步化,即使發(fā)送郵件的過(guò)程比較耗時(shí),也不會(huì)阻塞主線程,提高了應(yīng)用程序的響應(yīng)速度和吞吐量。
- 解耦:使用消息隊(duì)列可以將郵件發(fā)送操作解耦合,發(fā)送郵件的業(yè)務(wù)邏輯與其他業(yè)務(wù)邏輯相互獨(dú)立。這意味著你可以輕松地更改或擴(kuò)展郵件發(fā)送的實(shí)現(xiàn)方式,而不影響其他業(yè)務(wù)邏輯。
- 負(fù)載均衡:通過(guò)消息隊(duì)列,你可以將郵件發(fā)送請(qǐng)求分發(fā)到多個(gè)郵件發(fā)送服務(wù)節(jié)點(diǎn)上,從而實(shí)現(xiàn)負(fù)載均衡,提高了系統(tǒng)的穩(wěn)定性和可用性。
- 削峰填谷:在高并發(fā)情況下,郵件發(fā)送請(qǐng)求可能會(huì)突然增加,而消息隊(duì)列可以幫助平滑處理這種突發(fā)情況,避免郵件服務(wù)器過(guò)載。
- 失敗處理:使用消息隊(duì)列可以更好地處理郵件發(fā)送失敗的情況。如果郵件發(fā)送失敗,你可以通過(guò)消息隊(duì)列實(shí)現(xiàn)重試機(jī)制或者將失敗的消息重新放回隊(duì)列,以便稍后再次嘗試發(fā)送。
使用消息隊(duì)列實(shí)現(xiàn)郵件發(fā)送
額外引入依賴
<!-- spring amqp --> <dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-spring-boot-starter</artifactId> <version>${saToken.version}</version> </dependency>
這個(gè)依賴會(huì)自動(dòng)地添加所需的 RabbitMQ 客戶端庫(kù),并配置好Spring Boot的AMQP支持。
在配置中配置連接
spring: # rabbitmq配置 rabbitmq: host: localhost port: 5672 username: guest password: guest listener: simple: retry: enabled: true # 重試間隔時(shí)間 initial-interval: 3000 # 最大重試次數(shù) max-attempts: 3
創(chuàng)建郵件消費(fèi)者
package com.ican.consumer; import com.ican.model.dto.MailDTO; import com.ican.service.EmailService; import org.springframework.amqp.core.ExchangeTypes; import org.springframework.amqp.rabbit.annotation.Exchange; import org.springframework.amqp.rabbit.annotation.Queue; import org.springframework.amqp.rabbit.annotation.QueueBinding; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.handler.annotation.Payload; import org.springframework.stereotype.Component; import static com.ican.constant.MqConstant.*; /** * 郵件消費(fèi)者 * @author xiayexiaolu */ @Component public class EmailConsumer { @Autowired private EmailService emailService; @RabbitListener(bindings = { @QueueBinding( value = @Queue(value = EMAIL_SIMPLE_QUEUE, durable = "true", autoDelete = "false"), exchange = @Exchange(value = EMAIL_EXCHANGE, type = ExchangeTypes.TOPIC), key = EMAIL_SIMPLE_KEY )}) public void listenSendSimpleEmail(@Payload MailDTO mail) { emailService.sendSimpleMail(mail); } @RabbitListener(bindings = { @QueueBinding( value = @Queue(value = EMAIL_HTML_QUEUE, durable = "true", autoDelete = "false"), exchange = @Exchange(value = EMAIL_EXCHANGE, type = ExchangeTypes.TOPIC), key = EMAIL_HTML_KEY )}) public void listenSendHtmlEmail(@Payload MailDTO mail) { emailService.sendHtmlMail(mail); } }
@Component
注解表示這是一個(gè) Spring 組件,會(huì)被 Spring 掃描并納入到應(yīng)用程序的上下文中。@Autowired
注解注入了一個(gè)EmailService
對(duì)象,用于實(shí)際發(fā)送郵件的邏輯處理。- 使用了
@RabbitListener
注解標(biāo)注了兩個(gè)方法,分別用于監(jiān)聽兩個(gè)隊(duì)列中的消息。這兩個(gè)方法分別處理發(fā)送簡(jiǎn)單郵件和發(fā)送 HTML 郵件的邏輯。 - 在
@RabbitListener
注解中,通過(guò)@QueueBinding
注解配置了隊(duì)列與交換機(jī)的綁定關(guān)系,指定了隊(duì)列的屬性和交換機(jī)的名稱、類型、路由鍵等信息。 - 在方法參數(shù)中使用
@Payload
注解,指定了消息體的類型為MailDTO
,這樣方法參數(shù)就會(huì)自動(dòng)解析為消息體的內(nèi)容。
具體使用
首先需要?jiǎng)?chuàng)建一個(gè)郵件對(duì)象
MailDTO mailDTO = new MailDTO(); mailDTO.setToEmail("目標(biāo)郵箱"); mailDTO.setSubject("郵件主題"); mailDTO.setTemplate("郵件使用的模板"); //這里需要在之前加入了thymeleaf依賴支持 mailDTO.setContentMap(contentMap); // 這里的contentMap是一個(gè)HashMap 也是最重要的參數(shù),用于將值映射到模板中 具體示例如下圖所示
然后直接使用代碼:
// 發(fā)送HTML郵件 rabbitTemplate.convertAndSend(EMAIL_EXCHANGE, EMAIL_HTML_KEY, mailDTO);
背后的原理
郵件發(fā)送(生產(chǎn)者) :
- 當(dāng)你執(zhí)行
rabbitTemplate.convertAndSend(EMAIL_EXCHANGE, EMAIL_HTML_KEY, mailDTO);
時(shí),實(shí)際上是將mailDTO
對(duì)象發(fā)送到了 RabbitMQ 中的EMAIL_EXCHANGE
交換機(jī),并使用EMAIL_HTML_KEY
路由鍵。 - 這個(gè)過(guò)程是異步的,即發(fā)送操作執(zhí)行后就會(huì)立即返回,而不會(huì)等待郵件真正發(fā)送完成。
- 當(dāng)你執(zhí)行
郵件消費(fèi)者:
- 通過(guò)
@RabbitListener
注解,你的郵件消費(fèi)者監(jiān)聽了名為EMAIL_HTML_QUEUE
的隊(duì)列。 - 當(dāng)有消息到達(dá)隊(duì)列時(shí),
listenSendHtmlEmail
方法會(huì)被調(diào)用,并傳入消息體mailDTO
。 - 在
listenSendHtmlEmail
方法中,調(diào)用了emailService.sendHtmlMail(mail)
方法來(lái)實(shí)際發(fā)送郵件。
- 通過(guò)
消息傳遞:
- RabbitMQ 確保了消息傳遞的可靠性和順序性。當(dāng)你發(fā)送一條消息到交換機(jī)時(shí),RabbitMQ 會(huì)根據(jù)路由規(guī)則將消息路由到對(duì)應(yīng)的隊(duì)列中去。
- 郵件消費(fèi)者監(jiān)聽隊(duì)列,一旦有消息到達(dá)隊(duì)列,就會(huì)立即觸發(fā)消費(fèi)者方法的執(zhí)行,從而實(shí)現(xiàn)郵件發(fā)送的過(guò)程。
總的來(lái)說(shuō),執(zhí)行 rabbitTemplate.convertAndSend(EMAIL_EXCHANGE, EMAIL_HTML_KEY, mailDTO);
之后,程序并不會(huì)自動(dòng)調(diào)用消費(fèi)者中的代碼,而是將消息發(fā)送到 RabbitMQ 中,并觸發(fā)消費(fèi)者的監(jiān)聽。一旦有消息到達(dá)隊(duì)列,消費(fèi)者會(huì)立即執(zhí)行對(duì)應(yīng)的消費(fèi)方法,完成郵件發(fā)送的過(guò)程。
小結(jié)
本文介紹了如何在Spring Boot項(xiàng)目中實(shí)現(xiàn)郵件推送功能。首先,通過(guò)引入相關(guān)依賴,包括spring-boot-starter-mail
和spring-boot-starter-thymeleaf
,使得項(xiàng)目具備了發(fā)送郵件和使用Thymeleaf模板的能力。然后,配置了郵件服務(wù)的連接信息,包括郵箱的主機(jī)、端口、用戶名和授權(quán)碼等。接著,創(chuàng)建了郵件實(shí)體封裝類MailDTO
,定義了郵件的相關(guān)信息。通過(guò)郵件服務(wù)接口EmailService
和其實(shí)現(xiàn)類EmailServiceImpl
,實(shí)現(xiàn)了發(fā)送簡(jiǎn)單郵件和HTML郵件的功能。此外,還介紹了使用消息隊(duì)列來(lái)異步處理郵件發(fā)送的好處,以及如何通過(guò)RabbitMQ實(shí)現(xiàn)郵件發(fā)送的異步處理。最后,通過(guò)具體的代碼示例,展示了如何在項(xiàng)目中使用消息隊(duì)列發(fā)送郵件,并給出了發(fā)送郵件的具體步驟。
以上就是SpringBoot實(shí)現(xiàn)郵件推送的詳細(xì)代碼的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot郵件推送的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
利用java和sqlserver建立簡(jiǎn)易圖書管理系統(tǒng)的完整步驟
圖書館管理系統(tǒng)是圖書館管理工作中不可缺少的部分,它對(duì)于圖書館的管理者和使用者都非常重要,下面這篇文章主要給大家介紹了關(guān)于利用java和sqlserver建立簡(jiǎn)易圖書管理系統(tǒng)的完整步驟,需要的朋友可以參考下2022-06-06JAVA使用隨機(jī)數(shù)實(shí)現(xiàn)概率抽獎(jiǎng)
這篇文章主要為大家詳細(xì)介紹了JAVA使用隨機(jī)數(shù)實(shí)現(xiàn)概率抽獎(jiǎng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11Java 延遲隊(duì)列的常用的實(shí)現(xiàn)方式
這篇文章主要介紹了Java 延遲隊(duì)列的常用的實(shí)現(xiàn)方式,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下2021-04-04mybatis如何對(duì)大量數(shù)據(jù)的游標(biāo)查詢
這篇文章主要介紹了mybatis如何對(duì)大量數(shù)據(jù)的游標(biāo)查詢問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01Java性能優(yōu)化之?dāng)?shù)據(jù)結(jié)構(gòu)實(shí)例代碼
這篇文章主要介紹了Java性能優(yōu)化之?dāng)?shù)據(jù)結(jié)構(gòu)實(shí)例代碼,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01