2017-06-17 57 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;