java 中解析控制台命令的优雅方式

Elegant way to parse console commands in java

所以我正在制作一个通过控制台命令工作的应用程序(想想 "database new db_name")。处理这种事情最优雅的方法是什么?

这是我的小原型,基本上只有大量的开关。我的意思是它可以工作,但是一旦我想添加一些东西,比如如果你传递了一个错误的参数或太少的参数,它就会变得有点混乱,所以我想知道是否有更好的选择:

public static void main(String[] args) {
    while (running) {
        Scanner in = new Scanner(System.in);
        String cmd = in.nextLine();

        parseCmd(cmd);
    }
}

private static void parseCmd(String s) {
    String[] cmd = s.split(" ");
    try {
        switch (cmd[0]) {
            case "exit":
                running = false;
                System.out.println("Shutting down...");
                break;

            case "database":
                switch (cmd[1]) {
                    case "new":
                        databases.add(new Database(cmd[2]));
                        break;

                    default:
                        System.out.println("Unknown parameter");
                        break;
                }
                break;

            default:
                System.out.println("Unknown command");
                break;
        }
    } catch (Exception ArrayIndexOutOfBoundsException) {
        System.out.println("Too few arguments passed");
    }
}

也许你可以使用一个库来为你做很多这些命令解析,比如 joptsimple?

我不知道优雅的方式,但我已经做过几次这样的事情并想出了这个解决方案。

为代表命令的 "database" 创建一个 class,一旦找到字符串 "database",您将检索此 class 的实例并将剩余的传递给它参数,因此它可以进行其余的解析。

class DataBaseCommand implements Command {
    @Override
    public void eval(String[] args) {...}
}

然后您可以将这些命令的静态映射映射到它们的名称:

private static final Map<String, Command> commands = new HashMap<>();

static {
    commands.put("database", new DataBaseCommand());
}
switch (cmd[0]) {
    case "exit":
        running = false;
        System.out.println("Shutting down...");
        break;
    default:
        if(commands.contains(cmd[0])) {
            commands.get(cmd[0]).eval(cmd);
        } else {
            System.out.println("Unknown command");
        }
        break;
}

我建议使用http://jcommander.org/。它简单而优雅。在其中您可以使用内置注释 例如使用 jcommander annotaions

创建一个像这样的 class
@Parameters(commandNames = {"test", "Manages dates"})
public class CommandOption {

    @Parameter(names = {"-e", "--exit"}, description = "bla bla")
    public boolean exit = false;


}

then in main method 


      public static void main(String... args){

        CommandOption opt = new CommandOption();
            JCommander jc = new JCommander(opt);

            jc.parse(args);

    //and now use 
      System.out.println("value" +opt.exit)
    }

然后可以将参数作为 java class-e true 或者如果你可以创建 jar 然后 java -jar 'jar' -e true

可能更好