0

我使用 picocli,我想构建 cli 从数据库中获取数据并将其发送到另一个服务。所以我配置看起来像

object Student : Table("student") {
    val id = integer("student_id").autoIncrement().primaryKey()
    val name = varchar("name", 50)
    val grade = integer("grade")
}

class App() : Callable<Integer> {
    @CommandLine.Option(names = ["-ho", "--host"], description = arrayOf("Host database"), defaultValue = "localhost")
    var host: String? = null

    @CommandLine.Option(names = ["-p", "--port"], description = arrayOf("port database"), defaultValue = "5432")
    var port: String? = null

    @CommandLine.Option(names = ["-d", "--database"], description = arrayOf("database"), defaultValue = "postgres")
    var database: String? = null

    @CommandLine.Option(names = ["-u", "--username"], description = arrayOf("username of database"), defaultValue = "postgres")
    var username: String? = null

    @CommandLine.Option(names = ["-w", "--password"], description = arrayOf("password off database"), defaultValue = "password")
    var password: String? = null

    override fun call(): Integer {
       connectDB()
       createStudent()
       return Integer(0)
    }

    fun createStudent() {
        println("Begin create student")
        transaction {
            create(Student)
        }
        println("End create student")
    }

    fun connectDB() {
        try {
            Database.connect("jdbc:postgresql://${this.host}:${this.port}/${this.database}", "org.postgresql.Driver",this.username.toString(),this.password.toString())
            print("Connect db")
        } catch (e : Exception) {
            println("Connect db fail with error ${e.message}")
        }
    }
}

fun main(args: Array<String>) {
    val existCode = CommandLine(App()).execute(*args)
    System.exit(existCode);
}

当我执行时,它连接成功。但我不想从 args 解析值。我想从我的文件属性示例中读取:db.propertiesdb.yml。怎么做?

我搜索了文档 picocli,但找不到任何内容。所以现在我在我的 postgres 中使用 org.jetbrains.exposed:exposed crud。它可以与 picoli 一起使用吗?如果从数据库中获取数据并将其发送到另一个 api,是否有任何建议的框架?非常感谢

4

1 回答 1

1

您提到的要求是一种常见的 CLI 设计模式:用户可以在命令行或配置文件中指定值(或两者,在这种情况下,命令行会覆盖配置文件)。

在 picocli 中,实现这一点的最简单方法是使用默认提供程序:如果未在命令行上指定该值,则从该默认提供程序获取该值。

您的默认提供程序实现可以从属性文件或 yaml 文件中读取,这完全取决于您。

例如:

@Command(name = "db", defaultValueProvider = MyDefaultProvider.class)
class App() : Callable<Integer> {
   // ...
}

class MyDefaultProvider implements picocli.CommandLine.IDefaultValueProvider {
    public String defaultValue(ArgSpec argSpec) throws Exception {
        // read db.properties (or db.yml or something) from some location
        Properties defaultValues = readProperties();

        // return the default value for the argument
        if (argSpec.isOption()) {
            OptionSpec option = (OptionSpec) argSpec;
            return defaultValues.getProperty(option.longestName());
        }
    }

    private Properties readProperties() throws IOException {
        //...
    }
}

Picocli 还提供了一个内置的PropertiesDefaultProvider.${COMMAND-NAME}.properties实现,它在用户主目录中查找一个名为的文件,其中${COMMAND-NAME}是命令的名称。(在您的示例中,App该类没有@Command(name = "xxx")注释,如果您选择使用内置的 .,您可能需要添加它PropertiesDefaultProvider。)

于 2021-04-23T07:05:51.793 回答