标签:量化交易 jcommander 命令行解析 parameter注解
转载须注明出处:http://blog.csdn.net/minimicall?viewmode=contents,http://cloudtrade.top
在学习量化交易平台的过程中,接触到一个参数解析的库,JCommander。今天把它记录一下。
它的官网为:http://www.jcommander.org/
Jcommander是一个非常小的框架,用于解析命令行参数。
可以通过注解来描述你的参数选项:
import com.beust.jcommander.Parameter;
public class JCommanderExample {
@Parameter
private List<String> parameters = new ArrayList<String>();
@Parameter(names = { "-log", "-verbose" }, description = "Level of verbosity")
private Integer verbose = 1;
@Parameter(names = "-groups", description = "Comma-separated list of group names to be run")
private String groups;
@Parameter(names = "-debug", description = "Debug mode")
private boolean debug = false;
}
然后你可以通过下面代码来解析命令行参数:
JCommanderExample jct = new JCommanderExample();
String[] argv = { "-log", "2", "-groups", "unit" };
new JCommander(jct, argv);
Assert.assertEquals(jct.verbose.intValue(), 2);
你的参数可以是任何类型的。内置类型(Integer,Boolean,等),这些是默认就支持的,当然你可以写一个类型转换器来支持任意你想要支持的类型。
@Parameter(names = "-debug", description = "Debug mode") private boolean debug = false;
下面程序就是命令行的一个解析案例:
program -debug true program -debug false
JCommander支持String,Integer,Long类型的解析。
例如:
@Parameter(names = "-log", description = "Level of verbosity") private Integer verbose = 1;
java Main -log 3
当然,下面句子就会抛出异常:
java Main -log test
当Parameter注解放在一些列表List上时,那么JCommander会理解为该参数可以出现很多次。
@Parameter(names = "-host", description = "The host") private List<String> hosts = new ArrayList<String>();
java Main -host host1 -verbose -host host2
有时候你不想一个参数明文显示和出现在历史记录里面,比如输入的密码。这个时候你就可以将其配置为密码类型,只需要把password开关打开。
public class ArgsPassword {
@Parameter(names = "-password", description = "Connection password", password = true)
private String password;
}
Value for -password (Connection password):
public class ArgsPassword {
@Parameter(names = "-password", description = "Connection password", password = true, echoInput = true)
private String password;
}
JCommander是支持内置类型的参数配置。但更多时候吧,你需要输入一些更为复杂的类型。比如说,文件、主机名、列表等。。。。为了达到这个目的,你需要自己去实现下面这个转换接口:
public interface IStringConverter<T> {
T convert(String value);
}
public class FileConverter implements IStringConverter<File> {
@Override
public File convert(String value) {
return new File(value);
}
}
@Parameter(names = "-file", converter = FileConverter.class) File file;
上面的File file 用一次,就得使用一次converter=FileConverter.class。好麻烦不?如果要用多次,能不能省掉它呢。可以。
需要通过下面接口:
public interface IStringConverterFactory {
<T> Class<? extends IStringConverter<T>> getConverter(Class<T> forType);
}
java App -target example.com:8080
public class HostPort {
private String host;
private Integer port;
}
class HostPortConverter implements IStringConverter<HostPort> {
@Override
public HostPort convert(String value) {
HostPort result = new HostPort();
String[] s = value.split(":");
result.host = s[0];
result.port = Integer.parseInt(s[1]);
return result;
}
}
public class Factory implements IStringConverterFactory {
public Class<? extends IStringConverter<?>> getConverter(Class forType) {
if (forType.equals(HostPort.class)) return HostPortConverter.class;
else return null;
}
public class ArgsConverterFactory {
@Parameter(names = "-hostport")
private HostPort hostPort;
}
当然,你需要将工厂缴入到JCommander对象中:
ArgsConverterFactory a = new ArgsConverterFactory();
JCommander jc = new JCommander(a);
jc.addConverterFactory(new Factory());
jc.parse("-hostport", "example.com:8080");
Assert.assertEquals(a.hostPort.host, "example.com");
Assert.assertEquals(a.hostPort.port.intValue(), 8080);
你可以通过下面的接口来做一些早期的参数验证工作:
public interface IParameterValidator {
/**
* Validate the parameter.
*
* @param name The name of the parameter (e.g. "-host").
* @param value The value of the parameter that we need to validate
*
* @throws ParameterException Thrown if the value of the parameter is invalid.
*/
void validate(String name, String value) throws ParameterException;
}
public class PositiveInteger implements IParameterValidator {
public void validate(String name, String value)
throws ParameterException {
int n = Integer.parseInt(value);
if (n < 0) {
throw new ParameterException("Parameter " + name + " should be positive (found " + value +")");
}
}
}
使用例子:
@Parameter(names = "-age", validateWith = PositiveInteger.class) private Integer age;
到目前为止,你会发现每个参数都有一个names参数。JCommander允许且只允许你配置一个没有名字的参数,它会接受所有没有名字的参数。
例如:
@Parameter(description = "Files") private List<String> files = new ArrayList<String>(); @Parameter(names = "-debug", description = "Debugging level") private Integer debug = 1;
java Main -debug file1 file2
参数可以是私有的:
public class ArgsPrivate {
@Parameter(names = "-verbose")
private Integer verbose = 1;
public Integer getVerbose() {
return verbose;
}
}
ArgsPrivate args = new ArgsPrivate(); new JCommander(args, "-verbose", "3"); Assert.assertEquals(args.getVerbose().intValue(), 3);
默认情况下,参数是通过空白符分割的。但你可以改变为:
java Main -log:3
java Main -level=42
@Parameters(separators = "=")
public class SeparatorEqual {
@Parameter(names = "-level")
private Integer level = 2;
}
直接上例子吧:
public class ArgsMaster {
@Parameter(names = "-master")
private String master;
}
public class ArgsSlave {
@Parameter(names = "-slave")
private String slave;
}
ArgsMaster m = new ArgsMaster();
ArgsSlave s = new ArgsSlave();
String[] argv = { "-master", "master", "-slave", "slave" };
new JCommander(new Object[] { m , s }, argv);
Assert.assertEquals(m.master, "master");
Assert.assertEquals(s.slave, "slave");
JCommander支持@语法,允许你将参数写到文件里面,然后通过@符加载。例如:
-verbose file1 file2 file3
java Main @/tmp/parameters
一个参数会接收多个值,例如:
java Main -pairs slave master foo.xml
@Parameter(names = "-pairs", arity = 2, description = "Pairs") private List<String> pairs;
你可以定义参数接收无限个值,例如:
program -foo a1 a2 a3 -bar program -foo a1 -bar
@Parameter(names = "-foo", variableArity = true) public List<String> foo = new ArrayList<String>();
你可以为一个参数取多个名字:
@Parameter(names = { "-d", "--outputDirectory" }, description = "Directory")
private String outputDirectory;
java Main -d /tmp java Main --outputDirectory /tmp
好了,还有更多的细节,读者可以自行到其官网学习了。今天就到这里。。。。。。
程序员的量化交易之路(11)--命令参数解析库JCommonder学习
标签:量化交易 jcommander 命令行解析 parameter注解
原文地址:http://blog.csdn.net/minimicall/article/details/46238339