- 本章节主要讲解Java中常用的任务:
异步任务
邮件任务
定时执行任务
① 平时接触到的任务包含如下几种↓:
⑴ 异步任务
- 比如我们平时发送邮件,要等到邮件发送完才会响应一些消息回来。
- 那如何实现异步任务呢?可以利用"多线程"来实现,但是如果你直接使用多线程
的话,可能会让系统性能变慢,那得另外想办法来实现"异步任务"。
⑵ 定时任务
- 在某一个时间点,去执行一个东西。
⑶ 邮件发送任务(这个是SpringBoot里面官方的)
- 这个功能在大多数网站里面都是很常见的。
① 异步任务一般使用的场景分析
⑴ 比如:有些发邮件的网页的按钮一点邮件就发出去了,网页就响应回来了一个信息,
但是邮件就很久之后才发给你(因为发送邮件是需要时间的)。
- 在中间响应的这个时间为了不让用户一直等,网页会响应一个返回值给你,
让你不至于一直去等,提升用户体验,其实就是在利用多线程将邮件偷偷的发给你。
-------------------------------------------------------------------
② 以下使用"多线程",模拟一下异步任务,代码步骤如下↓:
⑴ 第一步:IDEA创建一个Spring Boot项目
- 选择的是"Spring initializr" 来创建项目。
⑵ 第二步:编写一个模拟线程延迟3秒的方法。
/**
* 业务类 :异步任务
*/
@Service
public class AsyncService {
/**
* 利用线程-->让此任务实现延迟
* -->下面让threadInit()线程休息3秒
* -->此时:若此方法被调用就会卡3秒钟(前台则会白屏3秒)
* 要实现此任务异步执行,Springboot框架已经帮我们实现了
* 只需要加一个注解即可实现方法的异步实现
*
* 1. @Async注解:就是告诉Spring这是一个异步的方法,
* 它只要运行的时候,就会帮我们开启一个线程池。
* 2.若要实现异步功能,你就需要在启动类Main()方法上面,开启异步功能。
* @EnableAsync -->此注解表示:开启异步注解的功能
*
*/
@Async
public void threadInit() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("数据正在处理...");
}
}
⑶ 第三步:创建一个controller类,调用延迟3秒的方法
/**
* 异步的Controller
*/
@RestController
public class AsyncController {
/**
* 注入被调用的Service
*/
@Autowired
AsyncService asyncService;
/**
* 1. 下面写一个方法去调用,在service里面异步的方法
* -->此时调用Service里面的threadInit()方法
* 会延迟停止3秒
* 1.1 因此当我们每次去访问此页面,都要延迟3秒,很影响用户体验
* -->如果你想让用户直接的得到一个数据,你就需要在后台调用多线程
* 去处理。这样如果你每次都要手动去编写多线程的处理,就很麻烦
* -->这东西你自己编写多线程也可以给用户返回数据,但是这样比较麻烦
* 1.2 因此Spring框架帮我们做了,我们只需要在threadInit()方法
* 上告诉Spring,这是一个异步的方法。执行调用此threadInit()方法,就会
* 马上给用户返回一个数据,无需等待3秒
* --->只需加一个注解在threadInit()方法加一个注解即可实现
* --->@Async注解加载threadInit()方法上,即可实现异步调用
*/
@RequestMapping("/threadQuest")
public String threadQuest() {
asyncService.threadInit(); //停止3秒
return "ok~~";
}
}
⑷ 第四步:启动类Main()方法开启异步注解功能
@EnableAsync //开启异步注解功能
@SpringBootApplication
public class AsynchronousTaskApplication {
public static void main(String[] args) {
SpringApplication.run(AsynchronousTaskApplication.class, args);
}
}
⑸ 第五步:测试
- 网页访问:localhost:8080/threadQuest
- 如果没开启异步功能,网页会白屏3秒后,在输出:ok~~
- 如果开启异步功能,此时网页马上响应,而不是等3秒在响应,
此时就实现了异步功能,如-"图asyn1"
⑹ 小结:
- 在方法上加一个注解开启异步的注解:@Async(告诉Spring这是一个异
步的方法)
- 在启动类Main()方法上加一个注解:@EnableAsync(开启异步注解的
功能)
- 异步的方法:就相当于同一时间可以执行多个功能(方法)。多条路走而
不是独木桥。
① 之前邮件发送的实现有两种方式:pop3和smtp协议(一个是发送一个是接收)。
- 现在在SpringBoot使用邮件发送很简单,我们原来要导入一个mail的包,此时
在SpringBoot中只需要导入一个jar包就将mail的启动项导进来了。
② 以下演示SpringBoot邮件发送↓
⑴ 第一步:pom.xml导入mail依赖
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-mail -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
⑵ 第二步:获取QQ的邮件账号密码,或是其他邮件账号的账号密码
- 点开qq邮箱,其开启pop3/smth并获取密码
⑶ 第三步:配置文件,配置mail相关属性
# 邮箱账号
spring.mail.username=xxxxxxxx@qq.com
# 邮箱的授权密码(这里的密码就是QQ邮箱里面,上面获取到的密码)
spring.mail.password=sadsadsadsadsad
# 发送的服务器(主机)
# 如果是163就是:smtp.163.com
# 如果是新浪就是:smtp.sina.com
spring.mail.host=smtp.qq.com #这里的服务器是qq
# qq有一个加密规则-->因此应该开启加密授权验证
# 其他的邮件就不需要,qq需要开启此加密规则
spring.mail.properties.mail.smtp.ssl.enable=true
⑷ 测试"一个简单的邮件","一个复杂的邮件"以及"将邮件封装成一个方法"。
@SpringBootTest
class SpringbootMailTaskApplication {
@Autowired
JavaMailSenderImpl mailSender;
/**
* 1.一个简单的邮件
*/
@Test
void contextLoads() {
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
//邮件主题
simpleMailMessage.setSubject("linzxxxxxx_subject");
//邮件内容
simpleMailMessage.setText("linxxxxx_text");
//邮件发给谁
simpleMailMessage.setTo("[email protected]");
//发送邮件的是谁
simpleMailMessage.setFrom("[email protected]");
mailSender.send(simpleMailMessage);
}
/**
* 2.一个复杂的邮件(发送附件"图片"等)
*
* -->一般下面的业务实现代码放在Controller类里面
* -->又或者写在业务实现层里面
* -->也可以对下面邮件发送的代码进行封装处理,方便调用。
*/
@Test
void contextLoads2() throws MessagingException {
//创建一个复杂的邮件
MimeMessage mimeMessage = mailSender.createMimeMessage();
/**
* 下面创建一个MimeMessageHelper类
* -->通过MimeMessageHelper类去实现组装,发送多文件
*/
//通过"MimeMessageHelper"去组装-->(是否支持多文件,True则表示支持多文本上传,因此需开启一个true)
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
/**
* 正文:主题+内容
*/
//主题
helper.setSubject("linxxxx2_subject");
//内容
helper.setText("linxxx2_邮件发送测试内容Test2
",true);
//附件
helper.addAttachment("1.jpg",new File("C:\\Users\\admin\\Desktop\\image\\guhikg.jpg"));
helper.addAttachment("2.jpg",new File("C:\\Users\\admin\\Desktop\\image\\guhikg.jpg"));
/**
* 邮件:发送给谁以及谁来接收
*/
helper.setTo("[email protected]");
helper.setFrom("[email protected]");
mailSender.send(mimeMessage);
}
/**********************************************/
/**
* 3. 将上面的邮件封装成一个方法
*
* @param html 是否开启多文本邮件发送
* @param subject 邮件主题
* @param text 邮件文本内容
* @throws MessagingException
*/
public void sendMail(Boolean html,String subject,String text ) throws MessagingException {
//一个复杂的邮件
MimeMessage mimeMessage = mailSender.createMimeMessage();
//组装~
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,html);
//正文
helper.setSubject(subject);
helper.setText(text,true);
//附件
helper.addAttachment("1.jpg",new File("C:\\Users\\admin\\Desktop\\image\\guhikg.jpg"));
helper.addAttachment("2.jpg",new File("C:\\Users\\admin\\Desktop\\image\\guhikg.jpg"));
helper.setTo("[email protected]");
helper.setFrom("[email protected]");
mailSender.send(mimeMessage);
}
}
① 定时任务的场景如下↓:
⑴ 类似凌晨12点,定时执行日志输出
⑵ 某一个时间点,定时举办商品折扣的互动弄
⑶ 利用定时任务实现某一个时间点,执行某一个业务代码。
-------------------------------------------------
② 定时任务中spring自带的两个定时任务的接口及注解,不用导入任何依
赖包
⑴ 两个接口↓:
- 接口一:TaskScheduler 任务调度者
- 接口二:TaskExecutor 任务执行者
---->上面这两个接口中是Spring帮我们封装好的接口,
我们可以直接拿来使用。
⑵ 注解↓:
- @EnableScheduling 表示:开启定时功能的注解
(加在启动类Main()方法上)
- @Scheduled 表示:表示什么时候执行异步任务
(里面涉及了:Cron表达式)
-------------------------------------------------
③ 定时任务代码演示如下↓:
⑴ 第一步:在启动类上开启定时功能
@SpringBootApplication
@EnableScheduling //开启定时功能的注解
public class TimingTaskApplication {
public static void main(String[] args) {
SpringApplication.run(TimingTaskApplication.class, args);
}
}
⑵ 第二步:编写一个定时任务的方法
@Service
public class ScheduledService {
/**
* 1. 在一个特定的时间,执行下面的testScheduledTask()方法
* -->可以利用@Scheduled注解里面的Cron表达式实现。
*
* 1.1 Cron表达式
* -->Cron表达式从左到右分别表示:
* 秒 分 时 日 月 周几
* 1.2 Cron表达式讲解
* 30 15 10 * * ? ==》表示每天的10点15分30秒执行一次
* 30 0/5 10,18 * * ? ==》表示每天10点和18点,每隔五分钟执行一次
* 0 15 10 ? * 1-6 ==》每个月的周一到周六10点15分,执行一次
* 0 0 12 * * ? ==》每天中午12点执行一次
* 0 15 10 15 * ? ==》每个月15号的上午10点15分执行一次
* 0 15 10 L * ? ==》每个月最后一天的上午10点15分执行一次
* 0/2 * * * * ? ==》每隔两秒执行一次
*
* --->具体更多Cron执行的表达式可网上搜索!
*/
@Scheduled(cron = "0/2 * * * * ?")
public void testScheduledTask(){
System.out.println("testScheduledTask,被执行了!");
}
}
⑶ 第三步:启动Main()方法,直接启动程序即可实现定时执行被注解了
@Scheduled的方法。
⑷ 注意:这里只要我们在启动类加上@EnableScheduling 表示-->开启
定时功能的注解.这个注解,然后编写一个要执行定时任务的方法(这里是
testScheduledTask()方法),然后在方法上添加@Scheduled的注解且
写上Cron表达式来表示具体要执行的时间--->此时我们直接启动Main()
方法,最后在Cron设置的时间,程序就会自动到某一个时间执行该方法下
面的业务代码了。