Spring boot搭建郵件服務(wù)的完整步驟
前言:
發(fā)送郵件,肯定是每個(gè)公司都會(huì)有的基本業(yè)務(wù)。很多公司都會(huì)選擇把發(fā)送郵件作為一個(gè)基礎(chǔ)服務(wù),對(duì)外提供接口。直接調(diào)用就可發(fā)郵件了。但是我們都知道發(fā)送郵件耗時(shí)都比較長。那么今天就介紹下使用Spring boot+eventbus來打造一個(gè)簡單郵件服務(wù)
規(guī)劃接口列表
發(fā)送郵件的類型準(zhǔn)備的有三種
- 發(fā)送普通郵件
- 發(fā)送html郵件
- 發(fā)送圖文郵件
還有一個(gè)細(xì)節(jié),如果我們同步的取發(fā)送郵件會(huì)有兩個(gè)問題。
- 接口響應(yīng)時(shí)間比較長
- 遇到并發(fā)的情況,容易導(dǎo)致服務(wù)器壓力過大或者郵箱服務(wù)封ip
所以我們準(zhǔn)備使用隊(duì)列來執(zhí)行發(fā)送郵件的操作??梢越鉀Q這個(gè)問題。隊(duì)列我選用的是Google的eventbus。是一款很輕量的隊(duì)列。直接走的內(nèi)存
準(zhǔn)備工作
首先要在pom.xml中引入 需要使用的包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>23.0</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
- spring-boot-starter-mail :spring-boot提供的發(fā)郵件的maven庫
- guava:google提供的開源庫。里面包含來很多工具
- lombok:可以幫你省去編寫實(shí)體類的工具
引入之后,我們還需要配置發(fā)送郵件所需要的必要配置
在application.properties中配置郵箱
spring.mail.host=smtp.mail.me.com //郵箱發(fā)送服務(wù)器 spring.mail.port=587//服務(wù)器端口 spring.mail.username=xxx6666@icloud.com//發(fā)件人郵箱 spring.mail.password=password//客戶端專用密碼 //如果和我一樣使用的icloud郵箱 還需要下列兩個(gè)配置,別的有的郵箱不需要 spring.mail.properties.mail.smtp.starttls.enable=true spring.mail.properties.mail.smtp.starttls.required=true
做到這里其實(shí)就已經(jīng)完成了,發(fā)郵件所需要的配置了。但是我們是要用隊(duì)列來發(fā)送,所以還需要配置下隊(duì)列
@Configuration
public class AsyncEventBusConfig {
//實(shí)例化bean,采用單例形式注入容器
@Bean
@Scope("singleton")
public AsyncEventBus asyncEventBus(){
//創(chuàng)建線程池對(duì)象
final ThreadPoolExecutor executor=executor();
return new AsyncEventBus(executor);
}
//創(chuàng)建線程池方法
private ThreadPoolExecutor executor(){
return new
ThreadPoolExecutor(2,
2,0L,
TimeUnit.MICROSECONDS,
new LinkedBlockingQueue<>());
}
}
封裝EmailService
準(zhǔn)備好了之后,就可以直接來封裝發(fā)送郵件的業(yè)務(wù)了。之前有提到我們需要三個(gè)接口,同樣的,我們也需要三個(gè)service方法
@Service
public class EmailService {
@Autowired
private JavaMailSender javaMailSender;
/**
* 發(fā)件人。這里發(fā)件人一般是同使用的發(fā)件郵箱一致
*/
@Value("${spring.mail.username}")
private String from;
/**
* 發(fā)送文本郵件
* @param to 收件人郵箱地址
* @param subject 主題
* @param content 內(nèi)容
*/
public void sendTextMail(String to,
String subject,
String content) {
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setTo(to);
simpleMailMessage.setSubject(subject);
simpleMailMessage.setText(content);
simpleMailMessage.setFrom(from);
javaMailSender.send(simpleMailMessage);
}
/**
* 發(fā)送html內(nèi)容的郵件
* @param to 收件人
* @param htmlContent html內(nèi)容
* @param subject 主題
* @throws MessagingException
*/
public void sendHtmlMail(String to,
String htmlContent,
String subject) throws MessagingException {
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(message, true);
messageHelper.setTo(to);
messageHelper.setSubject(subject);
messageHelper.setFrom(from);
messageHelper.setText(htmlContent, true);
javaMailSender.send(message);
}
/**
* 發(fā)送圖文郵件
* @param to 收件人
* @param imgContent 圖文內(nèi)容
* @param subject 主題
* @param rscId 資源id
* @param imgPath 資源路徑
* @throws MessagingException
*/
public void sendImgMail(String to,
String imgContent,
String subject,
String rscId,
String imgPath) throws MessagingException {
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(message, true);
messageHelper.setTo(to);
messageHelper.setSubject(subject);
messageHelper.setFrom(from);
messageHelper.setText(imgContent, true);
messageHelper.addInline(rscId, new File(imgPath));
javaMailSender.send(message);
}
}
隊(duì)列監(jiān)聽
既然封裝好了方法,那么就需要調(diào)用。調(diào)用的方式,其實(shí)就是將接口傳來的數(shù)據(jù)傳到隊(duì)列里。隊(duì)列的消費(fèi)者接收到了消息就將消息拿來調(diào)用發(fā)送郵件的方法
我們首先創(chuàng)建一個(gè)消費(fèi)類,用來接受消息,處理消息。
@Service
public class EventBusListener {
/**
* 引入bean
*/
@Autowired
private AsyncEventBus asyncEventBus;
@Autowired
private EmailService emailService;
/**
* 注冊(cè)服務(wù)類
*/
@PostConstruct
public void init(){
asyncEventBus.register(this);
}
/**
* 線程安全,消費(fèi) 文本消息
* @param textEmailDTO
*/
@AllowConcurrentEvents
@Subscribe
public void sendTextMail(TextEmailDTO textEmailDTO){
emailService.sendTextMail(
textEmailDTO.getTo(),
textEmailDTO.getSubject(),
textEmailDTO.getContent()
);
}
/**
* 線程安全 消費(fèi) html消息
* @param htmlEmailDTO
*/
@AllowConcurrentEvents
@Subscribe
public void sendHtmlMail(HtmlEmailDTO htmlEmailDTO){
try {
emailService.sendHtmlMail(
htmlEmailDTO.getTo(),
htmlEmailDTO.getHtmlContent(),
htmlEmailDTO.getSubject()
);
} catch (MessagingException e) {
// nothing to do
}
}
/**
* 線程安全 消費(fèi) 圖文消息
* @param imgEmailDTO
*/
@AllowConcurrentEvents
@Subscribe
public void sendImgMail(ImgEmailDTO imgEmailDTO){
try {
emailService.sendImgMail(
imgEmailDTO.getTo(),
imgEmailDTO.getImgContent(),
imgEmailDTO.getSubject(),
imgEmailDTO.getRscId(),
imgEmailDTO.getImgPath()
);
} catch (MessagingException e) {
// nothing to do
}
}
}
其實(shí)eventbus拋消息都是使用的post方法來拋消息。走到不同的方法里面是利用了類的多態(tài),拋入不同的實(shí)體類就可以進(jìn)行區(qū)分了。走進(jìn)了不同的方法,就調(diào)用相應(yīng)Service方法。
控制器與測試
控制器部分,沒什么好說的,我就貼出圖文的代碼。其余代碼可以在我的github上面看
先看眼實(shí)體類
@Data
public class ImgEmailDTO implements Serializable {
public ImgEmailDTO() {
}
/**
* 圖片路徑
*/
private String imgPath;
/**
* 資源id
*/
private String rscId;
/**
* 主題
*/
private String subject;
/**
* 圖片正文(同樣可以使用html)
*/
private String imgContent;
/**
* 收件人
*/
private String to;
}
/**
* 發(fā)送圖文郵件
* @param request
* @return
*/
@RequestMapping(value = "/sendImgMail", method = RequestMethod.POST)
public Result<Integer> sendImgMail(@RequestBody Request<ImgEmailDTO> request) {
Result<Integer> result = Result.create();
ImgEmailDTO imgEmailDTO=request.getData();
StringBuilder sb=new StringBuilder();
sb.append(imgEmailDTO.getImgContent());
//cid:資源id。在spring中會(huì)自動(dòng)綁定
sb.append("<img src=\'cid:").append(imgEmailDTO.getRscId()).append("\'></img>");
imgEmailDTO.setImgContent(sb.toString());
asyncEventBus.post(imgEmailDTO);
return result.success(1);
}
圖文要稍微特殊一點(diǎn),需要拼接下正文內(nèi)容。然后將實(shí)體類中的content替換。最后將實(shí)體類拋入隊(duì)列。直接返回接口請(qǐng)求。隊(duì)列那邊就會(huì)排著隊(duì)搞定所有的郵件
下面來做個(gè)測試

