用java8在linux上建一个springboot应用根据传递报文参数多个路径和文件名称执行对应的监听方法,例如同时监听/data/file/1.txt,/var/log/2/txt等多个路径,监听频率是一直监听每秒级别,如果某个路径文件txt有了就copy到另一个目录中,监听这个目录文件任务就结束继续监听其他目录文件,启动监听任务和停止监听任务通过接口控制
要在Java 8和Linux上使用Spring Boot构建一个文件监听应用,你可以按照以下步骤进行。这个应用将监听多个目录的文件变化,如果发现文件,就将其复制到另一个目录,然后停止对该目录的监听。
-
创建Spring Boot项目:
首先,使用Spring Initializr创建一个Spring Boot项目,选择依赖项为
Spring Web
和Spring Boot Actuator
(可选,用于监控应用)。 -
配置
pom.xml
:在生成的Spring Boot项目的
pom.xml
文件中,添加必要的依赖项:<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies>
-
创建文件监听服务:
使用
java.nio.file
包中的WatchService
来实现文件监听。我们创建一个服务类来管理文件监听任务。package com.example.filewatcher; import org.springframework.stereotype.Service; import java.io.IOException; import java.nio.file.*; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; @Service public class FileWatcherService { private final Map<String, Future<?>> watchTasks = new HashMap<>(); private final ExecutorService executor = Executors.newCachedThreadPool(); public void startWatching(String path, String destDir) { if (watchTasks.containsKey(path)) { System.out.println("Already watching this path: " + path); return; } Future<?> future = executor.submit(() -> { try (WatchService watchService = FileSystems.getDefault().newWatchService()) { Path dir = Paths.get(path).getParent(); dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE); while (true) { WatchKey key; try { key = watchService.take(); } catch (InterruptedException ex) { return; } for (WatchEvent<?> event : key.pollEvents()) { WatchEvent.Kind<?> kind = event.kind(); if (kind == StandardWatchEventKinds.OVERFLOW) { continue; } WatchEvent<Path> ev = (WatchEvent<Path>) event; Path fileName = ev.context(); if (fileName.toString().equals(Paths.get(path).getFileName().toString())) { Files.copy(dir.resolve(fileName), Paths.get(destDir).resolve(fileName), StandardCopyOption.REPLACE_EXISTING); System.out.println("File copied to " + destDir); return; } } boolean valid = key.reset(); if (!valid) { break; } } } catch (IOException e) { e.printStackTrace(); } }); watchTasks.put(path, future); System.out.println("Started watching: " + path); } public void stopWatching(String path) { Future<?> future = watchTasks.remove(path); if (future != null) { future.cancel(true); System.out.println("Stopped watching: " + path); } else { System.out.println("No watch task found for: " + path); } } }
-
创建REST控制器:
创建一个REST控制器来启动和停止文件监听任务。
package com.example.filewatcher; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/file-watcher") public class FileWatcherController { private final FileWatcherService fileWatcherService; @Autowired public FileWatcherController(FileWatcherService fileWatcherService) { this.fileWatcherService = fileWatcherService; } @PostMapping("/start") public String startWatching(@RequestParam String path, @RequestParam String destDir) { fileWatcherService.startWatching(path, destDir); return "Started watching: " + path; } @PostMapping("/stop") public String stopWatching(@RequestParam String path) { fileWatcherService.stopWatching(path); return "Stopped watching: " + path; } }
-
运行应用:
使用Spring Boot的典型方式运行应用,在项目根目录运行以下命令:
sh
./mvnw spring-boot:run
-
测试API:
使用
curl
或 Postman 测试你的API。-
启动文件监听任务:
curl -X POST "http://localhost:8080/file-watcher/start?path=/data/file/1.txt&destDir=/target/dir"
-
停止文件监听任务:
curl -X POST "http://localhost:8080/file-watcher/stop?path=/data/file/1.txt"
-
这个应用通过REST API来启动和停止文件监听任务,并在检测到指定文件时将其复制到目标目录。
用java8在linux上建一个springboot应用通过调用方法开启监听,监听的参数多是个目录下的文件,例如同时监听/data/file/fileName1.txt,/var/log/filename2.txt等多个路径,监听频率是一直监听每秒级别,如果某个路径文件1.txt有了就copy到另一个目录中,监听这个目录文件任务就结束继续监听其他目录文件,启动监听任务和停止监听任务通过接口控制
为了满足你的要求,我们可以实现一个Spring Boot应用,其中包含一个服务来管理文件监听任务,并提供REST接口来启动和停止监听任务。具体步骤如下:
-
创建Spring Boot项目: 使用Spring Initializr生成一个Spring Boot项目,选择
Spring Web
依赖。 -
配置
pom.xml
: 在项目的pom.xml
文件中添加必要的依赖:<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
-
创建文件监听服务: 使用
java.nio.file
包中的WatchService
实现文件监听。创建一个服务类来管理文件监听任务。package com.example.filewatcher; import org.springframework.stereotype.Service; import java.io.IOException; import java.nio.file.*; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; @Service public class FileWatcherService { private final Map<String, Future<?>> watchTasks = new HashMap<>(); private final ExecutorService executor = Executors.newCachedThreadPool(); public void startWatching(String path, String destDir) { if (watchTasks.containsKey(path)) { System.out.println("Already watching this path: " + path); return; } Future<?> future = executor.submit(() -> { try (WatchService watchService = FileSystems.getDefault().newWatchService()) { Path dir = Paths.get(path).getParent(); dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE); while (true) { WatchKey key; try { key = watchService.take(); } catch (InterruptedException ex) { return; } for (WatchEvent<?> event : key.pollEvents()) { WatchEvent.Kind<?> kind = event.kind(); if (kind == StandardWatchEventKinds.OVERFLOW) { continue; } WatchEvent<Path> ev = (WatchEvent<Path>) event; Path fileName = ev.context(); if (fileName.toString().equals(Paths.get(path).getFileName().toString())) { Files.copy(dir.resolve(fileName), Paths.get(destDir).resolve(fileName), StandardCopyOption.REPLACE_EXISTING); System.out.println("File copied to " + destDir); return; } } boolean valid = key.reset(); if (!valid) { break; } } } catch (IOException e) { e.printStackTrace(); } }); watchTasks.put(path, future); System.out.println("Started watching: " + path); } public void stopWatching(String path) { Future<?> future = watchTasks.remove(path); if (future != null) { future.cancel(true); System.out.println("Stopped watching: " + path); } else { System.out.println("No watch task found for: " + path); } } }
-
创建REST控制器: 创建一个REST控制器来启动和停止文件监听任务。
package com.example.filewatcher; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/file-watcher") public class FileWatcherController { private final FileWatcherService fileWatcherService; @Autowired public FileWatcherController(FileWatcherService fileWatcherService) { this.fileWatcherService = fileWatcherService; } @PostMapping("/start") public String startWatching(@RequestParam String path, @RequestParam String destDir) { fileWatcher
用java8在linux上建一个springboot应用通过调用端口和方法开启监听,监听的参数多是个目录下的文件,例如同时监听/data/file/fileName1.txt,/var/log/filename2.txt等多个路径,监听频率是一直监听每秒级别,如果某个路径文件1.txt有了就copy到另一个目录中,监听这个目录文件任务就结束继续监听其他目录文件,启动监听任务和停止监听任务通过接口控制
要在Java 8和Linux上使用Spring Boot构建一个文件监听应用,通过调用端口和方法来启动和停止文件监听任务,我们可以遵循以下步骤:
-
创建Spring Boot项目: 使用Spring Initializr生成一个Spring Boot项目,选择
Spring Web
依赖。 -
配置
pom.xml
: 在项目的pom.xml
文件中添加必要的依赖:<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
-
创建文件监听服务: 使用
java.nio.file
包中的WatchService
实现文件监听。创建一个服务类来管理文件监听任务。package com.example.filewatcher; import org.springframework.stereotype.Service; import java.io.IOException; import java.nio.file.*; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; @Service public class FileWatcherService { private final Map<String, Future<?>> watchTasks = new HashMap<>(); private final ExecutorService executor = Executors.newCachedThreadPool(); public void startWatching(String path, String destDir) { if (watchTasks.containsKey(path)) { System.out.println("Already watching this path: " + path); return; } Future<?> future = executor.submit(() -> { try (WatchService watchService = FileSystems.getDefault().newWatchService()) { Path dir = Paths.get(path).getParent(); dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE); while (true) { WatchKey key; try { key = watchService.take(); } catch (InterruptedException ex) { return; } for (WatchEvent<?> event : key.pollEvents()) { WatchEvent.Kind<?> kind = event.kind(); if (kind == StandardWatchEventKinds.OVERFLOW) { continue; } WatchEvent<Path> ev = (WatchEvent<Path>) event; Path fileName = ev.context(); if (fileName.toString().equals(Paths.get(path).getFileName().toString())) { Files.copy(dir.resolve(fileName), Paths.get(destDir).resolve(fileName), StandardCopyOption.REPLACE_EXISTING); System.out.println("File copied to " + destDir); return; } } boolean valid = key.reset(); if (!valid) { break; } } } catch (IOException e) { e.printStackTrace(); } }); watchTasks.put(path, future); System.out.println("Started watching: " + path); } public void stopWatching(String path) { Future<?> future = watchTasks.remove(path); if (future != null) { future.cancel(true); System.out.println("Stopped watching: " + path); } else { System.out.println("No watch task found for: " + path); } } }
-
创建REST控制器: 创建一个REST控制器来启动和停止文件监听任务。
package com.example.filewatcher; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/file-watcher") public class FileWatcherController { private final FileWatcherService fileWatcherService; @Autowired public FileWatcherController(FileWatcherService fileWatcherService) { this.fileWatcherService = fileWatcherService; } @PostMapping("/start") public String startWatching(@RequestParam String path, @RequestParam String destDir) { fileWatcherService.startWatching(path, destDir); return "Started watching: " + path; } @PostMapping("/stop") public String stopWatching(@RequestParam String path) { fileWatcherService.stopWatching(path); return "Stopped watching: " + path; } }
-
运行应用: 使用Spring Boot的典型方式运行应用。在项目根目录运行以下命令:
sh
./mvnw spring-boot:run
-
测试API: 使用
curl
或 Postman 测试你的API。-
启动文件监听任务:
curl -X POST "http://localhost:8080/file-watcher/start?path=/data/file/fileName1.txt&destDir=/target/dir"
-
停止文件监听任务:
curl -X POST "http://localhost:8080/file-watcher/stop?path=/data/file/fileName1.txt"
-
代码文件结构
项目的主要文件结构如下:
src
└── main
└── java
└── com
└── example
└── filewatcher
├── FileWatcherApplication.java
├── FileWatcherController.java
└── FileWatcherService.java
主要代码文件
FileWatcherApplication.java:
package com.example.filewatcher;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class FileWatcherApplication {
public static void main(String[] args) {
SpringApplication.run(FileWatcherApplication.class, args);
}
}
FileWatcherService.java:
package com.example.filewatcher;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.nio.file.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@Service
public class FileWatcherService {
private final Map<String, Future<?>> watchTasks = new HashMap<>();
private final ExecutorService executor = Executors.newCachedThreadPool();
public void startWatching(String path, String destDir) {
if (watchTasks.containsKey(path)) {
System.out.println("Already watching this path: " + path);
return;
}
Future<?> future = executor.submit(() -> {
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
Path dir = Paths.get(path).getParent();
dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
while (true) {
WatchKey key;
try {
key = watchService.take();
} catch (InterruptedException ex) {
return;
}
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (kind == StandardWatchEventKinds.OVERFLOW) {
continue;
}
WatchEvent<Path> ev = (WatchEvent<Path>) event;
Path fileName = ev.context();
if (fileName.toString().equals(Paths.get(path).getFileName().toString())) {
Files.copy(dir.resolve(fileName), Paths.get(destDir).resolve(fileName), StandardCopyOption.REPLACE_EXISTING);
System.out.println("File copied to " + destDir);
return;
}
}
boolean valid = key.reset();
if (!valid) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
});
watchTasks.put(path, future);
System.out.println("Started watching: " + path);
}
public void stopWatching(String path) {
Future<?> future = watchTasks.remove(path);
if (future != null) {
future.cancel(true);
System.out.println("Stopped watching: " + path);
} else {
System.out.println("No watch task found for: " + path);
}
}
}
FileWatcherController.java:
package com.example.filewatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/file-watcher")
public class FileWatcherController {
private final FileWatcherService fileWatcherService;
@Autowired
public FileWatcherController(FileWatcherService fileWatcherService) {
this.fileWatcherService = fileWatcherService;
}
@PostMapping("/start")
public String startWatching(@RequestParam String path, @RequestParam String destDir) {
fileWatcherService.startWatching(path, destDir);
return "Started watching: " + path;
}
@PostMapping("/stop")
public String stopWatching(@RequestParam String path) {
fileWatcherService.stopWatching(path);
return "Stopped watching: " + path;
}
}
这个应用通过REST API来启动和停止文件监听任务,并在检测到指定文件时将其复制到目标目录。
上面传递参数时多个path和filename怎么写参数最好时json格式的,在linux上部署
为了让Spring Boot应用接受JSON格式的参数并处理多个路径和文件名,我们需要对REST接口做一些调整,使其能够解析和处理传递的JSON数据。以下是详细的实现步骤:
-
创建Spring Boot项目: 使用Spring Initializr生成一个Spring Boot项目,选择
Spring Web
依赖。 -
配置
pom.xml
: 在项目的pom.xml
文件中添加必要的依赖:<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
-
创建文件监听服务: 使用
java.nio.file
包中的WatchService
实现文件监听。创建一个服务类来管理文件监听任务。package com.example.filewatcher; import org.springframework.stereotype.Service; import java.io.IOException; import java.nio.file.*; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; @Service public class FileWatcherService { private final Map<String, Future<?>> watchTasks = new HashMap<>(); private final ExecutorService executor = Executors.newCachedThreadPool(); public void startWatching(String path, String destDir) { if (watchTasks.containsKey(path)) { System.out.println("Already watching this path: " + path); return; } Future<?> future = executor.submit(() -> { try (WatchService watchService = FileSystems.getDefault().newWatchService()) { Path dir = Paths.get(path).getParent(); dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE); while (true) { WatchKey key; try { key = watchService.take(); } catch (InterruptedException ex) { return; } for (WatchEvent<?> event : key.pollEvents()) { WatchEvent.Kind<?> kind = event.kind(); if (kind == StandardWatchEventKinds.OVERFLOW) { continue; } WatchEvent<Path> ev = (WatchEvent<Path>) event; Path fileName = ev.context(); if (fileName.toString().equals(Paths.get(path).getFileName().toString())) { Files.copy(dir.resolve(fileName), Paths.get(destDir).resolve(fileName), StandardCopyOption.REPLACE_EXISTING); System.out.println("File copied to " + destDir); return; } } boolean valid = key.reset(); if (!valid) { break; } } } catch (IOException e) { e.printStackTrace(); } }); watchTasks.put(path, future); System.out.println("Started watching: " + path); } public void stopWatching(String path) { Future<?> future = watchTasks.remove(path); if (future != null) { future.cancel(true); System.out.println("Stopped watching: " + path); } else { System.out.println("No watch task found for: " + path); } } }
-
创建REST控制器: 创建一个REST控制器来启动和停止文件监听任务,接受JSON格式的参数。
package com.example.filewatcher; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Map; @RestController @RequestMapping("/file-watcher") public class FileWatcherController { private final FileWatcherService fileWatcherService; @Autowired public FileWatcherController(FileWatcherService fileWatcherService) { this.fileWatcherService = fileWatcherService; } @PostMapping("/start") public String startWatching(@RequestBody Map<String, List<String>> pathsAndDestDirs) { List<String> paths = pathsAndDestDirs.get("paths"); List<String> destDirs = pathsAndDestDirs.get("destDirs"); if (paths.size() != destDirs.size()) { return "Error: paths and destDirs must have the same size"; } for (int i = 0; i < paths.size(); i++) { fileWatcherService.startWatching(paths.get(i), destDirs.get(i)); } return "Started watching paths"; } @PostMapping("/stop") public String stopWatching(@RequestBody List<String> paths) { for (String path : paths) { fileWatcherService.stopWatching(path); } return "Stopped watching paths"; } }
-
运行应用: 使用Spring Boot的典型方式运行应用。在项目根目录运行以下命令:
sh
./mvnw spring-boot:run
-
测试API: 使用
curl
或 Postman 测试你的API。-
启动文件监听任务:
curl -X POST -H "Content-Type: application/json" -d '{ "paths": ["/data/file/fileName1.txt", "/var/log/filename2.txt"], "destDirs": ["/target/dir1", "/target/dir2"] }' "http://localhost:8080/file-watcher/start"
-
停止文件监听任务:
curl -X POST -H "Content-Type: application/json" -d '[ "/data/file/fileName1.txt", "/var/log/filename2.txt" ]' "http://localhost:8080/file-watcher/stop"
代码文件结构
-
项目的主要文件结构如下:
src
└── main
└── java
└── com
└── example
└── filewatcher
├── FileWatcherApplication.java
├── FileWatcherController.java
└── FileWatcherService.java
主要代码文件
FileWatcherApplication.java:
package com.example.filewatcher;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class FileWatcherApplication {
public static void main(String[] args) {
SpringApplication.run(FileWatcherApplication.class, args);
}
}
FileWatcherService.java:
package com.example.filewatcher;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.nio.file.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@Service
public class FileWatcherService {
private final Map<String, Future<?>> watchTasks = new HashMap<>();
private final ExecutorService executor = Executors.newCachedThreadPool();
public void startWatching(String path, String destDir) {
if (watchTasks.containsKey(path)) {
System.out.println("Already watching this path: " + path);
return;
}
Future<?> future = executor.submit(() -> {
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
Path dir = Paths.get(path).getParent();
dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
while (true) {
WatchKey key;
try {
key = watchService.take();
} catch (InterruptedException ex) {
return;
}
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (kind == StandardWatchEventKinds.OVERFLOW) {
continue;
}
WatchEvent<Path> ev = (WatchEvent<Path>) event;
Path fileName = ev.context();
if (fileName.toString().equals(Paths.get(path).getFileName().toString())) {
Files.copy(dir.resolve(fileName), Paths.get(destDir).resolve(fileName), StandardCopyOption.REPLACE_EXISTING);
System.out.println("File copied to " + destDir);
return;
}
}
boolean valid = key.reset();
if (!valid) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
});
watchTasks.put(path, future);
System.out.println("Started watching: " + path);
}
public void stopWatching(String path) {
Future<?> future = watchTasks.remove(path);
if (future != null) {
future.cancel(true);
System.out.println("Stopped watching: " + path);
} else {
System.out.println("No watch task found for: " + path);
}
}
}
FileWatcherController.java:
package com.example.filewatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/file-watcher")
public class FileWatcherController {
private final FileWatcherService fileWatcherService;
@Autowired
public FileWatcherController(FileWatcherService fileWatcherService) {
this.fileWatcherService = fileWatcherService;
}
@PostMapping("/start")
public String startWatching(@RequestBody Map<String, List<String>> pathsAndDestDirs) {
List<String> paths = pathsAndDestDirs.get("paths");
List<String> destDirs = pathsAndDestDirs.get("destDirs");
if (paths.size() != destDirs.size()) {
return "Error: paths and destDirs must have the same size";
}
for (int i = 0; i < paths.size(); i++) {
fileWatcherService.startWatching(paths.get(i), destDirs.get(i));
}
return "Started watching paths";
}
@PostMapping("/stop")
public String stopWatching(@RequestBody List<String> paths) {
for (String path : paths) {
fileWatcherService.stopWatching(path);
}
return "Stopped watching paths";
}
}
这个应用通过REST API来启动和停止文件监听任务,并在检测到指定文件时将其复制到目标目录。JSON格式的参数可以很容易地扩展以支持多个路径和文件名。
上面的代码提示Error:(3, 52) java: 无法访问org.springframework.beans.factory.annotation.Autowired 错误的类文件: /D:/tools/repository/org/springframework/spring-beans/6.0.4/spring-beans-6.0.4.jar!/org/springframework/beans/factory/annotation/Autowired.class 类文件具有错误的版本 61.0, 应为 52.0 请删除该文件或确保该文件位于正确的类路径子目录中。
这个错误提示你当前使用的JDK版本与Spring Boot版本不匹配。错误的版本 61.0 对应的是 JDK 17,而 52.0 对应的是 JDK 8。由于你在使用 JDK 8,需要确保使用兼容 JDK 8 的 Spring Boot 版本。
为了解决这个问题,你需要做以下几个步骤:
-
调整Spring Boot版本: 修改
pom.xml
文件中的 Spring Boot 版本,以确保它兼容 JDK 8。Spring Boot 2.5.x 是最后一个支持 JDK 8 的版本。<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.12</version> <relativePath/> <!-- lookup parent from repository --> </parent>
-
确保JDK 8为编译版本: 在
pom.xml
中设置 Maven 编译插件,以确保使用 JDK 8 进行编译。<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>
-
更新项目依赖: 确保项目依赖版本与Spring Boot 2.5.x版本兼容。
以下是调整后的 pom.xml
文件示例:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>file-watcher</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.12</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
文件结构
src
└── main
└── java
└── com
└── example
└── filewatcher
├── FileWatcherApplication.java
├── FileWatcherController.java
└── FileWatcherService.java
代码文件
FileWatcherApplication.java:
package com.example.filewatcher;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class FileWatcherApplication {
public static void main(String[] args) {
SpringApplication.run(FileWatcherApplication.class, args);
}
}
FileWatcherService.java:
package com.example.filewatcher;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.nio.file.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@Service
public class FileWatcherService {
private final Map<String, Future<?>> watchTasks = new HashMap<>();
private final ExecutorService executor = Executors.newCachedThreadPool();
public void startWatching(String path, String destDir) {
if (watchTasks.containsKey(path)) {
System.out.println("Already watching this path: " + path);
return;
}
Future<?> future = executor.submit(() -> {
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
Path dir = Paths.get(path).getParent();
dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
while (true) {
WatchKey key;
try {
key = watchService.take();
} catch (InterruptedException ex) {
return;
}
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (kind == StandardWatchEventKinds.OVERFLOW) {
continue;
}
WatchEvent<Path> ev = (WatchEvent<Path>) event;
Path fileName = ev.context();
if (fileName.toString().equals(Paths.get(path).getFileName().toString())) {
Files.copy(dir.resolve(fileName), Paths.get(destDir).resolve(fileName), StandardCopyOption.REPLACE_EXISTING);
System.out.println("File copied to " + destDir);
return;
}
}
boolean valid = key.reset();
if (!valid) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
});
watchTasks.put(path, future);
System.out.println("Started watching: " + path);
}
public void stopWatching(String path) {
Future<?> future = watchTasks.remove(path);
if (future != null) {
future.cancel(true);
System.out.println("Stopped watching: " + path);
} else {
System.out.println("No watch task found for: " + path);
}
}
}
FileWatcherController.java:
package com.example.filewatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/file-watcher")
public class FileWatcherController {
private final FileWatcherService fileWatcherService;
@Autowired
public FileWatcherController(FileWatcherService fileWatcherService) {
this.fileWatcherService = fileWatcherService;
}
@PostMapping("/start")
public String startWatching(@RequestBody Map<String, List<String>> pathsAndDestDirs) {
List<String> paths = pathsAndDestDirs.get("paths");
List<String> destDirs = pathsAndDestDirs.get("destDirs");
if (paths.size() != destDirs.size()) {
return "Error: paths and destDirs must have the same size";
}
for (int i = 0; i < paths.size(); i++) {
fileWatcherService.startWatching(paths.get(i), destDirs.get(i));
}
return "Started watching paths";
}
@PostMapping("/stop")
public String stopWatching(@RequestBody List<String> paths) {
for (String path : paths) {
fileWatcherService.stopWatching(path);
}
return "Stopped watching paths";
}
}
通过这些步骤,您可以在JDK 8上使用Spring Boot来构建文件监听应用,使用JSON格式的参数来启动和停止文件监听任务。
上面的代码改下目标目录只有一个List<String> destDirs = pathsAndDestDirs.get("destDirs");这里是一个目标目录只有一个,监听的文件都复制到一个目录里
好的,我们可以修改代码,使所有监听的文件都复制到一个目标目录。这里是修改后的代码:
- 更新REST控制器: 修改控制器,使其接受一个目标目录,并将所有监听的文件复制到该目录。
package com.example.filewatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/file-watcher")
public class FileWatcherController {
private final FileWatcherService fileWatcherService;
@Autowired
public FileWatcherController(FileWatcherService fileWatcherService) {
this.fileWatcherService = fileWatcherService;
}
@PostMapping("/start")
public String startWatching(@RequestBody Map<String, Object> pathsAndDestDir) {
List<String> paths = (List<String>) pathsAndDestDir.get("paths");
String destDir = (String) pathsAndDestDir.get("destDir");
for (String path : paths) {
fileWatcherService.startWatching(path, destDir);
}
return "Started watching paths";
}
@PostMapping("/stop")
public String stopWatching(@RequestBody List<String> paths) {
for (String path : paths) {
fileWatcherService.stopWatching(path);
}
return "Stopped watching paths";
}
}
- 更新服务类: 修改服务类,使其将所有监听的文件复制到一个目标目录。
package com.example.filewatcher;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.nio.file.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@Service
public class FileWatcherService {
private final Map<String, Future<?>> watchTasks = new HashMap<>();
private final ExecutorService executor = Executors.newCachedThreadPool();
public void startWatching(String path, String destDir) {
if (watchTasks.containsKey(path)) {
System.out.println("Already watching this path: " + path);
return;
}
Future<?> future = executor.submit(() -> {
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
Path dir = Paths.get(path).getParent();
dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
while (true) {
WatchKey key;
try {
key = watchService.take();
} catch (InterruptedException ex) {
return;
}
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (kind == StandardWatchEventKinds.OVERFLOW) {
continue;
}
WatchEvent<Path> ev = (WatchEvent<Path>) event;
Path fileName = ev.context();
if (fileName.toString().equals(Paths.get(path).getFileName().toString())) {
Files.copy(dir.resolve(fileName), Paths.get(destDir).resolve(fileName), StandardCopyOption.REPLACE_EXISTING);
System.out.println("File copied to " + destDir);
return;
}
}
boolean valid = key.reset();
if (!valid) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
});
watchTasks.put(path, future);
System.out.println("Started watching: " + path);
}
public void stopWatching(String path) {
Future<?> future = watchTasks.remove(path);
if (future != null) {
future.cancel(true);
System.out.println("Stopped watching: " + path);
} else {
System.out.println("No watch task found for: " + path);
}
}
}
- 更新POM文件: 确保Spring Boot版本和编译插件的配置正确。
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>file-watcher</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.12</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
测试API
使用 curl
或 Postman 测试你的API。
-
启动文件监听任务:
curl -X POST -H "Content-Type: application/json" -d '{ "paths": ["/data/file/fileName1.txt", "/var/log/filename2.txt"], "destDir": "/target/dir" }' "http://localhost:8080/file-watcher/start"
-
停止文件监听任务:
curl -X POST -H "Content-Type: application/json" -d '[ "/data/file/fileName1.txt", "/var/log/filename2.txt" ]' "http://localhost:8080/file-watcher/stop"
通过这些步骤,你可以实现一个Spring Boot应用,使用JSON格式的参数来启动和停止文件监听任务,并将所有监听的文件复制到一个目标目录。
上面的代码stop接口改一下调用这个接口停止监听并停止sprintboot服务
为了满足你的需求,可以修改 /stop
接口,使其不仅停止文件监听任务,还停止 Spring Boot 应用程序。我们可以通过调用 SpringApplication.exit()
来实现。
以下是更新后的代码:
FileWatcherController.java:
package com.example.filewatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/file-watcher")
public class FileWatcherController {
private final FileWatcherService fileWatcherService;
private final ApplicationContext appContext;
@Autowired
public FileWatcherController(FileWatcherService fileWatcherService, ApplicationContext appContext) {
this.fileWatcherService = fileWatcherService;
this.appContext = appContext;
}
@PostMapping("/start")
public String startWatching(@RequestBody Map<String, Object> pathsAndDestDir) {
List<String> paths = (List<String>) pathsAndDestDir.get("paths");
String destDir = (String) pathsAndDestDir.get("destDir");
for (String path : paths) {
fileWatcherService.startWatching(path, destDir);
}
return "Started watching paths";
}
@PostMapping("/stop")
public String stopWatching(@RequestBody List<String> paths) {
for (String path : paths) {
fileWatcherService.stopWatching(path);
}
stopApplication();
return "Stopped watching paths and stopping the application";
}
private void stopApplication() {
Thread thread = new Thread(() -> {
try {
Thread.sleep(1000); // Delay to ensure response is sent before shutting down
} catch (InterruptedException e) {
e.printStackTrace();
}
SpringApplication.exit(appContext, () -> 0);
});
thread.setDaemon(false);
thread.start();
}
}
在上述代码中,stopApplication
方法创建了一个新的线程,线程会在一秒钟后调用 SpringApplication.exit
来停止 Spring Boot 应用。这样可以确保HTTP响应在应用停止之前正确发送回客户端。
完整代码示例
FileWatcherApplication.java:
package com.example.filewatcher;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class FileWatcherApplication {
public static void main(String[] args) {
SpringApplication.run(FileWatcherApplication.class, args);
}
}
FileWatcherService.java:
package com.example.filewatcher;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.nio.file.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@Service
public class FileWatcherService {
private final Map<String, Future<?>> watchTasks = new HashMap<>();
private final ExecutorService executor = Executors.newCachedThreadPool();
public void startWatching(String path, String destDir) {
if (watchTasks.containsKey(path)) {
System.out.println("Already watching this path: " + path);
return;
}
Future<?> future = executor.submit(() -> {
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
Path dir = Paths.get(path).getParent();
dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
while (true) {
WatchKey key;
try {
key = watchService.take();
} catch (InterruptedException ex) {
return;
}
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (kind == StandardWatchEventKinds.OVERFLOW) {
continue;
}
WatchEvent<Path> ev = (WatchEvent<Path>) event;
Path fileName = ev.context();
if (fileName.toString().equals(Paths.get(path).getFileName().toString())) {
Files.copy(dir.resolve(fileName), Paths.get(destDir).resolve(fileName), StandardCopyOption.REPLACE_EXISTING);
System.out.println("File copied to " + destDir);
return;
}
}
boolean valid = key.reset();
if (!valid) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
});
watchTasks.put(path, future);
System.out.println("Started watching: " + path);
}
public void stopWatching(String path) {
Future<?> future = watchTasks.remove(path);
if (future != null) {
future.cancel(true);
System.out.println("Stopped watching: " + path);
} else {
System.out.println("No watch task found for: " + path);
}
}
}
FileWatcherController.java:
package com.example.filewatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/file-watcher")
public class FileWatcherController {
private final FileWatcherService fileWatcherService;
private final ApplicationContext appContext;
@Autowired
public FileWatcherController(FileWatcherService fileWatcherService, ApplicationContext appContext) {
this.fileWatcherService = fileWatcherService;
this.appContext = appContext;
}
@PostMapping("/start")
public String startWatching(@RequestBody Map<String, Object> pathsAndDestDir) {
List<String> paths = (List<String>) pathsAndDestDir.get("paths");
String destDir = (String) pathsAndDestDir.get("destDir");
for (String path : paths) {
fileWatcherService.startWatching(path, destDir);
}
return "Started watching paths";
}
@PostMapping("/stop")
public String stopWatching(@RequestBody List<String> paths) {
for (String path : paths) {
fileWatcherService.stopWatching(path);
}
stopApplication();
return "Stopped watching paths and stopping the application";
}
private void stopApplication() {
Thread thread = new Thread(() -> {
try {
Thread.sleep(1000); // Delay to ensure response is sent before shutting down
} catch (InterruptedException e) {
e.printStackTrace();
}
SpringApplication.exit(appContext, () -> 0);
});
thread.setDaemon(false);
thread.start();
}
}
这样,当你调用 /stop
接口时,它会停止监听指定的路径并关闭 Spring Boot 应用程序。