一、Java Api
1. 文件监听
背景:之前第三方系统使用 FTP 传输一些静态资源到服务器的指定文件夹中,包含图片、视频、txt 文本文件。其中需要读取 txt 的文本内容,并将其整理落库。本来想使用 js 脚本处理的,后来领导说尽量写在一起。于是使用该 API 实现。
WatchService 接口可以用来实现对系统的文件进行监听。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| @Test public void watchFileTest() { String path = "D:\\"; try { WatchService watchService = FileSystems.getDefault().newWatchService(); Paths.get(path).register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
while (true) { WatchKey key = watchService.take(); List<WatchEvent<?>> events = key.pollEvents(); events.stream() .filter(e -> Objects.equals(e.kind(), StandardWatchEventKinds.ENTRY_CREATE)) .forEach(e -> { String fileName = e.context().toString(); System.out.println("创建了 [" + fileName + "] 文件"); try { Thread.sleep(100); } catch (InterruptedException ex) { throw new RuntimeException(ex); } }); key.reset(); } } catch (IOException | InterruptedException e) { throw new RuntimeException(e); } }
|
2. ServiceLoader 获取某个接口的所有实现类
Java 6 引入了一个新功能,用于发现和加载与给定接口匹配的实现:Service Provider Interface (SPI)。SPI 的核心是 ServiceLoader 类。它具有延迟发现和加载实现的作用。它使用上下文类路径来查找提供程序实现并将它们放在内部缓存中。可以参见官方文档:https://docs.oracle.com/javase/tutorial/ext/basics/spi.html
1 2 3 4 5
| @Test public void testServiceLoader() { java.util.ServiceLoader<AssetsStrategy> strategies = java.util.ServiceLoader.load(AssetsStrategy.class); strategies.forEach(System.out::println); }
|
当然,如果直接执行以上代码是没有任何打印内容的。因为它还需要一点儿额外的配置。你需要在 resources/META-INF
目录下新建 services
目录,然后在新建的目录中添加一个文件,这个 文件名 必须是接口的 所在包路径+接口名称全限定名称
,不带任何后缀,且区分大小写。最后按照同样的格式把实现了该接口的实现类写到该文件中。
以上面的测试方法举个栗子,AssetsStrategy
是一个接口,该接口位于 com.example.strategy
包,并且它有 Model1
、Model2
两个实现类。在 resources/META-INF/services/com.example.strategy.AssetsStrategy
文件中(该文件必须采用 UTF-8 编码)添加以下内容:
resources/META-INF/services/com.example.strategy.AssetsStrategy1 2
| com.example.model.Model1 com.example.model.Model2
|
然后运行上面的测试代码,就可以看到结果啦~
3. JUC
LockSupport
LockSupport 可以实现线程的阻塞和释放,并且该类对外提供的方法都是静态方法:parkxxx 阻塞线程,unparkxxx 唤醒被阻塞的线程。
4. 树构造
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Data public class Tree { private Integer id;
private Integer parentId;
private String name;
private List<Tree> children = new ArrayList<>(); }
|
1 2 3 4 5 6 7 8 9 10 11 12
| public List<Tree> buildTree() { Map<Long, List<Tree>> target = result.stream() .filter(it -> Objects.nonNull(it.getParentId())) .collect(Collectors.groupingBy(Tree::getParentId));
result.forEach(tree -> { List<Tree> children = target.get(tree.getId()) == null ? Collections.emptyList() : target.get(tree.getId()); tree.setChildren(children); } ); return result.stream().filter(it -> Objects.isNull(it.getParentId())).toList(); }
|
参考 https://juejin.cn/post/7027823030290087973 修改
5. Java 使用 powershell 执行一些命令
某次,需要使用 Java 调用一些本机的命令玩,发现有些命令只能以超级管理员身份运行才有效,下面这个可以使用,但是每次调用会有弹框让用户确认,这个还不知道怎么搞。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| public static void main(String[] args) { System.out.println("Current user: " + System.getProperty("user.name")); System.out.println("Current user: " + System.getProperty("os.name")); String server = "mysql"; String command = "Start-Process powershell -Verb runAs -ArgumentList '-ExecutionPolicy Bypass -Command \"net stop %s && net start %s\"'"; String[] comd = { "powershell", "-ExecutionPolicy", "Bypass", "-Command", String.format(command, server, server), }; ProcessBuilder processBuilder = new ProcessBuilder(comd); processBuilder.redirectErrorStream(true); Charset gbk = Charset.forName("GBK"); Process exec = null; try { exec = processBuilder.start(); } catch (IOException e) { throw new RuntimeException(e); }
try ( BufferedReader reader = new BufferedReader(new InputStreamReader(exec.getInputStream(), gbk)); BufferedReader errorReader = new BufferedReader(new InputStreamReader(exec.getErrorStream(), gbk)); ) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); }
String errorLine; while ((errorLine = errorReader.readLine()) != null) { System.out.println(errorLine); } int exitCode = exec.waitFor(); System.out.println("Process exited with code: " + exitCode); } catch (IOException | InterruptedException e) { throw new RuntimeException(e); } }
|