SpringBoot3任务处理

news2024/12/24 20:27:39

目录

1.异步任务

无返回值异步任务

效果

有返回值异步任务

效果

2.定时任务

效果

3.邮件任务

获取授权码

加入依赖

配置文件

纯文本邮件

效果

复杂邮件

效果

 

1.异步任务

@Async注释:

SpringBoot中的异步调用,可以写在类上或方法上,异步调用只是发送调用的指定,调用者无需等待被调用的方法完全执行完毕,而是继续执行下面流程。

@EnableAsync:

SpringBoot启动类开启异步支持。

无返回值异步任务

为了释放主线程

实现类

/**
 * 无返回值异步任务
 */
@Service
//异步任务注释
@Async
public class TimeService {
    public void sendSMS() {
        System.out.println("发短信启动-----------------");
        long l = System.currentTimeMillis();
        //模拟发动短信过程
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        long l1 = System.currentTimeMillis();
        System.out.println("短信业务耗时" + (l1 - l));

    }
}

控制层

/**
     * 无返回值异步任务
     * 为了释放主线程
     *
     * @return
     */
    @Autowired
    TimeService timeService;

    @RequestMapping("/text1")
    public String SendSMS() {
        System.out.println("主程序启动-----------------");
        long timeMillis = System.currentTimeMillis();
        //异步任务
        timeService.sendSMS();
        long timeMillis1 = System.currentTimeMillis();
        System.out.println("主线程耗时" + (timeMillis1 - timeMillis));
        return "主流程已完成,已释放";
    }

效果

使用前:

cb6da98355454dd9972ebbd1eca9ef5f.png

主线程需要等待子线程完成后才结束。

使用后:

9385d47107f743a0a49b13d451e54543.png

8bb76472853a4706ab3da65ad269f817.png

主线程已经进行完毕,子线程还在继续。

有返回值异步任务

AsyncResult类:封装异步任务上的异步操作的结果

Future类:表示一个可能还没有完成的异步任务的结果

Future的主要方法:

get()方法可以当任务结束后返回一个结果,如果调用时,工作还没有结束,则会阻塞线程,直到任务执行完毕

get(long timeout,TimeUnit unit)做多等待timeout的时间就会返回结果

cancel(boolean mayInterruptIfRunning)方法可以用来停止一个任务,如果任务可以停止(通过mayInterruptIfRunning来进行判断),则可以返回true,如果任务已经完成或者已经停止,或者这个任务无法停止,则会返回false.

isDone()方法判断当前方法是否完成

isCancel()方法判断当前方法是否取消

实现类

此时@Async注解写在方法上,表示4个线程同时进行,主线程需要四个线程返回值的和

/**
 * 有返回值异步任务
 */
@Service
public class MyAsyncService {
    //异步任务注释
    @Async
    //Future<Integer>只能在这里和@Async配合使用
    public Future<Integer> processA() {
        System.out.println("开始分析并统计业务A数据...");
        Long startTime = System.currentTimeMillis();
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        int count = 123;
        Long endTime = System.currentTimeMillis();
        System.out.println("业务A数据统计耗时:" + (endTime - startTime));
        //封装在AsyncResult结果集中
        return new AsyncResult<Integer>(count);
    }

