Spring Boot | Spring Boot 整合 “异步任务“ 的实现

news2024/11/27 8:21:21

目录:

    • 一、异步任务
      • 1.1 "无返回值" 异步任务调用 :
        • ① 创建项目
        • ② 编写 "异步调用方法" ( 使用 @Async 注解 )
        • ③ "主程序启动类"中 开启基于 "注解" 的异步任务支持 ( 使用@EnableAsync注解 )
        • ④ 编写 "控制层" 相关方法
        • ⑤ "异步任务" 效果测试
      • 1.2 "有返回值" 异步任务调用 :
        • ① 创建项目
        • ② 编写 "异步调用方法" ( 使用 @Async 注解 )
        • ③ "主程序启动类"中 开启基于 "注解" 的异步任务支持 ( 使用@EnableAsync注解 )
        • ④ 编写 "控制层" 相关方法
        • ⑤ "异步任务" 效果测试

在这里插入图片描述

作者简介 :一只大皮卡丘,计算机专业学生,正在努力学习、努力敲代码中! 让我们一起继续努力学习!

该文章参考学习教材为:
《Spring Boot企业级开发教程》 黑马程序员 / 编著
文章以课本知识点 + 代码为主线,结合自己看书学习过程中的理解和感悟 ,最终成就了该文章

文章用于本人学习使用 , 同时希望能帮助大家。
欢迎大家点赞👍 收藏⭐ 关注💖哦!!!

(侵权可联系我,进行删除,如果雷同,纯属巧合)


  • 开发 Web 应用时,多数应用具备 “任务调度” 功能。( Spring Boot 任务管理 ) 常见的任务 包括 ① 异步任务
    ② 定时任务③ 发"邮件任务"
  • 我们将以数据库报表为例看看任务调度如何 帮助改善 “系统设计”报表可能是错综复杂的,用户可能需要很长时间找到需要的报表数据,此时,我们可以在这个报表应用添加"异步任务"减少用户等待时间,从而 提高用户体验
  • 除此之外,还可以在 报表应用添加"定时任务" 和 "邮件任务" ,以便用户可以安排在任何他们 需要的时间 "定时"生成报表,并在 Email发送。下面将介绍如何使用Spring Boot开发这些常见的任务

一、异步任务

  • Web 应用开发中,大多数情况都是通过 同步方式 完成数据交互处理,但是,处理与第三方系统的交互容易造成 响应迟缓的情况,之前大部分都是使用 “多线程完成此类任务,除此之外,还可以使用 异步调用 的方式完美解决这个问题
  • 根据 异步处理方式的不同,可以将 异步任务的调用分为 无返回值异步任务调用 有返回值异步任务 调用。

1.1 “无返回值” 异步任务调用 :

  • 实际开发中,项目 可能会 向新注册用户 "发送短信验证码",这时,可以考虑使用 异步任务调用的方式实现一方面是因为用户对这个时效性要求 不是特别高 ( 实际发送验证码客户手机上是要1-几秒的时间的 ,但提示说"验证码"已发送 这个可是几乎马上响应的,这两个动作有时间差前者满后者快,就是因为使用了 “异步任务” , 让"慢的动作" 和 “快的动作区分开来 ,这个效果是用"异步任务实现的" ,) 。
    一方面特定时间范围内没有收到验证码用户可以点击再次发送验证码。下面将使用Spring Boot框架演示这种场景需求,进一步说明 无返回值的异步任务调用

    ps
    实际情况时,点了获得验证码之后,系统快速回应说验证码已发送 ( 假设其是"主程序" ),然后 验证码过了一段时间才实际发到手机上 ( 假设其是 “次程序” )的,这两个动作是有 时间差的,怎么实现这个效果? 或者说 不用这种效果会有什么缺点呢?—在次程序这里使用了 “异步任务

    如果不使用 "异步任务" , 那么此时的i效果 就是 : 点了"发送验证码"按钮后要等几秒之后才说"验证码已发送",然后 “实际的” 验证码也发送到手机上,此时两个动作是没什么时间差的,这种效果好吗?
    ---- 那肯定是不好的,因为验证码过一段时间才发送到手机上的, 那为什么要让"主程序"也陪着一起等几秒呢? ,所以用了"异步任务"之后,主程序就可以快速做出响应,然后"次程序"执行多久就多久,客户只需等待就好。

