因为最近需要开发一个工具来进行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的编辑环境:
把参数写入program arguments中,然后启动项目即可进行测试