Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)

注:实践内容参考人民邮电出版社的教程《 Spring Boot企业级开发教程》作者:黑马程序员,上传本文仅以实践过程以供大家共同学习解决问题,如有侵权不当行为,请告知后,我会更正或删除。

Spring Boot任务管理

Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第1张图片

1 异步任务

在这里插入图片描述

1.1 无返回值异步任务调用

这里使用Spring Boot框架,结合使得异步任务调用的方式来演示项目向新注册用户发送短信验证码的场景需求,进一步说明无返回值的异步任务调用。

  • 1.使用Sping Initializr创建Spring Boot项目,选择Web依赖(Spring Boot整合 了异步任务,只需在项目中引入Web模块,然后完成项目创建。如图:
    Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第2张图片

  • 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注解开启基于注解的异步任务支持。如图,这里添加到项目启动类上。
    Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第3张图片

  • 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,效果 如图:

Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第4张图片
Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第5张图片

1.2 有返回值异步任务调用

这里演示一个程序中需要调用两个业务方法对相关业务数据统计分析,并将统计结果汇总,进一步说明有返回值 的异步任务调用。

  • 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 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第6张图片

    从演示结果看出,执行statistics()方法并调用异步方法处理业务有一定耗时。
    Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第7张图片

2 定时任务

在这里插入图片描述

2.1 定时任务介绍

Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第8张图片

2.2 定时任务实现

这里使用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

  • 3.启动项目,定时任务效果 如图:
    Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第9张图片

    从执行效果可以看出,fixedRate = 60000和fixedDelay = 60000,每隔一分钟会执行一次.其中fixedDelay属性对应的方法有休眠10秒,所以每次执行的实际时间为1分钟过10秒.cron = "0 * * * * *"该属性每到整数分钟时间点时执行一次.

3 邮件任务

在这里插入图片描述

3.1 发送纯文本邮件

定制纯文本邮件时,只需要指定收件人邮箱账号、邮件标题和邮件内容即可。下面,先使用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
    

Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第10张图片

  • 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服务

    进入邮箱设置,查看POP3/SMTP服务是否开启(这里演示的是QQ邮箱)
    Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第11张图片
    Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第12张图片

  • 5.在测试类中进行邮件发送测试,示例代码如下:

    @Autowired
    private SendEmailService sendEmailService;
    @Test
    public void sendSimpleMailTest() {
        String to="[email protected]";//这里修改为你能接收到的邮箱
        String subject="【纯文本邮件】标题";
        String text="Spring Boot纯文本邮件发送内容测试.....";
        // 发送简单邮件
        sendEmailService.sendSimpleEmail(to,subject,text);
    }
    

运行sendSimpleMailTest,效果如图:
Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第13张图片

通过邮箱可以查看到发送的邮件,如图:
Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第14张图片

3.2 发送带附件和图片的邮件

  • 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); }
  • 运行单元测试方法sendComplexEmailTest(),效果如图:
    Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第15张图片

    接收到的邮件与设置的内容一致,如图:
    Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第16张图片

3.3 发送模板邮件

Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第17张图片

  • 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);
    }
    

Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第18张图片

运行sendTemplateEmailTest(),效果如图:
Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第19张图片

查看邮件内容,如图:
Spring Boot 实践之十二 Spring Boot任务管理((无/有)返回值异步任务调用/定时任务/发送(纯文本/带附件/模板)邮件)_第20张图片

你可能感兴趣的:(Spring,Boot)