    @Async
    //Future<Integer>只能在这里和@Async配合使用
    public Future<Integer> processB() {
        System.out.println("开始分析并统计业务B数据...");
        Long startTime = System.currentTimeMillis();
        try {
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        int count = 456;
        Long endTime = System.currentTimeMillis();
        System.out.println("业务B数据统计耗时:" + (endTime - startTime));
        //封装在AsyncResult结果集中
        return new AsyncResult<Integer>(count);
    }

    @Async
    //Future<Integer>只能在这里和@Async配合使用
    public Future<Integer> processC() {
        System.out.println("开始分析并统计业务C数据...");
        Long startTime = System.currentTimeMillis();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        int count = 789;
        Long endTime = System.currentTimeMillis();
        System.out.println("业务C数据统计耗时:" + (endTime - startTime));
        //封装在AsyncResult结果集中
        return new AsyncResult<Integer>(count);
    }

    @Async
    //Future<Integer>只能在这里和@Async配合使用
    public Future<Integer> processD() {
        System.out.println("开始分析并统计业务D数据...");
        Long startTime = System.currentTimeMillis();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        int count = 963;
        Long endTime = System.currentTimeMillis();
        System.out.println("业务D数据统计耗时:" + (endTime - startTime));
        //封装在AsyncResult结果集中
        return new AsyncResult<Integer>(count);
    }
}

控制层

/**
     * 有返回值异步任务
     * 是为了释放完成任务的子线程
     * @return
     */
    @Autowired
    MyAsyncService myAsyncService;
    @RequestMapping("/text2")
    public String statistics() throws ExecutionException, InterruptedException {
        Long startTime = System.currentTimeMillis();
        Future<Integer> futureA = myAsyncService.processA();
        Future<Integer> futureB = myAsyncService.processB();
        Future<Integer> futureC = myAsyncService.processC();
        Future<Integer> futureD = myAsyncService.processD();
        int total = futureA.get() + futureB.get()+ futureC.get()+ futureD.get();
        System.out.println("异步任务数据统计汇总结果:" + total);
        Long endTime = System.currentTimeMillis();
        System.out.println("主流程耗时:" + (endTime - startTime));
        return "子线程已完成,已释放主流程已完成";
    }

效果

9cf4da02c0414602b39c39c1f6e28572.png

ab323156ed564874a8122d64e28bbbe0.png

此时,线程完成自己的任务后即可释放。

2.定时任务

@EnableScheduling:

启用了Spring的任务调度功能,在配置类上使用,开启计划任务的支持

@Scheduled:

写在发放上,来声明这是一个任务,包括 cron,fixDelay,fixRate 等类型。无需调用,系统识别到注解会自动调用。

fixRate --按时间频率执行,控制方法执行的间隔时间,是以上一次方法执行完开始算起,如上一次方法执行阻塞住了,那么直到上一次执行完,并间隔给定的时间后,执行下一次。

fixDelay--延迟时间,按照一定的速率执行,是从上一次方法执行开始的时间算起,如果上一次方法阻塞住了,下一次也是不会执行,但是在阻塞这段时间内累计应该执行的次数,当不再阻塞时,一下子把这些全部执行掉,而后再按照固定速率继续执行

cron--固定时间

是否必填

值以及范围

通配符

0-59

, - * /

0-59

, - * /

0-23

, - * /

1-31

, - * ? / L W

1-12 或 JAN-DEC

, - * /

1-7 或 SUN-SAT

, - * ? / L #

1970-2099

, - * /

* :通配,语义相当于… 比如第五个位置的 *就表示每月都会执行(相当于1-12)

? :忽略,语义相当于不管… 比如第六个位置的?就表示不管当前是周几就会执行。至于为什么会有这种用法,我觉得应该是因为它和其他的字符可能会冲突。如果用*的话表示周一到周日都会执行,此时其他语义就不明确了,所以如果用不上星期的话一般给它用一个?表示 not care。

/ :间隔,语义相当于每隔 比如例2中的第三个位置的2/5就表示从2点开始每隔五小时

- :区间,语义相当于到…的每… 比如例2中的第二个位置的15-20就表示第15分钟到20分钟之间的每分钟

, :枚举,语义相当于和… 比如例2中的第一个位置的15,20,40就表示第15秒、20秒和40秒

L :最后(last),语义相当于最后一个 比如例2中的第四个位置的L就表示最后一天

W :工作日,字面意思,就是工作日 比如例3中的第四个位置的15W表示15号附近最近的工作日,如果15号刚好是工作日那就15号触发,如果15号是周六那就14号触发,如果15号是周日那就16号触发。前面不带数字就是所有匹配的工作日。

'L'和 'W'可以一组合使用。如果在日字段上设置"LW",则表示在本月的最后一个工作日触发(一般指发工资)

# :周定位,语义相当于每月的第几个周几 比如例4中的第六个位置的2#3就表示第三个周一。

周字段的设置,若使用英文字母是不区分大小写的 MON 与mon相同。

效果

 

@Scheduled(fixedRate = 1000)
    public void ScheduledText(){
        System.out.println("快背单词!");
    }

每一秒打印一次

374abbafa7b54f81ade1e5f35eedb141.png

 

@Scheduled(fixedDelay = 1000)
    public void ScheduledTest2(){
        System.out.println("快去吃饭!------------------------");
    }

延迟1秒打印一次

161193344edb475f97e53f36c47d784d.png

   

