检查属性是否具有正确的值

时间:2017-06-17 16:41:31

标签: java properties

我有一个配置文件中定义的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种不同的选项。

3 个答案:

答案 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