Java Validation

参数检查用得最多的是JSR 303,用法示例:
http://blog.csdn.net/caihaijiang/article/details/7463514
但JSR 303有个缺点,那就是当参数的限制发生变化时,例如某String类型的最大长度由10改为20,就需要改代码重新编译。

那有没有办法只改配置文件重启程序就达到目的呢?

网上还没有类似的解决方案,那就自己实现Java Validation。

思路:

参数检查时,从配置文件中取得参数的限制条件,通过反射取得对应的字段值,并进行验证。

用法:

//利用反射和注解自行实现的参数检查 
Order order = newOrder();  
Map configMap = ConfigMap.INSTANCE.getMap();  

//需要两个参数:一是需要参数检查的对象,二是参数的限制条件  
List list = Checker.INSTANCE.check(order, configMap);  
          for (String str : list) {  
            /*输出示例:
            cardNo不符合正则表达式\d+
            name长度最小不能小于2
            address长度最小不能小于2
            intVal最大不能超过9
            integerVal最小不能小于4
            longVal最小不能小于4
            longGVal最小不能小于4
            */  
               System.out.println(str);  
           } 
       }  
package com.ljn.validation;  
import java.util.HashMap;  
import java.util.Map;  

/**
 * 
 * 模拟从配置文件中读取配置值
 * 用点号分隔,最后是字段名
 */  

public enum ConfigMap {  
    INSTANCE;  
private Map map;  
ConfigMap() {  
map =new HashMap();  
//在配置文件中这样写:check.com.ljn.validation.MyOrder.userId.max=3  
//表示MyOrder这个类的userId字段,长度最大为3  
map.put("check.com.robin.validation.MyOrder.userId.max", "3");  
map.put("check.com.robin.validation.MyOrder.name.max",  "3");  
map.put("check.com.robin.validation.MyOrder.address.max", "3");  
map.put("check.com.robin.validation.MyOrder.cardNo.reg", "\\d+");  
map.put("check.com.robin.validation.MyOrder.intVal.max",  "9");  
map.put("check.com.robin.validation.MyOrder.integerVal.max",  "9");  
map.put("check.com.robin.validation.MyOrder.longVal.max",  "9");  
map.put("check.com.robin.validation.MyOrder.longGVal.max",  "9");  
map.put("check.com.robin.validation.MyOrder.userId.min", "2");  
map.put("check.com.robin.validation.MyOrder.name.min",  "2");  
map.put("check.com.robin.validation.MyOrder.address.min", "2");  
map.put("check.com.robin.validation.MyOrder.intVal.min",  "4");  
map.put("check.com.robin.validation.MyOrder.integerVal.min",  "4");  
map.put("check.com.robin.validation.MyOrder.longVal.min",  "4");  
map.put("check.com.robin.validation.MyOrder.longGVal.min",  "4");  
map.put("check.com.robin.validation.MyOrder.bigDecimalVal.maxBigDecimalIntegerSize",  "5");  
map.put("check.com.robin.validation.MyOrder.bigDecimalVal.maxBigDecimalFractionSize",  "2");  
    }  
}  

调用:

package com.ljn.validation;  
import java.math.BigDecimal;  
import java.util.List;  
import javax.validation.constraints.Digits;  
import javax.validation.constraints.Max;  
import javax.validation.constraints.Min;  
import javax.validation.constraints.NotNull;  
import javax.validation.constraints.Size;  

public class Order {  
@Check(NotNull=true)  
@NotNull  
private List nullVal;  

@Size(min =2, max = 3)  
@Check(Min=true,Max=true)  
private String name;  

@Size(min =2, max = 3)  
@Check(Min=true, Max=true)  
private String address;  

private String userId;  

@Min(4)  
@Max(9)  
@Check(Min=true, Max=true)  
private int intVal;  

@Min(4)  
@Max(9)  
@Check(Min=true, Max=true)  
private Integer integerVal;  

@Min(4)  
@Max(9)  
@Check(Min=true, Max=true)  
private long longVal;  

@Min(4)  
@Max(9)  
@Check(Min=true, Max=true)  
private Long longGVal;  

@Digits(integer=5, fraction=2)  
@Check(MaxBigDecimalFractionSize=true, MaxBigDecimalIntegerSize=true)  
private BigDecimal bigDecimalVal;  

//...setter and getter  
    }  

测试表明,Checker比JSR 303速度更快。Checker没有JSR 303那么全面,但也基本够用。