 @Scheduled(cron = "0/10 08 19 * * ? ")
    public void ScheduledTest3(){
        System.out.println("要下课了!");
    }

从19时8分0秒起,每10秒打印一次。

8c75baaa2e7749ee87faaedfb236bdea.png

3.邮件任务

获取授权码

进入QQ邮箱,点击账号与安全

a021dc827bd24631a130337f7e831ada.png

点击安全设置,先和手机进行绑定,如果绑定跳过这一步,直接跳到图一。

f023f54ab0a64a63a63c5e33d93144e8.png

发送短信后点击我已发送。

cab3c0471f8e4f39892fff3c209fbe3a.png

d6a618761f7f42aab3b3dcd308b566f6.png

用微信扫描二维码,发送短信后点击我已发送。

b22a50bba638489786b82d47dc9d944d.png

即可获得授权码

d6dac14884ca4eb69f1a2fa60bc9fee6.png

加入依赖

      

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

配置文件

#发件人邮箱服务器相关配置
spring.mail.host=smtp.qq.com
spring.mail.port=587
#配置个人QQ账户和密码(密码是加密后的授权码)
spring.mail.username=3451866342@qq.com
spring.mail.password=oxfdtthfgoyrdbie
spring.mail.default-encoding=UTF-8

纯文本邮件

通过SimpleMailMessage类定制了邮件信息的发件人地址(From)、收件人地址(To)、邮件标题(ubject)和邮件内容(Text),最后使用JavaMailSenderImpl的send()方法实现纯文本邮件发送。

实现类

@Autowired
    JavaMailSenderImpl javaMailSender;
    @Value("${spring.mail.username}")//获得配置文件中的邮箱地址
    private String from;

    /**
     * 纯文本邮件任务
     */
    public void sendSimpleEmail(String to, String subject, String text) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(from);
        message.setTo(to);//发送邮箱
        message.setSubject(subject);//邮件主题
        message.setText(text);//邮件内容
        javaMailSender.send(message);//发送邮件
        System.out.println("纯文本邮件发送成功");
    }

控制层

/**
     * 邮件任务(纯文本邮件)
     * @return
     */
    @Autowired
    SendEmailService sendEmailService;
    @RequestMapping("/text3")
    public String sendEmail(){
        sendEmailService.sendSimpleEmail("3451866342@qq.com", "测试邮件", "这就是个邮件");
        return "已发送完成";
    }

效果

3249e20d4fd24a8aa6c743e9bccc7630.png

debc118bbaa14d4db2889aeb728d7d99.png

复杂邮件

编写一个发送带附件和图片邮件的业务方法sendComplexEmail() ,该方法需要接收的参数除了基本的发送信息外,还包括静态资源唯一标识、静态资源路径和附件路径。

实现类

/**
     * 复杂邮件任务
     */
    public void MailEmail(String to,String subject,String text,String filePath,String rscId,String rscId2,String rscPath,String rscPath2) {
        // 创建一个 JavaMail MimeMessage 对象
        MimeMessage message = javaMailSender.createMimeMessage();
        try {
            // 创建 MimeMessageHelper 对象,参数为 MimeMessage 对象和开启复杂邮件编码
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(from);//发送邮箱
            helper.setTo(to);//接收邮箱
            helper.setSubject(subject);//邮件主题
            helper.setText(text, true);//邮件内容

            // 创建一个 FileSystemResource 对象,表示给定的资源文件
            FileSystemResource res = new FileSystemResource(new File(rscPath));
            helper.addInline(rscId, res);//添加附件,将rscId和res附件联系一起
            FileSystemResource res2 = new FileSystemResource(new File(rscPath2));
            helper.addInline(rscId2, res2);//添加附件,将rscId和res附件联系一起

            FileSystemResource file = new FileSystemResource(new File(filePath));
            //截取文件名
            String fileName = filePath.substring(filePath.lastIndexOf(File.separator));
            helper.addAttachment(fileName, file);
           
            javaMailSender.send(message);//发送邮件

            System.out.println("复杂邮件发送成功");
        } catch (MessagingException e) {
            System.out.println("复杂邮件发送失败 " + e.getMessage());
            e.printStackTrace();
        }
    }

控制层

