SpringBoot自定义工具类—基于定时器完成文件清理功能
直接复制粘贴既可!!
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.io.File;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.chrono.ChronoLocalDate;
import java.time.format.DateTimeFormatter;@Component // 表示将该类声明为一个组件,以便能够被Spring容器管理。
public class FileCleanupTask {//@Scheduled(cron = "0 0 0 */3 * ?") // 每隔三天凌晨12点触发任务//@Scheduled(cron = "0 */1 * * * ?") // 每隔一分钟触发任务@Scheduled(cron = "0 */2 * * * *") // 每隔2秒触发任务public void cleanupFiles() {String directoryPath = "/manage/uploadFile"; // 修改为你的上传文件存放的目录路径File directory = new File(directoryPath);// 检查目录是否存在// LocalDateTime twoMinutesAgo就代表了当前时间减去1分钟之后的时间点。这个时间点用于比较文件的创建时间,如果文件的创建时间早于twoMinutesAgo,则会被删除。if (directory.exists() && directory.isDirectory()) {//LocalDate threeDaysAgo = LocalDate.now().minusDays(3);// LocalDateTime.now():获取当前的日期和时间。.minusMinutes(1):通过调用minusMinutes方法,在当前时间基础上减去1分钟。LocalDateTime twoMinutesAgo = LocalDateTime.now().minusMinutes(1);deleteOlderFiles(directory, twoMinutesAgo);}}private void deleteOlderDirectories(File directory, LocalDate threeDaysAgo) {File[] files = directory.listFiles();if (files != null) {for (File file : files) {if (file.isDirectory()) {// 获取文件夹的名称,格式为"yyyy-MM-ddXXX",其中XXX为随机数String folderName = file.getName();String dateString = folderName.substring(0, 10);LocalDate folderDate = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyy-MM-dd"));// 如果文件夹日期早于三天前的日期,则删除文件夹及其内容if (folderDate.isBefore(threeDaysAgo)) {deleteDirectory(file);System.out.println("Deleted directory: " + file.getAbsolutePath());}}}}}private void deleteOlderFiles(File directory, LocalDateTime twoMinutesAgo) {File[] files = directory.listFiles();if (files != null) {for (File file : files) {if (file.isDirectory()) {// 获取文件夹的名称,格式为"yyyy-MM-ddXXX",其中XXX为随机数String folderName = file.getName();String dateString = folderName.substring(0, 10);LocalDate folderDate = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyy-MM-dd"));// 如果文件的创建时间早于两分钟前,则删除文件if (folderDate.isBefore(ChronoLocalDate.from(twoMinutesAgo))) {deleteDirectory(file);System.out.println("Deleted file: " + file.getAbsolutePath());}}}}}private LocalDateTime getCreationDateTime(File file) {long fileTimestamp = file.lastModified();return LocalDateTime.ofEpochSecond(fileTimestamp / 1000, 0, ZoneOffset.UTC);}private void deleteDirectory(File directory) {File[] files = directory.listFiles();if (files != null) {for (File file : files) {if (file.isDirectory()) {deleteDirectory(file);} else {file.delete();}}}directory.delete();}
}
说明:
①、不要自己去写cron表达式,使用在线Cron表达式生成器 (pppet.net)
②、 记得还要在启动类上添加 @EnableScheduling // 启用定时任务,定时删除服务器上的文件
③、注意要删除的文件夹类型(文件夹名称由日期和三位随机数组成,不包含日期删除不了)