① 创建项目
  • 创建项目 :

    在这里插入图片描述

    需要说明的是Spring 框架 提供了对 异步任务支持SpringBoot框架继承了这一 异步任务 功能。在 Spring Boot 中整合异步任务时,只需在项目中引入Web 模块中的 Web 依赖就可以使用这种异步任务功能。

② 编写 “异步调用方法” ( 使用 @Async 注解 )
  • 在项目中创建 service包,并在该包下创建一个业务实现类 : MyAsyncService,在该类中编写模拟用户短信验证码发送方法例子代码如下 :

    MyAsyncService.java

    import org.springframework.scheduling.annotation.Async;
    import org.springframework.stereotype.Service;
    
    @Service //加入IOC容器
    public class MyAsyncService { //"异步任务" 业务类
    
        @Async //标记该方法为"异步方法" (此时该异步方法还不会生效,要在主程序启动类中添加 @EnableAsync注解 )
        //该方法用于模拟"发送短信验证码"
        public void sendSms() throws Exception{
            System.out.println("--------------------");
            System.out.println("调用短信验证码业务方法...,验证码发送中,请稍等...");
            /*
                System.currentTimeMillis():
               返回当前时间与1970年1月1日00:00:00 GMT之间的 "毫秒数"。这个方法通常用于生成"时间戳",它可以帮助我们跟踪和记录事件发生的时间。
             */
            Long startTime = System.currentTimeMillis();
            Thread.sleep(5000); //线程"睡眠"5秒
            Long endTime = System.currentTimeMillis();
            System.out.println("验证码真正实际发送到手机中~");
            System.out.println("短信业务执行完成耗时:(次流程) "+(endTime-startTime));
        }
    
    }
    
③ "主程序启动类"中 开启基于 “注解” 的异步任务支持 ( 使用@EnableAsync注解 )
  • 上一步编写的 用户短信验证码发送业务方法中,使用 @Async 注解标记了异步方法如果想要异步方法生效,还需要使用 @EnableAsync 注解 开启基于注解异步任务支持 ( 让被 “@Async注解” 标记的"异步方法"生效 )。@EnableAsync 注解通常会添加在 项目启动类 上,例子代码如下

    Chapter25Application.java ( 主程序启动类 ):

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.scheduling.annotation.EnableAsync;
    
    @EnableAsync //开启基于"注解"的异步任务支持 ( 让被 "@Async注解" 标记的"异步方法"生效 )
    @SpringBootApplication
    public class Chapter25Application {
    
        public static void main(String[] args) {
           SpringApplication.run(Chapter25Application.class, args);
        }
    }
    
④ 编写 “控制层” 相关方法
  • 在项目中创建 controller,在该包下创建类 MyAsyncControler用于 调用异步方法。在该类中模拟编写用户短信验证码发送处理方法,例子代码如下 :

    MyAsyncService.java :

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    @ResponseBody //将方法的返回值转换为“指定类型”且存入到响应体中
    @Controller //将该类加入到IOC容器中
    public class MyAsyncController {// "控制层"相关内容
    
        @Autowired
        private MyAsyncService myAsyncService;
    
        @GetMapping("/sendSMS")
        public String sendSms() throws Exception {
            long startTime = System.currentTimeMillis();
            //调用"业务层"中的"发送短信方法"
            myAsyncService.sendSms();
            long endTime = System.currentTimeMillis();
            System.out.println("验证码已发送...( 客户得到提示:验证码已发送~ )");
            System.out.println("主流程耗时: "+(endTime-startTime));
            return "success"; //响应该字符串信息给前端
        }
    }
    
⑤ “异步任务” 效果测试
  • 启动项目后,在浏览器上访问 http://localhost:8080/sendSMS ,测试"异步任务"请求,此时**控制台打印信息** 如下图所示 :

    在这里插入图片描述


    在这里插入图片描述

    演示结果可以看出,执行 sendSMS( )方法并调用异步方法处理短信业务时,在 很短的时间内(1毫秒)完成了主流程的执行,并向页面响应主流程结果,而在主流程打印输出方法之前 调用的 异步方法 经过一段时间后才执行完毕 ( 主次流程之间存在"时间差" ,此时为了不影响用户体验,可用 “异步任务” ) 。因此,从执行结果可以发现,案例中无返回值异步任务调用成功

    需要说明 的是,上述案例中的异步方法没有返回值 的,这样 主流程执行异步方法不会阻塞,而是继续向下执行主流程程序,直接向页面响应结果,而调用异步方法会作为 一个子线程单独执行,直到 异步方法执行完成

  • 注释 @Async注解重启动项目访问路径,看看""异步任务 和 ""异步任务区别 :

    在这里插入图片描述


    在这里插入图片描述