/**
     * 邮件任务(复杂邮件)
     * @return
     */
    @RequestMapping("/text4")
    public String sendEmail2(){
        String to  = "3451866342@qq.com";
        String subject  = "冯怡然-22610302150754";//标题
        StringBuilder builder = new StringBuilder();//页面
        builder.append("<html><head></head>");
        builder.append("<body><h1>今日农历二月十七日</h1>");
        builder.append("<body><h1>甲辰龙年-丁卯月-己丑日</h1>");
        String rscId = "img001";//图片id
        builder.append("<img src='cid:img001'/>");
        String rscPath = "C:\\Users\\Lenovo\\Desktop\\1.jpg";//图片路径
        String rscId2 = "img002";
        builder.append("<img src='cid:img002'/>");
        String rscPath2 = "C:\\Users\\Lenovo\\Desktop\\2.jpg";
        builder.append("<h3 color='red'>相信科学</h3>");
        builder.append("</body>");
        builder.append("</html>");
        String filePath = "E:\\Typora\\导出文件\\SpringBoot3的RabbitMQ消息服务.pdf";//文件路径
        sendEmailService.MailEmail(to, subject, builder.toString(), filePath,rscId, rscId2,rscPath, rscPath2);
        return "已发送完成";
    }

效果

32ed7792a647447c813edea58f376232.png

3bff79df5f5842d9b2ef6dd7f7f8b94a.png

 

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

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

相关文章

如何选择指纹浏览器?盘点好用是防关联浏览器

在网络世界中&#xff0c;保护您的在线隐私和安全非常重要。反检测浏览器是专门为此诞生的工具&#xff0c;旨在通过更改浏览器指纹来帮助您做到这一点&#xff0c;它们使网站、广告商和其他人很难跟踪您的在线行为。 一、什么是反检测浏览器&#xff1f; 您是否想过网站如何检…

PCD3012五通道高功率因数LED控制芯片,集成700V高压MOSFET 低THD 外围极少元件

概述 PCD 3012B 是一款五段低 THD 、高功率因数 LED 线性恒流控制芯片&#xff0c;芯片集成了 700V 高压 MOSFET &#xff0c;采用独特创新的器件工艺技术&#xff0c;具有优越的抗雪崩击穿及浪涌能力&#xff0c;在外围无保护器件时可通过650V 雷击浪涌测试&#xff0c;内置…

实验7 内置对象response

编写代码&#xff0c;掌握request、response的用法。【参考课本4.6.2】 三、源代码以及执行结果截图&#xff1a; input.jsp <% page language"java" contentType"text/html; charsetutf-8" pageEncoding"utf-8"%> <!DOCTYPE html>…

重学SpringBoot3-SpringBoot可执行JAR的原因

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-SpringBoot可执行JAR的原因 Spring Boot可执行JAR的结构打包运行JAR 包内部结构 工作原理优点总结 Spring Boot 的一个核心特性是它的可执行 JAR&#x…

在word中显示Euclid Math One公式的问题及解决(latex公式,无需插件)

问题&#xff1a;想要在word中显示形如latex中的花体字母 网上大多解决办法是安装Euclid Math One。安装后发现单独的符号插入可行&#xff0c;但是公式中选择该字体时依然显示默认字体。 解决办法&#xff1a;插入公式后&#xff0c;勾选左上角的latex 在公式块中键入latex代码…

在宝塔面板中,为自己的云服务器安装SSL证书,为所搭建的网站启用https(主要部分攻略)

前提条件 My HTTP website is running Nginx on Debian 10&#xff08;或者11&#xff09; 时间&#xff1a;2024-3-28 16:25:52 你的网站部署在Debain 10&#xff08;或者11&#xff09;的 Nginx上 安装单域名证书&#xff08;默认&#xff09;&#xff08;非泛域名&#xf…

Tensorflow2.0笔记 - metrics做损失和准确度信息度量

本笔记主要记录metrics相关的内容&#xff0c;详细内容请参考代码注释&#xff0c;代码本身只使用了Accuracy和Mean。本节的代码基于上篇笔记FashionMnist的代码经过简单修改而来&#xff0c;上篇笔记链接如下&#xff1a; Tensorflow2.0笔记 - FashionMnist数据集训练-CSDN博…

Codeforces Round 937 (Div. 4)

A. Stair, Peak, or Neither?&#xff08;模拟&#xff09; #include<iostream> using namespace std;int main(){int t;scanf("%d", &t);int a, b, c;while(t--){scanf("%d%d%d", &a, &b, &c);if(a < b && b < c) p…

(免费分享)基于微信小程序电影院购票系统带论文

基于小程序的电影院购票管理系统【含报告】&#xff1a;前端 vue、elementui、小程序&#xff0c;后端 maven、springboot、springmvc、spring、mybatis&#xff0c;角色分为管理员、用户&#xff1b;集成小程序浏览电影&#xff0c;购票等功能于一体的系统。 目录 摘要 I Ab…

