直接复制粘贴既可!!
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 环境下