④、文件路径的理解
import java.io.File;public class DirectoryExistsTest {public static void main(String[] args) {String directoryPath = "/manage/uploadFile"; // 相对路径File directory = new File(directoryPath);// 判断目录是否存在if (directory.exists() && directory.isDirectory()) {System.out.println("目录 " + directory.getAbsolutePath() + " 存在。");} else {System.out.println("目录 " + directory.getAbsolutePath() + " 不存在或不是一个目录。");}}
}
通过这个测试类可以发现,String directoryPath = "manage/uploadFile";生成的是目录 E:\excelreport\manage\uploadFile 不存在或不是一个目录,但是目录 E:\manage\uploadFile 存在。

其实,manage/uploadFile 是一个相对路径,它相对于当前工作目录。Java程序在执行时,会有一个当前工作目录,这取决于您运行程序所在的位置。例如,如果您的 Java 程序文件位于 E:\excelreport 文件夹下,那么当前工作目录将是 E:\excelreport。
而 /manage/uploadFile 是一个绝对路径,它表示从系统的根目录开始的完整路径。在 Windows 系统中,根目录通常是硬盘的根目录,比如 C:\ 或 D:\,而在 Linux 系统中,根目录表示为 /。
所以,使用相对路径时,它会将当前工作目录与相对路径拼接起来形成完整路径;而使用绝对路径时,它表示从根目录开始的完整路径。
⑤、判读文件目录是否存在 directory.exists() && directory.isDirectory() 的理解
directory.exists()方法用于判断指定的目录是否存在。点击directory.exists()方法的源码可以看到:

首先,通过System.getSecurityManager()方法获取SecurityManager对象,如果存在安全管理器,则调用security.checkRead(path)检查是否具有读取目录的权限。
接下来,调用isInvalid()方法检查当前File对象是否是无效的(例如由于路径名为空等原因)。如果是无效的,则直接返回false表示目录不存在。
然后,通过调用fs.getBooleanAttributes(this)方法获取指定目录的文件系统属性,其中fs为FileSystem对象。获取到的属性值可以使用位掩码进行判断。
最后,将获取到的属性值与FileSystem.BA_EXISTS进行按位与操作,如果结果不为0,则表示目录存在,返回true;否则表示目录不存在,返回false。综上所述,directory.exists()方法通过检查路径的有效性和获取文件系统属性来判断指定的目录是否存在。

同理,isDirectory()方法用于判断当前File对象是否表示一个目录。该方法的实现如下:
首先,通过System.getSecurityManager()方法获取SecurityManager对象,如果存在安全管理器,则调用security.checkRead(path)检查是否具有读取目录的权限。
接下来,调用isInvalid()方法检查当前File对象是否是无效的(例如由于路径名为空等原因)。如果是无效的,则直接返回false表示不是一个目录。
然后,通过调用fs.getBooleanAttributes(this)方法获取当前File对象的文件系统属性,其中fs为FileSystem对象。获取到的属性值可以使用位掩码进行判断。
最后,将获取到的属性值与FileSystem.BA_DIRECTORY进行按位与操作,如果结果不为0,则表示是一个目录,返回true;否则表示不是一个目录,返回false。综上所述,isDirectory()方法通过检查路径的有效性和获取文件系统属性来判断当前File对象是否表示一个目录。
⑤、删除文件(文件夹)方法的理解:
private void deleteDirectory(File directory) {File[] files = directory.listFiles();if (files != null) {for (File file : files) {if (file.isDirectory()) {deleteDirectory(file);} else {file.delete();}}}directory.delete();}
这段代码中使用的是Java中的File类和递归方法来删除指定目录下的所有文件和子目录。
首先,使用绝对路径/manage/uploadFile创建一个File对象表示目录。然后通过directory.exists()和directory.isDirectory()方法判断目录是否存在并且是一个目录。
接下来,使用directory.listFiles()方法获取目录下的所有文件和子目录,返回一个File数组。如果数组不为空,则使用循环遍历数组中的每个元素。
对于每个元素,首先判断是否是一个目录,如果是目录,则递归调用deleteDirectory()方法,传入当前目录作为参数,实现深度优先的删除操作,即先删除子目录中的内容。
如果元素不是目录,而是一个文件,则调用file.delete()方法将该文件删除。
完成对每个文件和子目录的删除后,最后调用directory.delete()方法删除当前目录本身。
通过递归方式删除目录及其子目录中的所有文件和文件夹,确保在删除父目录之前先删除子目录的内容。最终,整个目录结构都会被完全删除。
运行效果:
window环境下

Linux 环境下

相关文章:
SpringBoot自定义工具类—基于定时器完成文件清理功能
直接复制粘贴既可!! import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.io.File; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneOff…...
安卓设置混淆后,gson报错解决方法
一,设置开启混淆release {minifyEnabled truezipAlignEnabled trueshrinkResources trueproguardFiles getDefaultProguardFile(proguard-android-optimize.txt), proguard-rules.pro } 二,混淆的文件中,对gson相关类不进行混淆,否…...
WPF实战项目十四(API篇):登录注册接口
1、新建UserDto.cs public class UserDto : BaseDto{private string userName;/// <summary>/// 用户名/// </summary>public string UserName{get { return userName; }set { userName value;OnPropertyChanged(); }}private string account;/// <summary>…...
10个免费PPT下载资源网站分享
PPT超级市场https://pptsupermarket.com/ PPT超级市场是一个完全免费的PPT模板下载网站,不需要注册登录,点击下载就能直接使用。 叮当设计https://www.dingdangsheji.com/ 叮当设计是一个完全免费的PPT模板下载网站,每一套PPT的质量都很高。除…...
SpringCloud入门——微服务调用的方式 RestTemplate的使用 使用nacos的服务名初步(Ribbon负载均衡)
目录 引出微服务之间的调用几种调用方法spring提供的组件 RestTemplate的使用导入依赖生产者模块单个配置的情况多个配置的情况没加.yaml的报错【报错】两个同名配置【细节】 完整代码config配置主启动类controller层 消费者模块进行配置restTemplate配置类controller层 使用na…...
Python基础篇(16):python中__new__方法
一、__new__方法的定义 __new__() 方法是一种负责创建 类实例 的 静态方法 二、__new__方法的作用 在内存中为对象分配空间返回对象的引用 三、__new__方法的使用 创建对象时自动调用__new__方法,并且是在__init__初始化方法之前被调用Python解释器获得对象的引…...
linux并发服务器 —— 文件IO相关函数(三)
文件IO 以内存为主体,看待输入输出; 标准C库IO函数带有缓冲区,效率较高; 虚拟地址空间 虚拟地址空间是不存在的,一个应用程序运行期间对应一个虚拟地址空间; 虚拟地址空间的大小由CPU决定,位…...
matlab使用教程(27)—微分代数方程(DAE)求解
1.什么是微分代数方程? 微分代数方程是一类微分方程,其中一个或多个因变量导数未出现在方程中。方程中出现的未包含其导数的变量称为代数变量,代数变量的存在意味着您不能将这些方程记为显式形式 y ′ f t , y 。相反,您可以…...
vue3组合式api <script setup> props 父子组件的写法
父组件传入子组个的变量, 子组件是无法直接修改的, 只能通过 emit的方式, 让父组件修改, 之后子组件更新 <template><div class"parent">我是父组件<son :msg"msg" :obj"obj" chan…...
Compose - 自定义作用域限制函数
一、概念 在 Compose 中对于作用域的应用特别多。比如 weight 修饰符只能用在 RowScope 或者 ColumnScope 作用域中,item 组件只能用在 LazyListScope 作用域中。 标准库中的作用域函数如 apply()、let() 会以不同方式持有和返回上下文对象,调用它们时 L…...
【Flutter】Flutter 使用 photo_view 实现图片查看器
【Flutter】Flutter 使用 photo_view 实现图片查看器 文章目录 一、前言二、photo_view 简介三、安装与基本使用四、使用 PhotoViewGallery 展示多张图片五、完整示例六、总结 一、前言 大家好,我是小雨青年,今天我要给大家介绍一个在 Flutter 中非常实…...
电脑组装教程分享!
案例:如何自己组装电脑? 【看到身边的小伙伴组装一台自己的电脑,我也想试试。但是我对电脑并不是很熟悉,不太了解具体的电脑组装步骤,求一份详细的教程!】 电脑已经成为我们日常生活中不可或缺的一部分&a…...
【云原生之Docker实战】使用Docker部署flatnotes笔记工具
【云原生之Docker实战】使用Docker部署flatnotes笔记工具 一、flatnotes介绍1.1 flatnotes简介1.2 flatnotes特点 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、下载flatnotes…...
XSSchallenge1-20
test1 第一题直接在test插入XSS代码即可 test2 第二关对内容进行”“包裹 这里可以采用”>来绕过 test3 代码审计发现这里用了htmlspecialchars函数,这个函数对<>和’ “等进行了转义,这里可以用事件来绕过 test4 这里用了str_replace&a…...
centos 7的超详细安装教程
打开虚拟机,创建一个新电脑 我们选择经典,然后选择下一步 我们选择稍后安装,我们在后面进行改设备 因为centos系统是linux系统的一个版本,所有我们选择linux,版本选择centos 7 64位,然后就是点击下一步 这一…...
代码随想录算法训练营第五十二天 | 300.最长递增子序列,674. 最长连续递增序列,718. 最长重复子数组
代码随想录算法训练营第五十二天 | 300.最长递增子序列,674. 最长连续递增序列,718. 最长重复子数组 300.最长递增子序列674. 最长连续递增序列718. 最长重复子数组 300.最长递增子序列 题目链接 视频讲解 给你一个整数数组 nums ,找到其中最…...
计算机图形软件(三)6-6 小结
小结 这一章概括了图形软件系统的主要特点。某些软件系统,如 CAD 软件包和绘图程序,其为特定应用而设计。另外一些软件系统则提供可以在诸如 C的程序设计语言中使用的一个通用图形子程序库,用来为任何应用生成图片。 ISO和AN…...
Flink常用函数
1、比较函数 <> > > < < 注意:select nullnull; 返回为nullIS NULL 、 IS NOT NULL --非空判断value1 IS DISTINCT FROM value2、value1 IS NOT DISTINCT FROM value2、 --不同于value1 BETWEEN [ ASYMMETRIC | S OR 、AND、NOT boolean…...
stable diffusion实践操作-embedding(TEXTUAL INVERSION)
本文专门开一节写图生图相关的内容,在看之前,可以同步关注: stable diffusion实践操作 可以理解为提示词的集合,可以省略大量的提示词。后缀safetensors,大小几十kb 正文 1、功能 可以理解为提示词的集合࿰…...
代码随想录二刷day03
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、力扣203. 移除链表元素二、力扣707. 设计链表三、力扣206. 反转链表 前言 一、力扣203. 移除链表元素 /*** Definition for singly-linked list.* public…...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
