因为最近需要开发一个工具来进行NLP中的语料收集、处理、最后再进行训练,为了操作方便,准备使用命令行工具来进行操作,这时命令行处理有三个步骤:定义,解析和询问阶段,借助Apache Commons CLI是极其方便快捷的。

一、首先引入jar包
<dependency>
    <groupId>commons-cli</groupId>
    <artifactId>commons-cli</artifactId>
    <version>1.4</version>
    <optional>true</optional>
</dependency>
二、定义参数

每一条命令行都必须定义一组参数,它们被用来定义应用程序的接口。Apache Commons CLI 使用 Options 这个类来定义和设置参数,它是所有 Option 实例的容器。在 CLI 中,目前有两种方式来创建 Options,一种是通过构造函数,这是最普通也是最为大家所熟知的一种方式;另外一种方法是通过 Options 中定义的工厂方式来实现。
CLI 定义阶段的目标结果就是创建 Options 实例。上代码:

Options options = new Options();
 // 直接增加方式,参数1为短选项,2为长选项,3为是否选项后有参数,
 // 如-i 2之类。4为注释,在HelpFormatter打印中有用。
 options.addOption("h", "help", false, "显示帮助。");
 options.addOption("t", "type", true, "操作类型。");
 options.addOption("p", "path", true, "源语料路径。");
三、解析参数

在解析阶段中,通过命令行传入应用程序的文本来进行处理。处理过程将根据在解析器的实现过程中定义的规则来进行。在 CommandLineParser 类中定义的 parse 方法将用 CLI 定义阶段中产生的 Options 实例和一组字符串作为输入,并返回解析后生成的 CommandLine。
CLI 解析阶段的目标结果就是创建 CommandLine 实例,并且进行相应的业务操作,上代码:

CommandLineParser parser = new DefaultParser();
        Options options = buildOptions();
        try {
            CommandLine cl = parser.parse(options, strings, true);
            if (cl.hasOption("h")) {
                printHelp(options);
            } else if(cl.hasOption("t")){
                String type = cl.getOptionValue("t");
                if("export".equals(type)){
                    System.out.println("==========选择了导出操作==========");
                    String start = cl.getOptionValue("s");
                    String end = cl.getOptionValue("e");
                }
            }else{
                throw new NullPointerException("没有选择任何操作");
            }
        } catch (Exception exp) {
            System.out.println(exp.getMessage());

        }
private static void printHelp(Options options) {
        String cmdLineSyntax =
                "CorpusTool [OPTIONS] <INFILE>";

        HelpFormatter formatter = new HelpFormatter();
        formatter.printHelp(cmdLineSyntax, options, false);
    }
四、在springboot中写入

上面说的好像都和springboot没什么关系,其实这个要看你的业务需求的,看你的工具是干嘛的,因为在我这个工具的实现工程中,我需要用到项目的一些service,所以不可避免的,我一定要等spring的ioc容器初始化好我才能运行命令行。所以我把整个命令行程序放到了runner里面,runner是在ioc容器初始化好之后springboot会自动调用的一个接口,我们实现这个接口就会在程序运行成功之后调用runner的实现类。

package com.gildata.word2VecTrainer;

import com.gildata.word2VecTrainer.service.*;
import org.apache.commons.cli.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

/**
 * @description: 命令行工具
 * @author: cheny
 * @create: 2018-05-08
 **/
@Component
public class CmdRunner implements CommandLineRunner {

    @Autowired
    private ExportTxtService exportTxtService;

    @Autowired
    private NormalizeService normalizeService;

    @Autowired
    private SegmentService segmentService;

    @Autowired
    private TrainService trainService;

    @Autowired
    private StreamlinedService streamlinedService;

    @Override
    public void run(String... strings) throws Exception {
        //在这里做上面的参数定义、参数解析和业务实现,strings就是我们在命令行中输入的参数
    }
}
五、测试

第一种:测试的话如果代码改变不大可以打包jar出来,然后用java -jar xxx.jar 参数 这样进行测试。
第二种:用junit在方法中自定义字符串数组模仿输入参数进行测试:

// 测试带有 –h 参数的代码功能
public void testHelp() { 
    String args[]={"-h"}; 
    assertEquals(0, RMDataSource.simpleTest(args)); 
} 

// 测试没有带 –h 参数的代码功能
public void testNoArgs() { 
    String args[] = new String[0]; 
    assertEquals(1, RMDataSource.simpleTest(args)); 
} 

// 测试输入所有正确参数的代码功能
public void testRMDataSource() { 
  /** 
   * 此字符串参数等同于在命令行窗口输入命令 java rmdatasource -i 192.168.0.2 -p 5988 -t http 
    */ 
    String args[] = new String[]{"-i","192.168.0.2","-p","5988","-t","http"}; 
    assertEquals(0, RMDataSource.simpleTest(args)); 
}

第三种:利用idea的编辑环境:

springboot3比较好用的开源项目_命令行


springboot3比较好用的开源项目_命令行_02


把参数写入program arguments中,然后启动项目即可进行测试