2017-06-17 59 views
0

我有配置文件中定义的属性列表,但在继续进一步计算之前,我想检查属性是否具有一致的值。目前我只是通过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

,首先我要指出,你的代码中有一个错误:

if (properties.getProperty("totalnum").equals("null")) { ... } 

如果没有定义财产,getProperty()返回null,因此当您尝试访问equals()时,您的代码将产生NullPointerException。它不会返回值为“null”的字符串。这就是所有线路的情况。


我处理这个使用反射,与声明public领域可能与值检查被标注一个配置类。然后,方法将在该配置类的实例上设置值,从属性映射中读取。

进一步阅读:

这样做的优点是该配置显示intuitiv中的有效值e,口语格式。缺点是“解组”代码有点复杂。尽管这种方法非常强大。

的配置看起来是这样的:

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 { 

} 
0

您可以创建一个将接受来自您的配置文件值和预期值作为参数,并返回一个布尔值,例如实用方法:

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"); 
} 
0

一个选项,以避免直接验证Properties目的是将它映射到一个POJO,然后在其上使用Bean Validation

Bean Validation是一个标准的Java API,用于指定验证约束和检查对象(甚至是方法参数)的有效性,从而避免您编写大量用于建模错误的代码。 参考实现是Hibernate Validator,但是,尽管名称不同,但您可以使用独立的而不使用使用所有Hibernate。

为例(这可能需要一些额外的工作):

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 
} 

在这个例子中,我使用的是@Pattern约束使用相匹配正则表达式,但因为你提到一些属性有5-6个可能的值,所以定义你自己的注释可能会更好,如

@Values({"one", "two", "three", "four"}) 
    private String number;