Код DefaultParser
, как представляется, всегда вызывает метод checkRequiredArgs()
. Который, кажется, указывает, что вы не можете одним махом избежать этой проблемы.
То, как мы рассматривали эту ситуацию в прошлом, возможно, неоптимально, состоит в том, чтобы анализировать командную строку дважды. Разбор выполняется быстро, поэтому накладные расходы минимальны.
Мы создали метод checkForHelp(String[] args)
, который принимает (String [] args). Он добавляет только параметр справки к параметрам, анализирует командную строку, а затем выясняет, указана ли помощь. Если да, то справка печатается, и программа выходит. В противном случае обрабатывается полный набор параметров. Этот подход позволяет обрабатывать необходимые поля, как ожидалось. Обратите внимание, что параметр справки также должен быть добавлен в основной список.
public static Option helpOption = Option.builder("h")
.longOpt("help")
.required(false)
.hasArg(false)
.build();
public static boolean checkForHelp(String[] args) throws ParseException {
boolean hasHelp = false;
Options options = new Options();
try {
options.addOption(helpOption);
CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse(options, args);
if (cmd.hasOption(helpOption.getOpt())) {
hasHelp = true;
}
}
catch (ParseException e) {
throw e;
}
return hasHelp;
}
Тогда в main
метод, что-то похожее на:
options.addOption(hostOption);
options.addOption(portOption);
options.addOption(serviceNameOption);
options.addOption(helpOption); // <-- must also be here to avoid exception
try {
if (checkForHelp(args)) {
HelpFormatter fmt = new HelpFormatter();
fmt.printHelp("Help", options);
return;
}
CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse(options, args);
if (cmd.hasOption("host")) {
host = cmd.getOptionValue("host");
System.out.println(host); // gets in here but prints null
}
if (cmd.hasOption("port")) {
port = ((Number) cmd.getParsedOptionValue("port")).intValue();
System.out.println(port); // gets in here but throws a null
// pointer exception
}
if (cmd.hasOption("service_name")) {
serviceName = cmd.getOptionValue("service_name");
System.out.println(serviceName); // gets in here but prints null
}
}
catch (Exception e) {
e.printStackTrace();
}
EDIT: как выясняется, этот подход аналогичен ответу, предоставленной здесь: Commons CLI required groups. Думаю, мне лучше, что в нашем подходе есть другие, поддерживающие то, во что мы верили.
EDIT2: В быстрой проверке, я считаю, что проблему с наличием необходимых параметров можно избежать, используя «OptionGroup». Вот пересмотренный checkForHelp
, который работает, добавив все опции в OptionGroup. В моем быстром тестировании он избегает проблемы, которая присутствовала, например, («--arg1 --help»).
public static boolean checkForHelp(String[] args) throws ParseException
{
boolean hasHelp = false;
Options options = new Options();
try {
options.addOption(hostOption); //has required set
options.addOption(portOption);
options.addOption(serviceNameOption);
options.addOption(helpOption);
// create an option group
OptionGroup og = new OptionGroup();
og.addOption(hostOption);
og.addOption(portOption);
og.addOption(serviceNameOption);
og.addOption(helpOption);
CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse(options, args, false);
if (cmd.hasOption(helpOption.getOpt()) || cmd.hasOption(helpOption.getLongOpt())) {
hasHelp = true;
}
}
catch (ParseException e) {
throw e;
}
return hasHelp;
}
Спасибо за ответ. На самом деле, я уже пробовал это раньше, несмотря на то, что это выглядит как взломать больше, чем формальный способ :(. Тем не менее проблема заключается в том, что у вас есть объект-параметр только с помощью справки, другие параметры будут генерировать исключение исключенной опции. –
Благодарим вас за редактирование и указатель я не мог дотянуться до него, когда искал.В ответах на комментарии они жалуются, что проблемы могут возникнуть из-за наличия двух разных групп опций. –
@ MohamedGad-Elrab. Верно, что другие значения могут создать эту ситуацию. Однако посмотрите [здесь] (http://stackoverflow.com/questions/6049470/can-apache-commons-cli-options-parser-ignore-unknown-command-line-options) для быстрого способа потенциально решить нераспознанные аргумент исключение. – KevinO