1.2 “有返回值” 异步任务调用 :

  • 实际开发中,项目中可能会涉及 有返回值异步任务调用。例如,一个程序中需要 调用两个业务方法 对相关 业务数据统计分析,并将统计结果汇总。下面j将使用 Spring Boot框架演示这种场景需求,进一步说明 有返回值异步任务 调用。
① 创建项目
  • 创建项目 :

    在这里插入图片描述

    需要说明的是Spring 框架 提供了对 异步任务支持SpringBoot框架继承了这一 异步任务 功能。在 Spring Boot 中整合异步任务时,只需在项目中引入Web 模块中的 Web 依赖就可以使用这种异步任务功能。

② 编写 “异步调用方法” ( 使用 @Async 注解 )
  • 在项目中创建 service包,并在该包下创建一个业务实现类 : MyAsyncService,在该类中编写 两个模拟有返回值异步任务业务处理方法
    例子代码如下 :

    MyAsyncService.java

    import org.springframework.scheduling.annotation.Async;
    import org.springframework.scheduling.annotation.AsyncResult;
    import org.springframework.stereotype.Service;
    
    import java.util.concurrent.Future;
    
    @Service //加入IOC容器
    public class MyAsyncService { //"异步任务" 业务类
    
        @Async
        public Future<Integer> processA() throws Exception{ //该"异步方法"有一定的"处理时间",并且返回统计结果。
            System.out.println("开始分析统计业务A数据.....");
            Long startTime = System.currentTimeMillis();
            //休眠
            Thread.sleep(4000); //线程"睡眠"5秒
            //模拟定义一个假的统计结果
            int count = 123456;
            Long endTime = System.currentTimeMillis();
            System.out.println("业务A数据统计耗时: "+(endTime-startTime));
            //使用AsyncResult对象封装 返回的"异步结果数据",该方法的返回值为 Future类型
            return new AsyncResult<Integer>(count);
        }
    
    
    
        @Async
        public Future<Integer> processB() throws Exception{ //该"异步方法"有一定的"处理时间",并且返回统计结果。
            System.out.println("开始分析统计业务B数据.....");
            Long startTime = System.currentTimeMillis();
            //休眠
            Thread.sleep(5000); //线程"睡眠"5秒
            //模拟定义一个假的统计结果
            int count = 654321;
            Long endTime = System.currentTimeMillis();
            System.out.println("业务B数据统计耗时: "+(endTime-startTime));
            //使用AsyncResult对象封装 返回的"异步结果数据",该方法的返回值为 Future类型
            return new AsyncResult<Integer>(count);
        }
    
    }
    
    
③ "主程序启动类"中 开启基于 “注解” 的异步任务支持 ( 使用@EnableAsync注解 )
  • 上一步编写的 用户短信验证码发送业务方法中,使用 @Async 注解标记了异步方法如果想要异步方法生效,还需要使用 @EnableAsync 注解 开启基于注解异步任务支持 ( 让被 “@Async注解” 标记的"异步方法"生效 )。@EnableAsync 注解通常会添加在 项目启动类 上,例子代码如下

    Chapter25Application.java ( 主程序启动类 ):

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.scheduling.annotation.EnableAsync;
    
    @EnableAsync //开启基于"注解"的异步任务支持 ( 让被 "@Async注解" 标记的"异步方法"生效 )
    @SpringBootApplication
    public class Chapter25Application {
    
        public static void main(String[] args) {
           SpringApplication.run(Chapter25Application.class, args);
        }
    }
    
④ 编写 “控制层” 相关方法
  • 编写 "控制层" 相关方法

    MyAsyncController.java

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import java.util.concurrent.Future;
    
    @ResponseBody //将方法的返回值转换为“指定类型”且存入到响应体中 --让return 字符串时,不被默认识别为一个"视图页面"
    @Controller //将该类加入到IOC容器中
    public class MyAsyncController {// "控制层"相关内容
    
        @Autowired
        private MyAsyncService myAsyncService;
    
        @GetMapping("/statistics")
        public String statistics() throws Exception {
            long startTime = System.currentTimeMillis();
            //"有返回值"的 "异步任务"
            Future<Integer> futureA = myAsyncService.processA();
            Future<Integer> futureB = myAsyncService.processB();
            int total = futureA.get()+futureB.get();
            System.out.println("异步任务数据统计汇总结果: "+total);
            long endtTime = System.currentTimeMillis();
    
            System.out.println("主流程耗时: "+(endtTime-startTime));
            return "success"; //响应该字符串信息给前端
        }
    
    }
    
