2

我正在构建命令行 Java 应用程序,但在使用 Apache Commons CLI 解析命令行参数时遇到问题。

我试图涵盖我的场景,其中我需要两个具有长 (- -abc) 和短 ( -a) 参数的专有命令行参数组。

用例 1

  • 短参数:-d oracle -j jdbc:oracle:thin:@//host:port/databa
  • 相同但参数长:-dialect oracle -jdbcUrl jdbc:oracle:thin:@//host:port/databa

用例 2:

  • 短参数:-d oracle -h host -p 1521 -s database -U user -P pwd
  • 相同但参数长:-dialect oracle -host host -port 1521 -sid database -user user -password pwd

所以我OptionGroup用正确的Option项目创建了两个:

OptionGroup jdbcUrlGroup = new OptionGroup();
jdbcUrlGroup.setRequired(true);
jdbcUrlGroup.addOption(jdbcUrl);

第二组:

OptionGroup customConfigurationGroup = new OptionGroup();
customConfigurationGroup.setRequired(true);
customConfigurationGroup.addOption(host);
customConfigurationGroup.addOption(port);
customConfigurationGroup.addOption(sid);
customConfigurationGroup.addOption(user);
customConfigurationGroup.addOption(password);

然后我以Options这种方式构建对象:

Options options = new Options();
options.addOptionGroup(jdbcUrlGroup);
options.addOptionGroup(customConfigurationGroup);
options.addOption(dialect);

但这不起作用,因为它希望定义这两个组。

方言Option是这样定义的:

Option dialect = Option
        .builder("d")
        .longOpt("dialect")
        .required(false)
        .hasArg()
        .argName("DIALECT")
        .desc("supported SQL dialects: oracle. Default value: oracle")
        .build();

Option除了这个属性之外,其他强制性定义看起来相似:

.required(true)

结果:

  • -d oracle:缺少必需的选项:[-j ...]、[-h ...、-p ...、-s ...、-U ...、-P ...]
  • -d oracle -jdbcUrl xxx:缺少必需的选项:[-h ...,-p ...,-s ...,-U ...,-P ...]
  • -d oracle -h yyy:缺少必需选项:[-j ...]

但我想要的是以下内容:如果提供了 JDBC URL,则不需要主机、端口等参数,或者相反。

4

1 回答 1

1

我认为是时候忘记Apache Commons CLI并将其标记为已弃用的库了。好的,如果您只有几个命令行参数,那么您可以使用它,否则最好不要使用。事实上,这个 Apache 项目最近更新(2019 年 2 月 17 日),但仍然缺少许多功能,并且使用 Apache Commons CLI 库有点痛苦。

picocli项目看起来更适合解析命令行参数它是一个非常直观的库,易于使用,并且还有一个很好且全面的文档。我认为具有完美文档的中等评价工具比没有任何文档的闪亮项目要好。

不管怎样picocli,它是一个非常好的库,有完美的文档,所以我给它加倍加分:)

这就是我如何涵盖我的用例picocli

import picocli.CommandLine;
import picocli.CommandLine.ArgGroup;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;

@Command(name = "SqlRunner",
        sortOptions = false,
        usageHelpWidth = 100,
        description = "SQL command line tool. It executes the given SQL and show the result on the standard output.\n",
        parameterListHeading = "General options:\n",
        footerHeading = "\nPlease report issues at arnold.somogyi@gmail.com.",
        footer = "\nDocumentation, source code: https://github.com/zappee/sql-runner.git")
public class SqlRunner implements Runnable {

    /**
     * Definition of the general command line options.
     */
    @Option(names = {"-?", "--help"}, usageHelp = true, description = "Display this help and exit.")
    private boolean help;

    @Option(names = {"-d", "--dialect"}, defaultValue = "oracle", showDefaultValue = CommandLine.Help.Visibility.ALWAYS, description = "Supported SQL dialects: oracle.")
    private static String dialect;

    @ArgGroup(exclusive = true, multiplicity = "1", heading = "\nProvide a JDBC URL:\n")
    MainArgGroup mainArgGroup;

    /**
     * Two exclusive parameter groups:
     *    (1) JDBC URL parameter
     *    (2) Custom connection parameters
     */
    static class MainArgGroup {
        /**
         * JDBC URL option (only one parameter).
         */
        @Option(names = {"-j", "--jdbcUrl"}, arity = "1", description = "JDBC URL, example: jdbc:oracle:<drivertype>:@//<host>:<port>/<database>.")
        private static String jdbcUrl;

        /**
         * Custom connection parameter group.
         */
        @ArgGroup(exclusive = false, multiplicity = "1", heading = "\nCustom configuration:\n")
        CustomConfigurationGroup customConfigurationGroup;
    }

    /**
     * Definition of the SQL which will be executed.
     */
    @Parameters(index = "0", arity = "1", description = "SQL to be executed. Example: 'select 1 from dual'")
    String sql;

    /**
     * Custom connection parameters.
     */
    static class CustomConfigurationGroup {
        @Option(names = {"-h", "--host"}, required = true, description = "Name of the database server.")
        private static String host;

        @Option(names = {"-p", "--port"}, required = true, description = "Number of the port where the server listens for requests.")
        private static String port;

        @Option(names = {"-s", "--sid"}, required = true, description = "Name of the particular database on the server. Also known as the SID in Oracle terminology.")
        private static String sid;

        @Option(names = {"-U", "--user"}, required = true, description = "Name for the login.")
        private static String user;

        @Option(names = {"-P", "--password"}, required = true, description = "Password for the connecting user.")
        private static String password;
    }

    /**
     * The entry point of the executable JAR.
     *
     * @param args command line parameters
     */
    public static void main(String[] args) {
        CommandLine cmd = new CommandLine(new SqlRunner());
        int exitCode = cmd.execute(args);
        System.exit(exitCode);
    }

    /**
     * It is used to create a thread.
     */
    @Override
    public void run() {
        int exitCode = 0; //executeMyStaff();
        System.exit(exitCode);
    }
}

这就是生成的帮助的样子:

$ java -jar target/sql-runner-1.0-shaded.jar --help
Usage: SqlRunner [-?] [-d=<dialect>] (-j=<jdbcUrl> | (-h=<host> -p=<port> -s=<sid> -U=<user>
                 -P=<password>)) <sql>
SQL command line tool. It executes the given SQL and show the result on the standard output.

General settings:
      <sql>                 SQL to be executed. Example: 'select 1 from dual'
  -?, --help                Display this help and exit.
  -d, --dialect=<dialect>   Supported SQL dialects: oracle.
                              Default: oracle

Custom configuration:
  -h, --host=<host>         Name of the database server.
  -p, --port=<port>         Number of the port where the server listens for requests.
  -s, --sid=<sid>           Name of the particular database on the server. Also known as the SID in
                              Oracle terminology.
  -U, --user=<user>         Name for the login.
  -P, --password=<password> Password for the connecting user.

Provide a JDBC URL:
  -j, --jdbcUrl=<jdbcUrl>   JDBC URL, example: jdbc:oracle:<drivertype>:@//<host>:<port>/<database>.

Please report issues at arnold.somogyi@gmail.com.
Documentation, source code: https://github.com/zappee/sql-runner.git

这种外观比 Apache CLI 生成的帮助要好得多。

于 2020-07-09T21:12:27.447 回答