注:实践内容参考人民邮电出版社的教程《 Spring Boot企业级开发教程》作者:黑马程序员,上传本文仅以实践过程以供大家共同学习解决问题,如有侵权不当行为,请告知后,我会更正或删除。
这里使用Spring Boot框架,结合使得异步任务调用的方式来演示项目向新注册用户发送短信验证码的场景需求,进一步说明无返回值的异步任务调用。
1.使用Sping Initializr创建Spring Boot项目,选择Web依赖(Spring Boot整合 了异步任务,只需在项目中引入Web模块,然后完成项目创建。如图:
2.编写异步调用方法
在com.itheima创建service的包,并创建一个业务实现类MyAsyncService,在该类中模拟编写用户短信验证码发送的方法,内容如下:
@Service
public class MyAsyncService {
/**
* 模拟无返回值的异步任务处理
*/
@Async //@Async 注解标明下面的方法为异步方法
public void sendSMS() throws Exception {//sendSMS()模拟用户短信验证码发送功能
System.out.println("调用短信验证码业务方法...");
Long startTime = System.currentTimeMillis();
//System.currentTimeMillis()在java中是最常用的获取系统时间的方法,它返回的是1970年1月1日0点到现在经过的毫秒数
Thread.sleep(5000);//是将当前线程休眠5秒,用来模拟业务调用处理的时间
Long endTime = System.currentTimeMillis();//获取当前系统时间
System.out.println("短信业务执行完成耗时:" + (endTime - startTime));//计算业务处理耗时
}
}
3.开启基于注解的异步任务支持
上述业务实现类,使用了@Async注解标记了异步方法,还需要使用@EnableAsync注解开启基于注解的异步任务支持。如图,这里添加到项目启动类上。
4.编写控制层业务调用方法
在com.itheima下创建包controller,在该包下创建一个异步方法调用的实现类MyAsyncController,在该类模拟用户短信验证码发送的处理方法。内容如下:
@RestController
public class MyAsyncController {
@Autowired
private MyAsyncService myAsyncService;
@GetMapping("/sendSMS")//设置请求访问路径为"/sendSMS"
public String sendSMS() throws Exception {
Long startTime = System.currentTimeMillis();//获取业务处理开始时当前系统时间
myAsyncService.sendSMS();//调用业务实现对象的sendSMS()模拟短信发送业务
Long endTime = System.currentTimeMillis();//获取业务处理结束时的当前系统时间
System.out.println("主流程耗时: "+(endTime-startTime));//计算业务耗时
return "success";
}
}
5.运行项目启动类,浏览器两次访问 :http://localhost:8080/sendSMS,效果 如图:
这里演示一个程序中需要调用两个业务方法对相关业务数据统计分析,并将统计结果汇总,进一步说明有返回值 的异步任务调用。
1.编写异步调用方法
在之前创建 的MAsyncService异步任务处理类中,添加两个模拟有返回值的异步任务业务处理方法,代码如下:
/**
* 模拟有返回值的异步任务处理
*/
@Async //标明下面的方法为异步方法
public Future processA() throws Exception {
System.out.println("开始分析并统计业务A数据...");
Long startTime = System.currentTimeMillis();
Thread.sleep(4000);//是将当前线程休眠4秒,用来模拟统计业务A数据的时间
// 模拟定义一个假的统计结果
int count=123456;
Long endTime = System.currentTimeMillis();
System.out.println("业务A数据统计耗时:" + (endTime - startTime));
return new AsyncResult(count);//封装返回的结果数据
}
@Async //标明下面的方法为异步方法
public Future processB() throws Exception {
System.out.println("开始分析并统计业务B数据...");
Long startTime = System.currentTimeMillis();
Thread.sleep(5000);//是将当前线程休眠4秒,用来模拟统计业务B数据的时间
// 模拟定义一个假的统计结果
int count=654321;
Long endTime = System.currentTimeMillis();
System.out.println("业务B数据统计耗时:" + (endTime - startTime));
return new AsyncResult(count);
}
2.编写控制层业务调用方法
在之前创建 的MyAsyncController异步任务处理 类中,编 写业务数据分析统计的请求处理方法.代码如下:
@GetMapping("/statistics")
public String statistics() throws Exception {
Long startTime = System.currentTimeMillis();
Future futureA = myAsyncService.processA();
Future futureB = myAsyncService.processB();
int total = futureA.get() + futureB.get();
System.out.println("异步任务数据统计汇总结果: "+total);
Long endTime = System.currentTimeMillis();
System.out.println("主流程耗时: "+(endTime-startTime));
return "success";
}
3.运行项目启动类,浏览器访问:http://localhost:8080//statistics,
这里使用Spring Boot框架整合一个简单的定时任务案例演示对定时任务的使用。
1.编写定时任务业务处理方法
在项目的com.itheima.service包下新建一个定时任务管理的业务处理类ScheduledTaskService,并在该类中编写对应的定时任务处理方法,内容如下:
package com.itheima.service;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Classname ScheduledTaskService
*/
@Service
public class ScheduledTaskService {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private Integer count1 = 1;
private Integer count2 = 1;
private Integer count3 = 1;
@Scheduled(fixedRate = 60000)//配置@Scheduled注解fixedRate属性的定时方法会项目启动后立即执行一次
public void scheduledTaskImmediately() {
System.out.println(String.format("fixedRate第%s次执行,当前时间为:%s", count1++, dateFormat.format(new Date())));
}
@Scheduled(fixedDelay = 60000)//配置@Scheduled注解fixedDelay属性的定时方法会项目启动后立即执行一次
public void scheduledTaskAfterSleep() throws InterruptedException {
System.out.println(String.format("fixedDelay第%s次执行,当前时间为:%s", count2++, dateFormat.format(new Date())));
Thread.sleep(10000);//隔10秒后重复执行一次.
}
@Scheduled(cron = "0 * * * * *")////配置@Scheduled注解cron = "0 * * * * *"属性的定时方法会在整数分钟时间点立即执行一次
public void scheduledTaskCron(){
System.out.println(String.format("cron第%s次执行,当前时间为:%s",count3++, dateFormat.format(new Date())));
}
}
2.在项目启动类上添加基于注解的定时任务支持:@EnableScheduling
从执行效果可以看出,fixedRate = 60000和fixedDelay = 60000,每隔一分钟会执行一次.其中fixedDelay属性对应的方法有休眠10秒,所以每次执行的实际时间为1分钟过10秒.cron = "0 * * * * *"该属性每到整数分钟时间点时执行一次.
定制纯文本邮件时,只需要指定收件人邮箱账号、邮件标题和邮件内容即可。下面,先使用Sping Boot框架实现纯文本邮件的发送任务。
1.在pom.xml中添加邮件服务依赖启动器
org.springframework.boot
spring-boot-starter-mail
2.在全局配置文件application.properties添加邮件服务配置,内容如文件9.6所示:
# 发件人邮件服务器相关配置
spring.mail.host=smtp.qq.com
spring.mail.port=587
# 配置个人QQ账户和密码(这里需要大家修改为自己的QQ账号和密码,密码是加密后的授权码,授权码的获得后继讲解)
[email protected]
spring.mail.password=ijdjokspcbnzfbfa
spring.mail.default-encoding=UTF-8
# 邮件服务超时时间配置
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=3000
spring.mail.properties.mail.smtp.writetimeout=5000
3.定制邮件发送服务
在com.itheima.service的包中,新建一个邮件发送任务管理的业务处理类SendEmailService,内容如下:
@Service
public class SendEmailService {
@Autowired
private JavaMailSenderImpl mailSender;//使用Spring框架提供的实现类JavaMailSenderImpl来实现邮件发送。
@Value("${spring.mail.username}")//借助@Value注解读取全局变量中的spring.mail.username的值来作发件人
private String from;
/**
* 发送纯文本邮件
*
* @param to 收件人地址
* @param subject 邮件标题
* @param text 邮件内容
*/
public void sendSimpleEmail(String to, String subject, String text) {
// 定制纯文本邮件信息SimpleMailMessage
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);//设置发件人
message.setTo(to);//设置收件人
message.setSubject(subject);//设置邮件标题
message.setText(text);//设置 正文件内容
try {
// 发送邮件
mailSender.send(message);
System.out.println("纯文本邮件发送成功");
} catch (MailException e) {
System.out.println("纯文本邮件发送失败 " + e.getMessage());
e.printStackTrace();
}
}
}
4.邮箱配置POP3/SMTP服务
5.在测试类中进行邮件发送测试,示例代码如下:
@Autowired
private SendEmailService sendEmailService;
@Test
public void sendSimpleMailTest() {
String to="[email protected]";//这里修改为你能接收到的邮箱
String subject="【纯文本邮件】标题";
String text="Spring Boot纯文本邮件发送内容测试.....";
// 发送简单邮件
sendEmailService.sendSimpleEmail(to,subject,text);
}
1.定制邮件发送服务
上一节已添加了邮件服务依赖和相关配置,这里我们可以直接使用。这里,我们打开之前创建 的邮件发送任务的业务处理类SendEmailService,编写一个发送带附件和图片邮件的业务方法,示例代码如下:
/**
* 发送复杂邮件(包括静态资源和附件)
* @param to 收件人地址
* @param subject 邮件标题
* @param text 邮件内容
* @param filePath 附件地址
* @param rscId 静态资源唯一标识
* @param rscPath 静态资源地址
*/
//sendComplexEmail()方法需要接收的参数除了基本的发送信息外,还包括静态资源唯一标识、静态资源路径和附件路径
public void sendComplexEmail(String to,String subject,String text,String filePath,String rscId,String rscPath){
// 定制复杂邮件信息MimeMessage
MimeMessage message = mailSender.createMimeMessage();
try {
// 使用MimeMessageHelper帮助类对邮件信息封装处理 ,并设置multipart多部件使用为true
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text, true);
// 设置邮件静态资源
FileSystemResource res = new FileSystemResource(new File(rscPath));
helper.addInline(rscId, res);//设置邮件静态资源的方法
// 设置邮件附件
FileSystemResource file = new FileSystemResource(new File(filePath));
String fileName = filePath.substring(filePath.lastIndexOf(File.separator));
helper.addAttachment(fileName, file);//设置邮件附件的方法
// 发送邮件
mailSender.send(message);
System.out.println("复杂邮件发送成功");
} catch (MessagingException e) {
System.out.println("复杂邮件发送失败 "+e.getMessage());
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
在测试类中添加一个方法调用带附件和图片的复杂邮件发送的方法进行测试,代码如下:
@Test
public void sendComplexEmailTest() {
//根据前面定义的复杂邮件发送业务定制各种参数
String to="[email protected]";//修改为你自己的邮件方便接收查看
String subject="【复杂邮件】标题";
// 定义邮件内容
StringBuilder text = new StringBuilder();
//对邮件内容使用了HTML标签编辑邮件内容
text.append("");
text.append("祝大家元旦快乐!
");
// cid为嵌入静态资源文件关键字的固定写法,如果改变将无法识别;rscId则属于自定义的静态资源唯一标识,一个邮件内容中可能会包括多个静态资源,该属性是为了区别唯一性的。
String rscId = "img001";
text.append("");
text.append("");
// 指定静态资源文件和附件路径
String rscPath="D:\\abc.png";//注意这里修改为你的硬盘中有的资源
String filePath="D:\\CONFIG.txt";//注意这里修改为你的硬盘中有的资源
// 发送复杂邮件
sendEmailService.sendComplexEmail(to,subject,text.toString(),filePath,rscId,rscPath);
}
1.在pom.xml中添加一个Thymeleaf模板引擎依赖启动器
org.springframework.boot
spring-boot-starter-thymeleaf
2.定制模板邮件
在项目的模板页面文件夹templates中添加发送用户注册验证码的模板页面emailTemplate_vercode.html,内容如下:
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>用户验证码title>
head>
<body>
<div><span th:text="${username}">XXXspan> 先生/女士,您好:div>
<P style="text-indent: 2em">您的新用户验证码为<span th:text="${code}" style="color: cornflowerblue">123456span>,请妥善保管。P>
body>
html>
邮件模板中主要模拟给注册用户发送一个动态验证码,从内容可以看出,该模板页面上包含两个变量:用户名username和验证码code,这两个变量需要后继发送过程中动态填充。
3.在SendEmailService中,编写一个发送HTML模板邮件的业务方法,代码如下:
/**
* 发送模板邮件
* @param to 收件人地址
* @param subject 邮件标题
* @param content 邮件内容
*/
public void sendTemplateEmail(String to, String subject, String content) {
MimeMessage message = mailSender.createMimeMessage();
try {
// 使用MimeMessageHelper帮助类对邮件信息进行封装处理,并设置multipart多部件使用为true
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content, true);
// 发送邮件
mailSender.send(message);
System.out.println("模板邮件发送成功");
} catch (MessagingException e) {
System.out.println("模板邮件发送失败 "+e.getMessage());
e.printStackTrace();
}
}
4.模板邮件发送效果测试
在测试类中添加一个方法调用前面编写的Html模板邮件发送方法进行测试效果,代码如下:
@Autowired
private TemplateEngine templateEngine;
@Test
public void sendTemplateEmailTest() {
String to="[email protected]";
String subject="【模板邮件】标题";
// 使用模板邮件定制邮件正文内容
Context context = new Context();//Context注意正确导入“import org.thymeleaf.context.Context;”
context.setVariable("username", "石头");
context.setVariable("code", "456123");
// 使用TemplateEngine设置要处理的模板页面
String emailContent = templateEngine.process("emailTemplate_vercode", context);
// 发送模板邮件
sendEmailService.sendTemplateEmail(to,subject,emailContent);
}