請(qǐng)求很迅速的返回了結(jié)果
然后去郵箱中查看結(jié)果

好了今天對(duì)郵件服務(wù)的介紹就寫到這里。知識(shí)點(diǎn)并不深?yuàn)W,主要介紹一個(gè)思路。如有不對(duì)的地方,請(qǐng)大神指出。謝謝
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
- 詳解Spring Boot Admin監(jiān)控服務(wù)上下線郵件通知
- Spring Boot實(shí)現(xiàn)郵件注冊(cè)功能示例代碼
- Spring Boot實(shí)戰(zhàn)之發(fā)送郵件示例代碼
- Spring Boot中利用JavaMailSender發(fā)送郵件的方法示例(附源碼)
- Spring Boot實(shí)現(xiàn)郵件服務(wù)(附:常見郵箱的配置)
- Spring Boot整合郵件發(fā)送與注意事項(xiàng)
- Spring Boot實(shí)現(xiàn)郵件發(fā)送功能
- Spring Boot發(fā)送郵件詳解
- SpringBoot中發(fā)送QQ郵件功能的實(shí)現(xiàn)代碼
- SpringBoot使用FreeMarker模板發(fā)送郵件
相關(guān)文章
springboot中使用Hibernate-Validation校驗(yàn)參數(shù)詳解
這篇文章主要為大家介紹了springboot中使用Hibernate-Validation校驗(yàn)參數(shù)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
Java之BigDecimal實(shí)現(xiàn)詳解
這篇文章主要介紹了Java之BigDecimal實(shí)現(xiàn)詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
解析Java的InputStream類并借助其讀取ppt文件
這篇文章主要介紹了Java的InputStream類并借助其讀取ppt文件,講到了InputStream類中一些常用的方法的問題,需要的朋友可以參考下2015-11-11
微信企業(yè)號(hào) 根據(jù)錯(cuò)誤碼返回錯(cuò)誤信息類封裝
這篇文章主要介紹了微信企業(yè)號(hào) 根據(jù)錯(cuò)誤碼返回錯(cuò)誤信息類封裝的相關(guān)資料,需要的朋友可以參考下2016-10-10
jbuilder2006連接sqlserver2000的方法
xp jbuiler2006 連接SQL SERVER2000的問題2008-10-10
SpringBoot中的多RabbitMQ數(shù)據(jù)源配置實(shí)現(xiàn)
本篇博客將介紹如何在 Spring Boot 中配置和管理多個(gè) RabbitMQ 數(shù)據(jù)源,以滿足不同的應(yīng)用需求,具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09
Java中jdk1.8和jdk17相互切換實(shí)戰(zhàn)步驟
之前做Java項(xiàng)目時(shí)一直用的是jdk1.8,現(xiàn)在想下載另一個(gè)jdk版本17,并且在之后的使用中可以進(jìn)行相互切換,下面這篇文章主要給大家介紹了關(guān)于Java中jdk1.8和jdk17相互切換的相關(guān)資料,需要的朋友可以參考下2023-05-05
Java Lambda表達(dá)式原理及多線程實(shí)現(xiàn)
這篇文章主要介紹了Java Lambda表達(dá)式原理及多線程實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
Spring中ContextLoaderListener監(jiān)聽詳解
這篇文章主要介紹了Spring中ContextLoaderListener監(jiān)聽詳解,SpringMVC啟動(dòng)時(shí)會(huì)啟動(dòng)WebApplicationContext類型的容器,并且會(huì)調(diào)用之前分析的refresh方法,需要的朋友可以參考下2024-01-01

