首页 > 解决方案 > 如何在重新启动时恢复 Java 命令行工具的执行

问题描述

我正在开发一个 Java 命令行工具,其工作原理如下:

  1. 下载一个文件(其中包含一些键/值对数据)
  2. 处理整个文件并将键/值对存储在内存中的 TreeMap 中(按键排序)。
  3. 遍历 TreeMap 并将每个键/值映射条目传递给外部库。因此,基本上它的工作是按“键”对键/值条目进行排序,然后将它们传递给外部方法。
Sample file content (key-value pairs in JSON):
[{   
      "key" : 2
      "value" : "version2Content"
 },
 {   
      "key" : 1
      "value" : "version1Content"
 }, 
 {   
      "key" : 3
      "value" : "version3Content"
 }]

CLI 工具中的伪代码:

List<VersionPair> pairs = getVersionPairsFromJSON(input); 

TreeMap<Long, String> orderedEntries = new TreeMap<>();

for (VersionPair pair : pairs) {
    orderedEntries.put(pair.getKey(), pair.getVersionContent());
}

for (Map.Entry<Long, String> entry : orderedEntries) {
    externalMethod.sendVersion(entry.getKey(), entry.getValue())
        .whenComplete((metadata, error) -> {
            if (error != null) {
                System.err.println("Failed to send Version with key: " + entry.getKey() + ", with content: " + entry.getKey());
            }
        });
}

// POJO for VersionPair
public class VersionPair {
    Long key;
    String versionContent;
    ...
    // constructor, getters and setters
}
public CompletableFuture<Metadata> externalMethod(Long key, String versionContent);

在这里,调用的顺序externalMethod应该严格基于keysJSON 文件中的排序顺序(由于我的应用程序的性质)。例如:

externalMethod.sendVersion(1, "version1Content");
externalMethod.sendVersion(2, "version2Content");
externalMethod.sendVersion(3, "version3Content");

我想知道是否可以从它停止的地方恢复执行该工具,以防由于某种原因终止执行。(例如,用户按 Ctrl+C)。假设文件内容保持不变。

我的用例还要求对于给定的键/值对,不能多次调用外部库方法。因此,如果程序在为某些键/值对调用外部库后停止,我需要从程序停止的地方恢复,而不是重新开始。

是否可以使用 Java 命令行工具实现此行为?如果没有,我可以知道我们还有哪些其他选择可以实现这一目标?

提前致谢!

标签: javacommand-line-interfaceresumeapplication-restart

解决方案


我猜您的用例是您想为最终用户构建一个命令行应用程序以将数据提交到外部系统。

为了实现“恢复”过程,这就需要“持久化”存储来记住它“停止”的时间点。

因此,您可能需要包含“基于文件”的数据库,例如 H2、HSQL 等或使用简单的文本文件,以记住哪些记录已被处理。

假设你的命令行是这样的:java -jar app.jar data1.json,那么在你的程序中可能会立即创建一个 data1-inprogress.dat 文件。然后写下您已成功处理外部方法的每条记录。

因此,如果应用程序被中断,并且用户重新运行相同的命令,您的程序可以确定任何 data1.json 有 data1-inprogress.dat 表示未完成。然后您可以开始编写 data1.json 和 dat1-inprogress.dat 之间的所有条件语句,以确保您的程序不会重新处理旧数据。


推荐阅读