1. введение
В этом уроке мы представим Airline — управляемую аннотациями библиотеку Java для построения интерфейсов командной строки (CLI).
2. Сценарий
При создании приложения командной строки естественно создать простой интерфейс, позволяющий пользователю формировать выходные данные по мере необходимости. Почти каждый играл с Git CLI и может понять, насколько он мощный, но простой. Увы, немногие инструменты пригодятся при создании такого интерфейса.
Авиакомпания стремится уменьшить шаблонный код , обычно связанный с классом в Java , поскольку наиболее распространенное поведение может быть достигнуто с помощью аннотаций и нулевого пользовательского кода.
Мы собираемся реализовать небольшую программу на Java, которая будет использовать функциональные возможности авиакомпании для имитации общего интерфейса командной строки. Он предоставит пользовательские команды для настройки конфигурации нашей программы, такие как определение URL-адреса базы данных, учетных данных и подробностей регистратора. Мы также погрузимся под поверхность нашей библиотеки и используем больше, чем ее основы, чтобы исследовать, может ли она справиться с некоторой сложностью.
3. Настройка
Для начала давайте добавим зависимость Airline в наш pom.xm l:
com.github.rvesse airline 2.7.2
4. Простой ЩЕЛЧОК
Давайте создадим нашу точку входа для приложения — класс CommandLine :
@Cli(name = "baeldung-cli", description = "Baeldung Airline Tutorial", defaultCommand = Help.class) public class CommandLine { public static void main(String[] args) { Clicli = new Cli<>(CommandLine.class); Runnable cmd = cli.parse(args); cmd.run(); } }
С помощью простой аннотации @Cli мы определили команду по умолчанию, которая будет выполняться в нашем приложении, – команду Help .
Класс Help входит в библиотеку авиакомпаний и предоставляет команду справки по умолчанию с использованием параметров -h или –help .
Просто так, базовая настройка завершена.
5. Наша Первая Команда
Давайте реализуем нашу первую команду, простую команду Logging class, которая будет контролировать многословность наших журналов. Мы будем аннотировать класс с помощью @Command , чтобы убедиться, что правильная команда применяется при вызове пользователем setup-log :
@Command(name = "setup-log", description = "Setup our log") public class LoggingCommand implements Runnable { @Inject private HelpOptionhelp; @Option(name = { "-v", "--verbose" }, description = "Set log verbosity on/off") private boolean verbose = false; @Override public void run() { if (!help.showHelpIfRequested()) System.out.println("Verbosity: " + verbose); } } }
Давайте подробнее рассмотрим наш пример команды.
Во-первых, мы задали описание, чтобы наш помощник, благодаря инъекции, отображал наши параметры команды по запросу.
Затем мы объявили переменную boolean , verbose и аннотировали ее с помощью @Option , чтобы дать ей имя, описание, а также псевдоним -v/–verbose , чтобы представить нашу опцию командной строки для управления многословием.
Наконец, в методе run мы проинструктировали нашу команду останавливаться всякий раз, когда пользователь обращается за помощью.
Пока все идет хорошо. Теперь нам нужно добавить нашу новую команду в основной интерфейс, изменив аннотацию @ Cli :
@Cli(name = "baeldung-cli", description = "Baeldung Airline Tutorial", defaultCommand = Help.class, commands = { LoggingCommand.class, Help.class }) public class CommandLine { public static void main(String[] args) { Clicli = new Cli<>(CommandLine.class); Runnable cmd = cli.parse(args); cmd.run(); } }
Теперь, если мы передадим setup-log-v нашей программе, она выполнит нашу логику.
6. Ограничения и многое другое
Мы видели, как авиакомпания безупречно генерирует CLI, но… это еще не все!
Мы можем указать ограничения (или ограничения) для наших параметров для обработки разрешенных значений, требований или зависимостей и многого другого.
Мы собираемся создать команду Database Setup class, которая будет реагировать на команду setup-db ; то же самое, что мы делали ранее, но мы добавим некоторые специи.
Во-первых, мы запросим тип базы данных, принимая только 3 допустимых значения через @AllowedRawValues :
@AllowedRawValues(allowedValues = { "mysql", "postgresql", "mongodb" }) @Option(type = OptionType.COMMAND, name = {"-d", "--database"}, description = "Type of RDBMS.", title = "RDBMS type: mysql|postgresql|mongodb") protected String rdbmsMode;
При использовании подключения к базе данных, без сомнения, пользователи должны предоставить конечную точку и некоторые учетные данные для доступа к ней. Мы позволим CLI обрабатывать это с помощью одного ( URL-режим) или нескольких параметров ( режим хоста ). Для этого мы будем использовать аннотацию @Mutually_exclusive_with , помечая каждый параметр одним и тем же тегом:
@Option(type = OptionType.COMMAND, name = {"--rdbms:url", "--url"}, description = "URL to use for connection to RDBMS.", title = "RDBMS URL") @MutuallyExclusiveWith(tag="mode") @Pattern(pattern="^(http://.*):(d*)(.*)u=(.*)&p=(.*)") protected String rdbmsUrl = ""; @Option(type = OptionType.COMMAND, name = {"--rdbms:host", "--host"}, description = "Host to use for connection to RDBMS.", title = "RDBMS host") @MutuallyExclusiveWith(tag="mode") protected String rdbmsHost = "";
Обратите внимание, что мы использовали @Pattern декоратор, который помогает нам определить формат строки URL.
Если мы посмотрим на проектную документацию, мы найдем другие ценные инструменты для обработки требований, вхождений, допустимых значений, конкретных случаев и многого другого, что позволит нам определить наши пользовательские правила .
Наконец, если пользователь выбрал режим хоста, мы должны попросить его предоставить свои учетные данные. Таким образом, один вариант зависит от другого. Мы можем добиться такого поведения с помощью аннотации @RequiredOnlyIf :
@RequiredOnlyIf(names={"--rdbms:host", "--host"}) @Option(type = OptionType.COMMAND, name = {"--rdbms:user", "-u", "--user"}, description = "User for login to RDBMS.", title = "RDBMS user") protected String rdbmsUser; @RequiredOnlyIf(names={"--rdbms:host", "--host"}) @Option(type = OptionType.COMMAND, name = {"--rdbms:password", "--password"}, description = "Password for login to RDBMS.", title = "RDBMS password") protected String rdbmsPassword;
Что делать, если нам нужно использовать некоторые драйверы для обработки подключения к БД? А также предположим, что нам нужно получить более одного значения в одном параметре. Мы можем просто изменить тип опции на Тип опции.АРГУМЕНТЫ или – еще лучше – принять список значений:
@Option(type = OptionType.COMMAND, name = {"--driver", "--jars"}, description = "List of drivers", title = "--driver--driver ") protected List jars = new ArrayList<>();
Теперь давайте не забудем добавить команду настройки базы данных в наш основной класс. В противном случае он не будет доступен в CLI.
7. Бегите
Мы сделали это! Мы закончили наш проект, и теперь мы можем его запустить.
Как и ожидалось, без передачи каких-либо параметров вызывается Help :
$ baeldung-cli usage: baeldung-cli[ ] Commands are: help Display help information setup-db Setup our database setup-log Setup our log See 'baeldung-cli help ' for more information on a specific command.
Если вместо этого мы выполним setup-log –help , мы получим:
$ baeldung-cli setup-log --help NAME baeldung-cli setup-log - Setup our log SYNOPSIS baeldung-cli setup-log [ {-h | --help} ] [ {-v | --verbose} ] OPTIONS -h, --help Display help information -v, --verbose Set log verbosity on/off
Наконец, предоставление параметров этим командам приведет к правильной бизнес-логике.
8. Заключение
В этой статье мы создали простой, но мощный интерфейс командной строки с очень небольшим количеством кода.
Библиотека авиакомпаний с ее мощными функциональными возможностями упрощает CLI, предоставляя нам общую, чистую и многоразовую инфраструктуру . Это позволяет нам, разработчикам, сосредоточиться на нашей бизнес-логике, а не тратить время на разработку того, что должно быть тривиальным.
Как всегда, код можно найти на GitHub .