我有一个配置文件中定义的poperties列表,但在我继续进行进一步的计算之前,我想检查属性是否具有一致的值。目前我只是通过ifs做。
private static void checkprops (Properties properties) throws Throwable {
if (!properties.getProperty("number").equals("one")
&& !properties.getProperty("number").equals("two")) {
throw new Exception("ERROR");
}
if (!properties.getProperty("check").equals("false")
&& !properties.getProperty("check").equals("true")) {
throw new Exception("ERROR");
}
if (properties.getProperty("totalnum").equals("null")) {
throw new Exception("ERROR");
}
}
有没有办法以某种方式更短更容易阅读,因为我有一些属性将有5-6种不同的选项。
答案 0 :(得分:0)
您可以创建一个实用程序方法,该方法将接受配置文件中的值和期望值作为参数并返回bool,例如:
public boolean validateProp(T propVal, T... expectedVals) {
for(T expectedVal : expectedVals) {
if(propVal == null) {
if(expectedVal == null) {
return true;
}
}
else if(propVal.equals(expectedVal)) {
return true;
}
}
return false;
}
在这种情况下的示例调用将是:
if(!validateProp(properties.getProperty("number"), "one", "two") {
throw new Exception("ERROR");
}
答案 1 :(得分:0)
首先让我指出,您的代码有错误:
if (properties.getProperty("totalnum").equals("null")) { ... }
如果未定义该属性,getProperty()
会返回null
,因此在尝试访问NullPointerException
时,您的代码会引发equals()
。它不返回值为“null”的字符串。这就是你们所有人的情况。
我会使用反射来解决这个问题,使用一个config类来声明可能使用值检查注释的public
个字段。然后,方法将在该配置类的实例上设置值,从属性映射中读取。
进一步阅读:
这样做的好处是配置以直观的说话格式显示有效值。缺点是“解组”代码有点复杂。虽然这种方法非常强大。
配置可能如下所示:
static class Config {
@RegExp("^(one|two)$")
public String number;
public Boolean check;
@Required @Range(min=1, max=6)
public Integer totalnum;
}
如果某个字段缺少@Required
注释,则缺少的属性不会导致异常,因此会使用Config
的初始化值。
使用以下方法完成解组:
Config config = new Config();
setProperties(properties, config);
当值丢失,类型或值错误时, setProperties()
会抛出几个异常。可以捕获和区分异常以显示正确的错误消息。
在您的应用程序中,您可以像简单对象一样访问配置:
if (config.totalnum == 3) {
// do something when totalnum is 3
}
这是解组码:
private void setProperties(Properties properties, Props props) throws SecurityException, IllegalArgumentException, IllegalAccessException {
Class<?> clazz = props.getClass();
for (Field field : clazz.getDeclaredFields()) {
if ((field.getModifiers() & Modifier.PUBLIC) == 0) {
// ignore non-public properties
continue;
}
// the type of the field
Class<?> fieldType = field.getType();
// the field name of the class
String fieldName = field.getName();
// the raw value loaded from the .properties file
String value = properties.getProperty(fieldName);
// fields may be annotated with @Required
boolean required = (field.getAnnotation(Required.class) != null);
if (required && value == null) {
// field required but not defined in the properties, fail
throw new IllegalArgumentException(
String.format(
"Field %s is required",
fieldName
)
);
} else if (value == null) {
// ignore undefined field, default to class initialized value
continue;
}
// checks per type follow ...
if (fieldType == String.class) {
// fields may be annotated with RegExp to specify a matcher
RegExp regExp = field.getAnnotation(RegExp.class);
if (regExp != null && !Pattern.matches(regExp.value(), value)) {
throw new IllegalArgumentException(
String.format(
"Value for field %s does not match %s: %s",
fieldName,
regExp.value(),
value
)
);
}
field.set(props, value);
} else if (fieldType == Integer.class) {
// may throw NumberFormatException if not a valid integer
Integer intValue = Integer.parseInt(value);
// fields may be annotated with Range to specify an integer range
Range range = field.getAnnotation(Range.class);
if (range != null && !(intValue >= range.min() && intValue <= range.max())) {
throw new IllegalArgumentException(
String.format(
"Value for field %s out of range (%d..%d): %d",
fieldName,
range.min(),
range.max(),
intValue
)
);
}
field.set(props, intValue);
} else if (fieldType == Boolean.class) {
// strictly check valid boolean values
if (!Pattern.matches("^(true|false)$", value)) {
throw new IllegalArgumentException(
String.format(
"Value for field %s is not a valid boolean (true|false): %s",
fieldName,
value
)
);
}
field.set(props, Boolean.parseBoolean(value));
}
}
}
虽然已经非常复杂,但这段代码相当简单。它不处理其他数字类型,如Long
或原始类型,如int
。这些可以使用更多if
分支来实现。
这些是注释(在不同的类中定义):
@Retention(RUNTIME)
@Target(FIELD)
public @interface Range {
public int min() default Integer.MIN_VALUE;
public int max() default Integer.MAX_VALUE;
}
@Retention(RUNTIME)
@Target(FIELD)
public @interface RegExp {
public String value() default "^.*$";
}
@Retention(RUNTIME)
@Target(FIELD)
public @interface Required {
}
答案 2 :(得分:0)
避免直接验证 public IEnumerable<T> GetAllQuerable(
Expression<Func<T,
bool>> filter = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
string includeProperties = "")
{
return _repository.GetAllQuerable(filter, orderBy, includeProperties);
}
对象的选项是将其映射到POJO,然后在其上使用Bean Validation。
Bean Validation是一个标准的Java API,用于指定验证约束和检查对象(甚至方法参数)的有效性,这使您无需编写大量用于建模错误的代码。 参考实现是Hibernate Validator但是,尽管有名称,您可以单独使用它而不使用使用所有Hibernate。
作为一个例子(可能需要一些额外的工作):
Properties
调用代码:
public class Config {
@Pattern("^(one|two)$")
private String number;
@NotNull
private Boolean check;
@NotNull
@Min(1)
@Max(6)
private Integer totalnum;
public static Config fromProperties(Properties ps) {
Config conf = new Config();
conf.number = ps.getProperty("number");
// fails right away if "check" is null
conf.check = Boolean.valueOf(ps.getProperty("check"));
// fails right away if "totalnum" is null
conf.totalnum = Integer.valueOf(ps.getProperty("totalnum"));
return conf;
}
}
在示例中,我使用Validator validator = Validation.buildDefaultValidatorFactory()
.getValidator();
Config config = Config.fromProperties(properties);
Set<ConstraintViolation<Config>> violations = validator.validate(config);
if (violations.isEmpty()) {
// good to go
} else {
// some code to print the errors
}
约束来匹配使用正则表达式,但是,由于您提到某些属性具有5-6个可能的值,因此最好定义自己的注释,如
@Pattern