import java.lang.annotation.ElementType;  
import java.lang.annotation.Retention;  
import java.lang.annotation.RetentionPolicy;  
import java.lang.annotation.Target;  
/**

 * 1.NotNull/NotBlank默认值为false,其他为true
 * 2.即使Min/Max/MaxBigDecimalIntegerSize/MaxBigDecimalFractionSize/RegExp这些选项配置为true,
 *   也需要在配置文件中配置了具体值才会进行检查
 * 3.对于String类型,不要同时配置NotNull和NotBlank,建议只配置NotBlank
 *
 */  
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.FIELD)  
public @interface Check {  
/**
     * 检查是否为null,适用所有数据类型
     */  
public boolean NotNull() default false;  

/**
     * 检查字符串是否为空字符串(包括null),相当于StringUtils.isBlank
     */  
public boolean NotBlank() default false;  

/**
     * 对于String类型,检查字符串长度是否小于最小长度
     * 对于short/Short/int/Integer/long/Long类型,检查是否小于最小值
     */  
public boolean Min() default true;  

/**

     * 对于String类型,检查字符串长度是否超过最大长度

     * 对于short/Short/int/Integer/long/Long类型,检查是否超过最大值

     */  

public boolean Max() default true;  

/**
     * 检查BigDecimal类型的整数部分的长度是否超过最大长度
     */  
public boolean MaxBigDecimalIntegerSize() default true;  

/**
     * 检查BigDecimal类型的小数部分的长度是否超过最大长度
     */  
public boolean MaxBigDecimalFractionSize() default true;  

/**
     * 检查字符串类型的值是否符合正则表达式指定的格式
     */  
public boolean RegExp() default true;  
}  