⑤ “异步任务” 效果测试
  • 启动项目后,在浏览器上访问 http://localhost:8080/statistics ,测试"异步任务"请求,此时 控制台打印信息下图所示 :

    在这里插入图片描述

    演示结果可以看出,执行 statistics( )方法调用异步方法处理业务数据统计时,需要 耗费一定的时间(5004毫秒)完成主流程的执行,并向页面响应结果,而在主流程打印输出结果之前一直等待着业务A 和业务 B 两个异步方法异步调用处理结果汇总。因此,从执行结果可以发现,案例中 有返回值异步任务调用成功


需要说明的是,上述的异步方法有返回值的,当返回值较多时 主流程执行异步方法是会有 短暂阻塞需要等待并获取异步方法的 返回结果,而调用的两个异步方法会作为两个子线程 “并行执行”,直到异步方法执行完成返回结果,这样 主流程 会在 最后一个异步方法返回结果后跳出阻塞状态

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1659639.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue中常用指令

Vue中的常用指令 Vue中的常用指令内容渲染指令条件渲染指令事件绑定指令内联语句事件处理函数给事件处理函数传参 属性绑定指令列表渲染指令v-for中的key 双向绑定指令 Vue中的常用指令 概念&#xff1a;指令 是 Vue 提供的带有 v- 前缀 的 特殊 标签属性。Vue 会根据不同的【…

2024年数维杯高校数学建模竞赛(B题) 建模解析| 生物质和煤共热解问题的研究 |小鹿学长带队指引全代码文章与思路

我是鹿鹿学长&#xff0c;就读于上海交通大学&#xff0c;截至目前已经帮200人完成了建模与思路的构建的处理了&#xff5e; 本篇文章是鹿鹿学长经过深度思考&#xff0c;独辟蹊径&#xff0c;实现综合建模。独创复杂系统视角&#xff0c;帮助你解决数维杯的难关呀。 完整内容可…

Linux-远程登录

远程登录Linux服务器的两款小工具&#xff1a; 1、Xshell &#xff08;可以远程登录到Linux终端控制台&#xff09; 2、 Xftp (可以与Linux服务器互相传递文件) 家庭/学校免费 - NetSarang Website 下载地址 1、傻瓜式安装Xshell6 2、在Linux主机上查看 Linux主机的…

Java Web 学习笔记(一) —— MySQL(3)

目录 1 Mysql 函数1.1 日期函数1.2 判断函数1.3 字符函数1.4 数学函数 2 Mysql 性能2.1 提高操作数据库性能2.2 执行次数比较多的语句2.3 sql语句的执行效率 3 Mysql 优化&#xff08;***&#xff09;3.1 定位慢查询3.2 SQL执行计划3.3 索引3.3.1 索引介绍与分类3.3.2 索引的使…

案例研究|硬之城借助DataEase以数据驱动供应链精细化管理

深圳硬之城信息技术有限公司&#xff08;以下简称为“硬之城”&#xff09;成立于2015年&#xff0c;专注电子元件供应链领域&#xff0c;定位于电子产业供应链与智造平台。硬之城通过名为“Allchips”的集成式服务平台&#xff0c;为客户提供一站式的电子元件采购和供应链管理…

VLAN聚合

VLAN聚合&#xff08;VLAN Aggregation&#xff0c;也称Super VLAN&#xff09;指在一个物理网络内&#xff0c;用多个VLAN&#xff08;称为Sub-VLAN&#xff09;隔离广播域&#xff0c;并将这些Sub-VLAN聚合成一个逻辑的VLAN&#xff08;称为Super-VLAN&#xff09;&#xff0…

MySQL·复合查询

目录 基本查询回顾 案例1&#xff1a;查询工资高于500或岗位为MANAGER的雇员&#xff0c;同时还要满足他们的姓名首字母为大写的J 案例2&#xff1a;按照部门号升序而雇员的工资降序排序 案例3&#xff1a;使用年薪进行降序排序 案例4&#xff1a;显示工资最高的员工的名字…

『先进技术助力』Kompas AI:智能AI代理在工作中的应用与效率提升

『智能化未来』Kompas AI如何改变我们的工作方式&#xff1f; 在这个信息时代&#xff0c;利用AI聊天机器人来处理机械性的工作已经成为一种趋势。ChatGPT作为一种智能助手&#xff0c;不仅能够提高工作效率&#xff0c;还可以帮助我们更明智地做出决策&#xff0c;从而释放出更…

