SpringBoot系列:8. SpringBoot实现异步,邮件发送,定时任务

前言

  1. 本章节主要讲解Java中常用的任务:
    异步任务
    邮件任务
    定时执行任务

一、Java中的-任务

① 平时接触到的任务包含如下几种↓:
⑴ 异步任务
- 比如我们平时发送邮件,要等到邮件发送完才会响应一些消息回来。 
- 那如何实现异步任务呢?可以利用"多线程"来实现,但是如果你直接使用多线程
的话,可能会让系统性能变慢,那得另外想办法来实现"异步任务"。

⑵ 定时任务
- 在某一个时间点,去执行一个东西。
⑶ 邮件发送任务(这个是SpringBoot里面官方的)
- 这个功能在大多数网站里面都是很常见的。

1.1 异步任务

① 异步任务一般使用的场景分析

⑴ 比如:有些发邮件的网页的按钮一点邮件就发出去了,网页就响应回来了一个信息,
但是邮件就很久之后才发给你(因为发送邮件是需要时间的)- 在中间响应的这个时间为了不让用户一直等,网页会响应一个返回值给你,
让你不至于一直去等,提升用户体验,其实就是在利用多线程将邮件偷偷的发给你。

-------------------------------------------------------------------

② 以下使用"多线程",模拟一下异步任务,代码步骤如下↓:
⑴ 第一步: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(开启异步注解的
功能)
- 异步的方法:就相当于同一时间可以执行多个功能(方法)。多条路走而
不是独木桥。


SpringBoot系列:8. SpringBoot实现异步,邮件发送,定时任务_第1张图片
图asyn1

1.2 邮件任务

① 之前邮件发送的实现有两种方式: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); } }

1.3 定时执行任务

① 定时任务的场景如下↓:
⑴ 类似凌晨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设置的时间,程序就会自动到某一个时间执行该方法下
面的业务代码了。

你可能感兴趣的:(SpringBoot,定时任务,spring,boot,javamail,java,http)