public enum Checker {  
    INSTANCE;  
public static final String KEY_SEPARATOR = ".";  
public static final String PREFIX = "check";  
public static final String SUFFIX_MAX = "max";  
public static final String SUFFIX_MIN = "min";  
public static final String SUFFIX_MAX_BIGDECIMAL_INTEGER_SIZE = "maxBigDecimalIntegerSize";  
public static final String SUFFIX_MAX_BIGDECIMAL_FRACTION_SIZE = "maxBigDecimalFractionSize";  
public static final String SUFFIX_REG_EXP = "regExp";  
private Map, List> classFields = new HashMap, List>();  

/**
     * 
     * @param obj 对obj进行参数检查
     * @param configMap 配置值,配置了各字段的限制值,例如最小长度,最大长度
     * @return 参数不合法的信息列表
     */  
public List check(Object obj, Map configMap){  
List list =new ArrayList();  
if (obj == null || configMap == null || configMap.isEmpty()) {  
return list;  
}  

List fields = classFields.get(clazz);  
if (fields == null) {  
fields = getFieldsUpTo(clazz, Object.class);  
if (fields == null || fields.isEmpty()) {  
return list;  
}  
classFields.put(clazz, fields);  
}  

for (Field field : fields) {  
field.setAccessible(true);  
Check check = field.getAnnotation(Check.class);  
if (check == null) {  
continue;  
}  

Class fieldType = field.getType();  
String fieldName = field.getName();  
Object value =null;  
try {  
       value = field.get(obj);  
}catch (Exception e) {  
throw new RuntimeException(e);  
 }  

if (value == null) {  
if (check.NotNull()) {  
list.add(fieldName +"不能为null");  
}else if ( check.NotBlank() && fieldType.equals(String.class)) {  
list.add(fieldName +"不能为空");  
}  
}else {  
//check_className_fieldName_suffix  
String minKey = StringUtils.join(new String[]{PREFIX, clazz.getName(), fieldName, SUFFIX_MIN}, KEY_SEPARATOR);                  
String maxKey = StringUtils.join(new String[]{PREFIX, clazz.getName(), fieldName, SUFFIX_MAX}, KEY_SEPARATOR);                  
String maxBigDecimalIntegerSizeKey = StringUtils.join(new String[]{PREFIX, clazz.getName(), fieldName, SUFFIX_MAX_BIGDECIMAL_INTEGER_SIZE}, KEY_SEPARATOR);  
String maxBigDecimalFractionSizeKey = StringUtils.join(new String[]{PREFIX, clazz.getName(), fieldName, SUFFIX_MAX_BIGDECIMAL_FRACTION_SIZE}, KEY_SEPARATOR);  
String regExpKey = StringUtils.join(new String[]{PREFIX, clazz.getName(), fieldName, SUFFIX_REG_EXP}, KEY_SEPARATOR);  

if (fieldType.equals(String.class)) {  
      String val = (String)value;  
if (check.NotBlank() && StringUtils.isBlank(val)) {  
list.add(fieldName +"不能为空");  
}  
if (check.Min()) {  
int min = getInt(configMap, minKey);  
if (min != -1 && val.length() < min) {  
list.add(fieldName +"长度最小不能小于" + min);   
  }  
}  
if (check.Max()) {  
int max = getInt(configMap, maxKey);  
if (max != -1 && val.length() > max) {  
list.add(fieldName +"长度最大不能超过" + max);   
 }  
}  

if (check.RegExp()) {  
      String exp = configMap.get(regExpKey);  
if (StringUtils.isNotBlank(exp) && StringUtils.isNotBlank(val) && !val.matches(exp)) {  
list.add(fieldName +"不符合正则表达式" + exp);  
}  
}  
}  

if (fieldType.equals(Integer.class) || fieldType.equals(int.class)) {  
Integer val = (Integer)value;  
if (check.Min()) {  
int min = getInt(configMap, minKey);  
if (min != -1 && val < min) {  
list.add(fieldName +"最小不能小于" + min);   
}  
}  

if (check.Max()) {  
int max = getInt(configMap, maxKey);  
if (max != -1 && val > max) {  
list.add(fieldName +"最大不能超过" + max);   
 }  
 }  
}  



if (fieldType.equals(Short.class) || fieldType.equals(short.class)) {  
          Short val = (Short)value;  
if (check.Min()) {  
int min = getInt(configMap, minKey);  
if (min != -1 && val < min) {  
list.add(fieldName +"最小不能小于" + min);   
   }  
}  

if (check.Max()) {  
int max = getInt(configMap, maxKey);  
if (max != -1 && val > max) {  
list.add(fieldName +"最大不能超过" + max);   
}  
 }  
 }  

if (fieldType.equals(Long.class) || fieldType.equals(long.class)) {  
         Long val = (Long)value;  
if (check.Min()) {  
long min = getLong(configMap, minKey);  
if (min != -1 && val < min) {  
list.add(fieldName +"最小不能小于" + min);   
 }  
}  

if (check.Max()) {  
long max = getLong(configMap, maxKey);  
if (max != -1 && val > max) {  
list.add(fieldName +"最大不能超过" + max);   
 }  
  }  
}  

if (fieldType.equals(BigDecimal.class)) {  
   BigDecimal val = (BigDecimal)value;  
   String str = val.toPlainString();  
String[] parts = str.split("\\.");  
if (parts == null || parts.length == 0) {  
continue;  
}  

int integerSize = parts[0].length();  
int fractionSize = parts.length == 2 ? parts[1].length() : 0;  
if (check.MaxBigDecimalIntegerSize()) {  
int max = getInt(configMap, maxBigDecimalIntegerSizeKey);  
if (max != -1 && integerSize > max) {  
list.add(fieldName +"整数部分长度最大不能超过" + max);  
}  
}  
if (check.MaxBigDecimalFractionSize()) {  
int max = getInt(configMap, maxBigDecimalFractionSizeKey);  
if (max != -1 && fractionSize > max) {  
list.add(fieldName +"小数部分长度最大不能超过" + max);  
}  
}  
}  
 }  
}  
return list;  
}  

/**
     * 获取所有的Field
     * @param startClass
     * @param exclusiveParent
     * @return
     */  
public List getFieldsUpTo(Class startClass, Class exclusiveParent) {  
List currentClassFields =new ArrayList();  
Field[] declaredFields = startClass.getDeclaredFields();  
for (Field field : declaredFields) {  
            currentClassFields.add(field);  
        }  
        Class parentClass = startClass.getSuperclass();  
if (parentClass != null && (exclusiveParent == null || !(parentClass.equals(exclusiveParent)))) {  
            List parentClassFields = (List) getFieldsUpTo(parentClass, exclusiveParent);  
            currentClassFields.addAll(parentClassFields);  
        }  
return currentClassFields;  
    }  

private static int getInt(Map map, String key) {  
        String val = map.get(key);  
if (val != null) {  
return Integer.parseInt(val);  
 }  
return -1;  
    }  

private static long getLong(Map map, String key) {  
        String val = map.get(key);  
if (val != null) {  
return Long.parseLong(val);  
        }  
return -1;  
    }  
}  

你可能感兴趣的:(Java Validation)