【MySQL数据库】丨一文详解 JdbcTemplate(Spring中的CRUD)

前言 JdbcTemplate 是 Spring框架 中提供的一个对象&#xff0c;用于简化JDBC操作。它使得数据库操作变得更为简单和方便&#xff0c;大大提高了开发效率。 文章目录 前言为何要使用JdbcTemplate在JdbcTemplate中执行SQL语句的方法大致分为3类&#xff1a;案例代码 JdbcTemplat…

活字格中如何加入JavaScript的代码和事件以及如何调试

活字格&#xff1a; 如何加入JavaScript的代码和事件 1&#xff09;选中组件。 2&#xff09;编辑命令“按钮。 3&#xff09;选择JavaScript命令&#xff0c;并点亮五星。 4&#xff09;编写js代码&#xff0c;确定。 5&#xff09;运行。 如何查看js运行&#xff1a; …

【R语言】边缘概率密度图

边缘概率密度图是一种在多变量数据分析中常用的图形工具&#xff0c;用于显示每个单独变量的概率密度估计。它通常用于散点图的边缘&#xff0c;以便更好地理解单个变量的分布情况&#xff0c;同时保留了散点图的相关性信息。 在边缘概率密度图中&#xff0c;每个变量的概率密度…

基于TL431和CSA的恒压与负压输出

Hello uu们,51去那里玩了呀?该收心回来上班了,嘿嘿! 为什么会有这个命题,因为我的手头只有这些东西如何去实现呢?让我们一起来看电路图吧.电路图如下图1所示 图1:CSA恒压输出电路 图1中,R1给U2提供偏置,Q1给R1提供电流,当U1-VOUT输出大于2.5V时候,U2内部的三极管CE导通,使得…

存储和NFS共享

存储类型 存储类型分为三种 直连式存储&#xff1a;Direct-Attached Storage&#xff0c;简称DAS网络附加存储&#xff1a;Network-Attached Storage&#xff0c;简称NAS存储区域网络&#xff1a;Storage Area Network&#xff0c;简称SAN DAS:存储和主机是直连的&#xff0…

安全数据交换系统哪个好?该如何选型?

安全数据交换系统是用于在不同网络或组织之间安全、高效地传输和共享数据的解决方案。安全数据交换系统对于任何需要处理敏感数据、确保数据安全、并满足合规要求的组织来说都是至关重要的。 这种系统通常用于以下目的&#xff1a; 1&#xff09;数据传输&#xff1a;允许用户…

Midjourney Imagine API 申请及使用

Midjourney Imagine API 申请及使用 申请流程 要使用 Midjourney Imagine API&#xff0c;首先可以到 Midjourney Imagine API 页面点击「Acquire」按钮&#xff0c;获取请求所需要的凭证&#xff1a; 如果你尚未登录或注册&#xff0c;会自动跳转到登录页面邀请您来注册和登…

【mysql】mysql导入导出数据详解

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

计算机毕业设计系列~~~基于SSM的宠物销售网站

目录 一、项目介绍 二、开题报告 三、项目截图 一、项目介绍 本项目是一款基于SSM的宠物销售网站&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1. 包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2. …

Web实时通信的学习之旅:WebSocket入门指南及示例演示

文章目录 WebSocket的特点1、工作原理2、特点3、WebSocket 协议介绍4、安全性 WebSocket的使用一、服务端1、创建实例&#xff1a;创建一个webScoket实例对象1.1、WebSocket.Server(options[&#xff0c;callback])方法中options对象所支持的参数1.2、同样也有一个加密的 wss:/…

llama.cpp制作GGUF文件及使用

llama.cpp的介绍 llama.cpp是一个开源项目&#xff0c;由Georgi Gerganov开发&#xff0c;旨在提供一个高性能的推理工具&#xff0c;专为在各种硬件平台上运行大型语言模型&#xff08;LLMs&#xff09;而设计。这个项目的重点在于优化推理过程中的性能问题&#xff0c;特别是…

【Oracle直播课】5月19日Oracle 19c OCM认证大师课 (附课件预览)

Oracle 19c OCM认证大师培训 - 课程体系 - 云贝教育 (yunbee.net) 部分课件预览 OCM部分课件预览 Oracle Database 19c Certified Master Exam (OCM) 认证大师 25 天 / 150课时 什么是Oracle 19c OCM&#xff1f; Oracle Certified Master (OCM)是Oracle认证大师&#xff0c;…