fpga 通过axi master读写PS侧DDR的仿真和上板测试

FPGA和ARM数据交互是ZYNQ系统中非常重要的内容。PS提供了供FPGA读写的AXI-HP接口用于两者的高速通信和数据交互。一般的&#xff0c;我们会采用AXI DMA的方式去传输数据&#xff0c;DMA代码基本是是C编写&#xff0c;对于FPGA开发者来说不利于维护和debug。本文提供一种手写AXI…

系统分析师-数学与经济管理

系统架构设计师 系统架构设计师-软件开发模型总结 文章目录 系统架构设计师前言一、最小生成树二、最短路径三、网络与最大流量四、不确定型决策 前言 数学是一种严谨、缜密的科学&#xff0c;学习应用数学知识&#xff0c;可以培养系统架构设计师的抽象思维能力和逻辑推理能…

【WebJs 爬虫】逆向进阶技术必知必会

前言 在数字化时代&#xff0c;网络爬虫已成为一种强大的数据获取工具&#xff0c;广泛应用于市场分析、竞争对手研究、舆情监测等众多领域。爬虫技术能够帮助我们快速、准确地获取网络上的海量信息&#xff0c;为决策提供有力支持。然而&#xff0c;随着网络环境的日益复杂和…

基于vue的MOBA类游戏攻略分享平台的设计与实现|Springboot+Vue+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)

本项目包含可运行源码数据库LW&#xff0c;文末可获取本项目的所有资料。 推荐阅读100套最新项目持续更新中..... 2024年计算机毕业论文&#xff08;设计&#xff09;学生选题参考合集推荐收藏&#xff08;包含Springboot、jsp、ssmvue等技术项目合集&#xff09; 目录 1. …

istio 设置 istio-proxy sidecar 的 resource 的 limit 和 request

方式一 修改 configmap 查看当前 sidecar 的 cpu 和 memory 的配额 在 istio-sidecar-injector 中查找&#xff0c;修改后重启 pod 可以生效&#xff08;下面那个 proxy_init 配置不管&#xff0c;不知道是干嘛的&#xff09; 方式二 如果是通过 iop 安装的 istio&#xf…

连同网络的操作次数【并查集】

用以太网线缆将 n 台计算机连接成一个网络&#xff0c;计算机的编号从 0 到 n-1。线缆用 connections 表示&#xff0c;其中 connections[i] [a, b] 连接了计算机 a 和 b。 网络中的任何一台计算机都可以通过网络直接或者间接访问同一个网络中其他任意一台计算机。 给你这个…

那些激励你深入研究技术的语录

遇到耗时高的问题&#xff0c;90%能用重启解决&#xff0c;但是不找到原因&#xff0c;问题一定会再次出现。 代码里的Bug就像房间里的老鼠&#xff0c;你不找到它&#xff0c;它就会一直捣乱。 代码的质量决定了程序的稳定性&#xff0c;而程序的稳定性则决定了业务的成败。 不…

python程序如何工作

随着人工智能时代的来临&#xff0c;python成为了人们学习编程的首先语言。那么&#xff0c;python程序怎么运行的?我们下面来介绍下。 python程序执行原理 我们都知道&#xff0c;使用C&#xff0c;C之类的编译性语言编写的程序&#xff0c;是需要从源文件转换成计算机使用…

SAP FIORI App

什么是SAP FIORI App SAP FIORI是SAP公司推出的一套用户体验(UX)设计系统。 SAP Fiori不仅仅是一个产品&#xff0c;而是一个用户体验和用户交互的标准。它提供了一套基于HTML5的应用程序&#xff0c;这些应用程序可以运行在所有桌面和移动平台上&#xff0c;包括Windows、Ma…

HarmonyOS 应用开发之ExtensionAbility组件

ExtensionAbility组件是基于特定场景&#xff08;例如服务卡片、输入法等&#xff09;提供的应用组件&#xff0c;以便满足更多的使用场景。 每一个具体场景对应一个 ExtensionAbilityType&#xff0c;开发者只能使用&#xff08;包括实现和访问&#xff09;系统已定义的类型。…

「JavaSE」Lambda表达式

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;快来卷Java啦 &#x1f387;欢迎点赞收藏加关注哦&#xff01; Lambda表达式 &#x1f349;简介&#x1f349;函数式接口&#x1f34c;注解 &#x1f349;语法&#x1f349;Lambda表达式的基本…