java validation_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;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值