👨🎓作者:bug菌
✏️博客:CSDN、掘金、infoQ、51CTO等
🎉简介:CSDN博客专家,C站历届博客之星Top50,掘金/InfoQ/51CTO等社区优质创作者,全网合计8w粉+,对一切技术感兴趣,重心偏Java方向;硬核公众号「 猿圈奇妙屋」,欢迎小伙伴们的加入,一起秃头,一起变强。
..
✍️温馨提醒:本文字数:1999字, 阅读完需:约 5 分钟
嗨,家人们,我是bug菌呀,我又来啦。今天我们来聊点什么咧,OK,接着为大家更《springboot零基础入门教学》系列文章吧。希望能帮助更多的初学者们快速入门!
小伙伴们在批阅文章的过程中如果觉得文章对您有一丝丝帮助,还请别吝啬您手里的赞呀,大胆的把文章点亮👍吧,您的点赞三连(收藏⭐+关注👨🎓+留言📃)就是对bug菌我创作道路上最好的鼓励与支持😘。时光不弃🏃🏻♀️,创作不停💕,加油☘️
一、前言🔥
环境说明:Windows10 + Idea2021.3.2 + Jdk1.8 + SpringBoot 2.3.1.RELEASE
先不开始这期的内容,我们先来回顾一下吧,考考大家, 上几篇都讲了些什么知识点呀,不知道大家都还有印象没?如果实在回忆不起,那也没关系,bug菌再集中给大家复盘下,让大家都能系统性的掌握这整块知识点,好吧。
springboot如何整合邮件发送提醒功能?这个业务场景虽然平时开发比较少接触,毕竟一般邮件开发基本都是一些用于什么人员oa、pm、财务等管理系统,但这些早就已经被系统集成过了,一般情况下也不会说拿出来二次开发或者迭代,但是身为开发,多了解一些总归没有坏处,万一那天就排上用场了,说不定你还得回来感谢bug菌我哦。
再者,此次带大家了解加实践,也算是有过开发邮件业务的经验咯,你们说是不是。
如下呢,是上几期的教学大纲,大家可以看一下:
然而,今天是最后一期啦,啊呸呸,不是我要最后一期,而是这块知识点啦,要与大家说再见啦。如果有小伙伴直接中途插入,还请麻烦先去看上几期的内容,要不然贸然跟着学,肯定要吃大亏,去我的专栏《SpringBoot零基础入门》从头开始跟进。
首先,我先给大家整理下上几期所开发实现的代码吧,我尽量把完整代码都粘贴出来,一来方便大家系统性的阅读(cv大法),二来也能有个标准核对自己的代码,如果有运行不起来的,也好有个标准答案可以借鉴,哈哈哈哈哈哈。
二、方法类
如下就是上几期所实现的不同邮件发送方法类,需要的小伙伴自行存取,尽情拿去造吧~
package com.example.demo.component.mail.build;
import com.example.demo.component.mail.model.AccessoryMail;
import com.example.demo.component.mail.model.ImgResMail;
import com.example.demo.component.mail.model.Mail;
import com.example.demo.component.mail.model.ThymeleafMail;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
/**
* @author luoYong
* @version 1.0
* @date 2022/1/18 9:36
*/
@Component
public class SendMailBuild {
@Autowired
private JavaMailSender javaMailSender;
@Autowired
private SpringTemplateEngine templateEngine; //创建模板引擎
@Autowired private UserService userService;
/**
* 发送简单邮件
*/
public void sendSimpleMail(Mail model) {
//构建邮件内容对象
SimpleMailMessage msg = new SimpleMailMessage(); //邮件发送者
msg.setFrom(model.getSendMailAccount()); //邮件接收者
msg.setTo(model.getAcceptMailAccount()); //邮件主题
msg.setSubject(model.getTheme()); //邮件正文
msg.setText(model.getMailText()); //邮件发送时间
msg.setSentDate(model.getSendTime());
javaMailSender.send(msg);
}
/**
* 发送带附件的邮件
*/
public void sendAccessoryMail(AccessoryMail model) throws MessagingException {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper msg = new MimeMessageHelper(mimeMessage, true); //邮件发送者
msg.setFrom(model.getSendMailAccount()); //邮件接收者
msg.setTo(model.getAcceptMailAccount()); //邮件主题
msg.setSubject(model.getTheme()); //邮件正文
msg.setText(model.getMailText()); //邮件发送时间
msg.setSentDate(model.getSendTime()); //添加附件
msg.addAttachment(model.getAttachmentName(), new File(model.getAttachmentPath()));
javaMailSender.send(mimeMessage);
}
/**
* 发送带图片资源的邮件
* 图片资源和附件的区别就在于:图片资源是放在邮件正文中的,就是一打开邮件就能看到图片。
*/
public void sendImgResMail(ImgResMail model) throws MessagingException {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper msg = new MimeMessageHelper(mimeMessage, true); //邮件发送者
msg.setFrom(model.getSendMailAccount()); //邮件接收者
msg.setTo(model.getAcceptMailAccount()); //邮件主题
msg.setSubject(model.getTheme()); //邮件发送时间
msg.setSentDate(model.getSendTime()); //邮件正文
msg.setText(model.getMailText(),true); //添加图片链接
for (int i = 0; i < model.getContentIds().size(); i++) {
msg.addInline(model.getContentIds().get(i), new FileSystemResource(new File(model.getPaths().get(i))));
} javaMailSender.send(mimeMessage);
}
/**
* 配置静态模板 这里使用了Thymeleaf 作为邮件模板
*/
public void sendThymeleafMail(ThymeleafMail model) throws MessagingException {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper msg = new MimeMessageHelper(mimeMessage, true); //邮件发送者
msg.setFrom(model.getSendMailAccount()); //邮件接收者
msg.setTo(model.getAcceptMailAccount()); //邮件主题
msg.setSubject(model.getTheme()); //邮件发送时间
msg.setSentDate(model.getSendTime());
Context context = new Context(); //添加模板数据
model.getVariables().forEach(p -> {
context.setVariable(p.getName(), p.getValue());
}); //指定静态页面模板
String process = templateEngine.process(model.getTemplate(), context);
msg.setText(process, true);
javaMailSender.send(mimeMessage);
}
}
如上是这几期发送邮件功能点的核心,大家有空一定要好好研究,虽然我也有的是参考了网上大佬的教学才自己去进行了尝试,我希望你们也能跟我一样,能把这些方法分别断点研究,看看每一处代码类都是在干一件什么事!
其实邮件发送,由于被springboot集成过后,一切使用就变得超级简单了,你只需要学习SimpleMailMessage 与 MimeMessage 这两邮件创建类是如何工作的,基本就了解到这儿就可以了,毕竟一般业务中也不怎么会接触到这个,了解使用为主,不必深入研究,好吧。
三、vo类
Mail.java
package com.example.demo.component.mail.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.Date;
/**
* 基本邮件参数
*
* @author luoYong
* @version 1.0
* @date 2022/1/18 9:37
*/
@ApiModel(value = "基本邮件参数",description = "基本邮件参数")
public class Mail {
@ApiModelProperty("发件人邮箱账号")
private String sendMailAccount;
@ApiModelProperty("收件人邮箱账号")
private String acceptMailAccount;
@ApiModelProperty("邮件主题")
private String theme;
@ApiModelProperty("邮件内容")
private String mailText;
@ApiModelProperty("发送时间")
private Date sendTime = new Date();
public String getTheme() {
return theme;
}
public void setTheme(String theme) {
this.theme = theme;
}
public String getSendMailAccount() {
return sendMailAccount;
}
public void setSendMailAccount(String sendMailAccount) {
this.sendMailAccount = sendMailAccount;
}
public String getAcceptMailAccount() {
return acceptMailAccount;
}
public void setAcceptMailAccount(String acceptMailAccount) {
this.acceptMailAccount = acceptMailAccount;
}
public Date getSendTime() {
return sendTime;
}
public void setSendTime(Date sendTime) {
this.sendTime = sendTime;
}
public String getMailText() {
return mailText;
}
public void setMailText(String mailText) {
this.mailText = mailText;
}
}
ImgResMail.java
package com.example.demo.component.mail.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
/**
* 发送带图片资源邮件参数
*
* @author luoYong
* @version 1.0
* @date 2022/1/18 10:54
*/
@ApiModel(value = "发送带图片资源邮件参数",description = "发送带图片资源邮件参数")
public class ImgResMail extends Mail {
@ApiModelProperty("对于的图片标记id")
private List<String> contentIds;
@ApiModelProperty("图片地址")
private List<String> paths;
public List<String> getContentIds() {
return contentIds;
}
public void setContentIds(List<String> contentIds) {
this.contentIds = contentIds;
}
public List<String> getPaths() {
return paths;
}
public void setPaths(List<String> paths) {
this.paths = paths;
}
}
AccessoryMail.java
package com.example.demo.component.mail.model;
import io.swagger.annotations.ApiModelProperty;
/**
* 发送带附件的邮件参数
*
* @author luoYong
* @version 1.0
* @date 2022/1/18 10:57
*/
public class AccessoryMail extends Mail {
@ApiModelProperty("附件地址")
private String attachmentPath;
@ApiModelProperty("附件名")
private String attachmentName;
public String getAttachmentPath() {
return attachmentPath;
}
public void setAttachmentPath(String attachmentPath) {
this.attachmentPath = attachmentPath;
}
public String getAttachmentName() {
return attachmentName;
}
public void setAttachmentName(String attachmentName) {
this.attachmentName = attachmentName;
}
}
Variable.java
package com.example.demo.component.mail.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* 静态文件对应的key-value
*
* @author luoYong
* @version 1.0
* @date 2022/1/18 11:25
*/
@ApiModel(value = "静态文件对应的key-value",description = "静态文件对应的key-value")
public class Variable {
@ApiModelProperty("参数名")
private String name;
@ApiModelProperty("值")
private String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
ThymeleafMail.java
package com.example.demo.component.mail.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* 静态文件对应的key-value
*
* @author luoYong
* @version 1.0
* @date 2022/1/18 11:25
*/
@ApiModel(value = "静态文件对应的key-value",description = "静态文件对应的key-value")
public class Variable {
@ApiModelProperty("参数名")
private String name;
@ApiModelProperty("值")
private String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
四、test-case类
至于test-case,可能每个人书写习惯不一样,大家都有自己独特的代码习惯,你们也可以按照自己的风格来写,毕竟主要是为了测试邮件方法,别的倒没啥,测试方法功能点是否正常即可。如下是我的:仅供参考,
package com.example.demo.component.build;
import com.example.demo.component.mail.build.SendMailBuild;
import com.example.demo.component.mail.model.*;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.mail.MessagingException;import java.util.ArrayList;
import java.util.Date;import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class MailTest {
@Autowired
private SendMailBuild sendMailBuild;
/**
* 发送简单邮件
*/
@Test
void sendSimpleMail() {
Mail mailModel = new Mail();
mailModel.setTheme("title:这是一封测试邮件哈!"); // 设置邮件主题
mailModel.setSendMailAccount("luoyong0603@foxmail.com"); // 设置邮箱发送者
mailModel.setAcceptMailAccount("luoyong0603@foxmail.com"); // 设置邮件接收者,可以有多个接收者
mailModel.setSendTime(new Date()); // 设置邮件发送日期
mailModel.setMailText("text:这是测试邮件的正文内容:我是testMail"); // 设置邮件的正文
sendMailBuild.sendSimpleMail(mailModel);
}
/**
* 发送带附件的邮件
*/
@Test
void sendSimpleMailForDoc() throws MessagingException {
AccessoryMail mailModel = new AccessoryMail();
mailModel.setTheme("这是一封测试邮件"); // 设置邮件主题
mailModel.setSendMailAccount("luoyong0603@foxmail.com"); // 设置邮箱发送者
mailModel.setAcceptMailAccount("luoyong0603@foxmail.com"); // 设置邮件接收者,可以有多个接收者
mailModel.setSendTime(new Date()); // 设置邮件发送日期
mailModel.setMailText("这是测试邮件的正文"); // 设置邮件的正文
mailModel.setAttachmentName("2022.png");//附件名
mailModel.setAttachmentPath("C:\\Users\\Administrator\\Desktop\\2022.png");//附件地址
sendMailBuild.sendAccessoryMail(mailModel);
}
/**
* 发送带图片资源的邮件 * 图片资源和附件的区别就在于 图片资源是放在邮件正文中的,就是一打开邮件就能看到图片
*/
@Test
public void sendImgResMail() throws MessagingException {
ImgResMail mailModel = new ImgResMail();
mailModel.setTheme("这是一封测试邮件"); // 设置邮件主题
mailModel.setSendMailAccount("luoyong0603@foxmail.com"); // 设置邮箱发送者
mailModel.setAcceptMailAccount("luoyong0603@foxmail.com"); // 设置邮件接收者,可以有多个接收者
mailModel.setSendTime(new Date()); // 设置邮件发送日期
mailModel.setMailText("<p>hello 大家好,我是一封测试邮件,我包含了两张图片,分别如下</p><p>第一张图片:</p><img src='cid:img1'/><p>第二张图片:</p><img src='cid:img2'/>");
List<String> paths = new ArrayList<>();
paths.add("C:\\Users\\Administrator\\Desktop\\2022.png");
paths.add("C:\\Users\\Administrator\\Desktop\\test.png");
mailModel.setPaths(paths);
List<String> contentIds = new ArrayList<>();
contentIds.add("img1");
contentIds.add("img2");
mailModel.setContentIds(contentIds);
sendMailBuild.sendImgResMail(mailModel);
}
/**
* 配置静态模板 这里使用了Thymeleaf 邮件模板
*/
@Test
public void testSendThymeleafMail() throws MessagingException {
ThymeleafMail mailModel = new ThymeleafMail();
mailModel.setTheme("这是一封测试邮件"); // 设置邮件主题
mailModel.setSendMailAccount("luoyong0603@foxmail.com"); // 设置邮箱发送者
mailModel.setAcceptMailAccount("luoyong0603@foxmail.com"); // 设置邮件接收者,可以有多个接收者
mailModel.setSendTime(new Date()); // 设置邮件发送日期
List<Variable> variables = new ArrayList<>();
Variable variable1 = new Variable();
variable1.setName("school");
variable1.setValue("清华附属小学");
Variable variable2 = new Variable();
variable2.setName("className");
variable2.setValue("六(1)班");
Variable variable3 = new Variable();
variable3.setName("name");
variable3.setValue("小罗");
variables.add(variable1);
variables.add(variable2);
variables.add(variable3);
mailModel.setVariables(variables);
mailModel.setTemplate("mail.html");
sendMailBuild.sendThymeleafMail(mailModel);
}
}
如下是我实现这个功能块的项目结构。
大家也可以像我一样,一个组件就是一个功能点,然后所涉及的model类,单独封装方法一个component中,日后,项目进行维护,后人一看也就明白了,原来这一组件就是干了一件邮件发送等功能点,自己用起来或他人进行调用,一看文件目录便知。
五、静态模板文件
1、mail.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Thymeleaf邮件模板</title>
</head>
<body>
<p>这是一份学生名单:请查收</p>
<table border="1">
<tr>
<td>学校</td>
<td th:text="${school}"></td>
</tr>
<tr>
<td>班级</td>
<td th:text="${className}"></td>
</tr>
<tr>
<td>姓名</td>
<td th:text="${name}"></td>
</tr>
</table>
<div style="color: red;">以上是学生名单!</div>
</body>
</html>
2、user.html
这套模板暂时没用上,这主要是一个循环遍历集合的模板。也供大家参考:
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta content="text/html;charset=UTF-8"/>
</head>
<body>
<h6>Thymeleaf 模板引擎</h6>
<table border="1" bgcolor="#f0ffff">
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>地址</th>
</tr>
</thead>
<!--th:each表示循环遍历,和Vue一样-->
<tbody th:each="user : ${users}">
<tr>
<td th:text="${user.name}"></td>
<td th:text="${user.age}"></td>
<td th:text="${user.sex}"></td>
<td th:text="${user.address}"></td>
</tr>
</tbody>
</table>
</body>
</html>
这里我就有必要向大家介绍一下:html 的 xmlns 属性。
**问:为什么返回的是集合 数组结构的,xmlns属性配了两个链接指向?
****答:**xmlns 属性 是可以配置多个命名空间的,就比如上方,我就配置了两个命名空间。该属性可以放在文档内任何元素的开始标签中,比如:
<div xmlns="http://www.w3.org/1999/Math/MathMl">这是一个div</div>然后该属性的值类似于url,定义了一个命名空间,在进行浏览器访问的时候,就会将此命名空间用于该属性所在元素内的所有内容。
例如,如果需要使用符合 XML 规范的 XHTML 文档,则应该在文档中的 标签中至少使用一个 xmlns 属性,以指定整个文档所使用的主要命名空间:
<html xmlns="http://www.w3.org/1999/xhtml">
一个简单的 XHTML 文档,带有最少的必需标签应该如此,大家请看:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<title>文档标题</title>
</head>
<body>
文档内容......
</body>
</html>
以上是对html 的 xmlns 属性拓展。供大家参考。
接着,如下是我的静态模板目录结构:
如果是要指定返回静态模板类,那你就要配置环境了,比如spring.thymeleaf.xxx 相关属性值了,其中就有一个属性是配置这个templeates文件夹的,这个在我以前的教程中,也专门出了一期,大家想看的也可以去看看,至于为啥我本文没有配置静态路径,却邮件模板能正确找到呢?这个大家可以思考一下,为何能正确找到mail.html.
... ...
说到这儿,就要跟大家说拜拜了,以上就是针对如何代码实现邮件提醒功能的全部内容啦,如果你还卡在途中某个点,但说无妨,bug菌是不会嘲笑你的,只会耐心的对你的疑惑进行全面解答,我为人人,人人才会为我!对吧,没有付出,哪有回报,所以尽情的把问题抛出来把,下下方留言或者加我的交流群,都可。可能就会有小伙伴问了,bug菌你这么倾囊相授,到底图啥呀?图我们回报你啥呀?
如果非要论回报,那就帮我把文章左上角的大拇指点亮吧。如果能一键三连,那bug菌更是喜笑颜开啦,更加充满动力为大家奉献自己的时间,要知道上班时间拿来写文章,是一件多么危险的事。
好啦,咱们就说到这儿,如果有任何问题欢迎评论区批评指正,886 咱们下期见。
六、往期热门推荐
- springboot系列(一):如何创建springboot项目及启动
- springboot系列(二):yaml、properties两配置文件介绍及使用
- springboot系列(三):多环境切换,实例演示
- springboot系列(四):stater入门
- springboot系列(五):史上最最最全springboot常用注解
- springboot系列(六):mysql配置及数据库查询
- springboot系列(七):如何通过mybatis-plus实现接口增删改查
- springboot系列(八):mybatis-plus之条件构造器使用手册
- springboot系列(九):mybatis-plus之如何自定义sql
- springboot系列(十):mybatis之xml映射文件>、<=等特殊符号写法
- springboot系列(十一):实现多数据源配置,开箱即用
- springboot系列(十二):如何实现邮件发送提醒,你一定得会(准备篇)
- springboot系列(十三):如何实现发送普通邮件?你一定得会
- springboot系列(十四):如何实现发送图片、doc文档等附件邮件?你一定得会
- springboot系列(十五):如何实现静态邮件模板发送?你一定得会
- springboot系列(十六):如何实现发送邮件提醒,附完整源码
- springboot系列(十七):集成在线接口文档Swagger2
- springboot系列(十八):如何Windows安装redis?你玩过么
- springboot系列(十九):如何集成redis?不会我教你
- springboot系列(二十):如何通过redis实现手机号验证码功能
- ... ...
文末🔥
如果还想要学习更多,小伙伴们可关注bug菌专门为大家创建的专栏《springboot零基础入门教学》,从无到有,从零到一!希望能帮助到更多小伙伴们。
我是bug菌,一名想走👣出大山改变命运的程序猿。接下来的路还很长,都等待着我们去突破、去挑战。来吧,小伙伴们,我们一起加油!未来皆可期,fighting!
感谢认真读完我博客的铁子萌,在这里呢送给大家一句话,不管你是在职还是在读,绝对终身受用。
时刻警醒自己:
抱怨没有用,一切靠自己;
想要过更好的生活,那就要逼着自己变的更强,生活加油!!!