Даже в 2019 году мы иногда пишем консольные утилиты. Эти консольные программы не имеют графического интерфейса, но принимают различные параметры и ключи с командной строки. Разбирать эти параметры командной строки вручную довольно муторная работа. К счастью, у нас есть Apache Commons CLI, который позволяет облегчить процесс разбора различных флагов и параметров, передаваемых в наше приложение.
Давайте начнём. Для начала нужно подключить Apache Commons CLI в наш проект. В maven нужно добавить следующую зависимость:
1 2 3 4 5 |
<dependency> <groupId>commons-cli</groupId> <artifactId>commons-cli</artifactId> <version>1.4</version> </dependency> |
Теперь можно начать обработку параметров командной строки. Начнём с вот такой заготовки:
1 2 3 4 5 6 7 8 9 |
package ru.urvanov.javaexamples.commonscli; public class App { public static void main( String[] args ) { System.out.println( "Hello World!" ); } } |
Нам передаётся массив args, но мы не будем разбирать его вручную. Мы задействуем мощь Apache Commons CLI. Для начала нам нужно создать объект Options:
1 |
Options options = new Options(); |
В созданный экземпляр класса Options мы будем добавлять описания ключей и параметров. Добавлять можно с помощью фабричных методов, либо создавая экземпляры Option вручную:
1 |
options.addOption("v", "Verbose output"); |
В примере выше мы добавили ключ -v, при обработке которого мы будем выводить больше информации в консоль.
Кроме указания коротких ключей мы можем заодно добавить длинный вариант, который будет указываться после двух знаков минус, например, в следующем параметре можно будет указать -s или --secondOption:
1 2 3 |
// -s or --secondOption options.addOption("s", "secondOption", false, "Just a second option."); |
Обратите внимание на третий параметр метода addOption в примере выше. Если его выставить в true, то будет предполагаться передача параметра в программу после этого ключа:
1 2 3 |
// -f <file >or --file <file> options.addOption("f", "file", true, "File to process"); |
Все предыдущие ключи/параметры были необязательными. Добавим теперь один обязательный параметр с помощью метода addRequiredOption:
1 2 |
options.addRequiredOption("r", "requiredOption", false, "Required option example"); |
Ок. Поскольку мы уже описали наши параметры, то теперь нам нужно распарсить массив args, переданный в метод main:
1 2 3 4 5 6 7 |
CommandLineParser parser = new DefaultParser(); CommandLine cmd = null; try { cmd = parser.parse( options, args); } catch (ParseException pe) { pe.printStackTrace(); } |
После выполнения метода parse у CommandLineParser мы получим экземпляр объекта CommandLine, с помощью которого мы можем проверить, какие опции были выставлены. Сейчас же обратите внимание на обработку ParseException. Мы просто выводим стектрейс в консоль. В идеале нам бы нужно здесь вывести подсказку, как на самом деле нужно вводить параметры. Для этого используется HelpFormatter:
1 2 3 4 |
} catch (ParseException pe) { HelpFormatter formatter = new HelpFormatter(); formatter.printHelp( "myappname", options ); } |
Попробуйте теперь скомпилировать и запустить приложение как Debug Java Application, для чего в дереве файлов проекта просто кликните правой кнопкой мышки и выберите Debug As -> Java Application.. В консоли должно вывестись:
1 2 3 4 5 |
usage: myappname -f,--file <arg> File to process -r,--requiredOption Required option example -s,--secondOption Just a second option. -v Verbose output |
Наш HelpFormatter отлично отработал. Теперь давайте добавим обработку ключей, для чего используется метод hasOption, проверяющий, передана ли нам опция с указанным ключом:
1 2 3 4 5 6 7 |
if (cmd.hasOption("v")) { System.out.println("We have verbose option"); // process verbose option key. } if (cmd.hasOption("f")) { System.out.println("FileName: " + cmd.getOptionValue("f")); } |
Теперь в конфигурации запуска нашего Debug Java Application укажите Program Arguments:
1 |
-r --file myfileargument -v |
Пример для Eclipse:

Запустите полученную конфигурацию и в консоли увидите:
1 2 |
We have verbose option FileName: myfileargument |
Как видим, наша обработка опций сработала.
Добавим в наш “pom.xml” конфигурацию, которая будет собирать jar-файл, который можно запускать с консоли (не берите сильно в голову, это не относится к текущей статье:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
.... <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.0</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>ru.urvanov.javaexamples.commonscli.App</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifest> <mainClass>org.prettypets.virtualpets.client.swing.MainClass</mainClass> <addClasspath>true</addClasspath> <classpathPrefix>data/lib/</classpathPrefix> </manifest> </archive> </configuration> </plugin> <plugin> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <phase>install</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/data/lib</outputDirectory> </configuration> </execution> </executions> </plugin> </plugins> </build> ... |
Теперь соберём jar файл с помощью:
1 |
mvn clean install |
и с собранным файлом проверим работоспособность опций:
1 2 3 4 5 6 7 8 9 |
$ java -jar commons-cli-0.0.1-SNAPSHOT.jar -r --file myfileargument -v We have verbose option FileName: myfileargument $ java -jar commons-cli-0.0.1-SNAPSHOT.jar -v usage: myappname -f,--file <arg> File to process -r,--requiredOption Required option example -s,--secondOption Just a second option. -v Verbose output |
Ура! Всё работает. Подписывайтесь, делайте донаты на Яндекс.Кошелек. Всем Бобра.
Ссылки по статье:
Файлы по статье: