- 浏览: 778328 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
萨琳娜啊:
Java读源码之Netty深入剖析网盘地址:https://p ...
Netty源码学习-FileRegion -
飞天奔月:
写得有趣 ^_^
那一年你定义了一个接口 -
GoldRoger:
第二个方法很好
java-判断一个自然数是否是某个数的平方。当然不能使用开方运算 -
bylijinnan:
<script>alert("close ...
自己动手实现Java Validation -
paul920531:
39行有个bug:"int j=new Random ...
java-蓄水池抽样-要求从N个元素中随机的抽取k个元素,其中N无法确定
参数检查用得最多的是JSR 303,用法示例:
http://blog.csdn.net/caihaijiang/article/details/7463514
但JSR 303有个缺点,那就是当参数的限制发生变化时,例如某String类型的最大长度由10改为20,就需要改代码重新编译。
那有没有办法只改配置文件重启程序就达到目的呢?
网上还没有类似的解决方案,那就自己实现Java Validation。
思路:
参数检查时,从配置文件中取得参数的限制条件,通过反射取得对应的字段值,并进行验证。
用法:
测试表明,Checker比JSR 303速度更快。Checker没有JSR 303那么全面,但也基本够用。
源码:
http://blog.csdn.net/caihaijiang/article/details/7463514
但JSR 303有个缺点,那就是当参数的限制发生变化时,例如某String类型的最大长度由10改为20,就需要改代码重新编译。
那有没有办法只改配置文件重启程序就达到目的呢?
网上还没有类似的解决方案,那就自己实现Java Validation。
思路:
参数检查时,从配置文件中取得参数的限制条件,通过反射取得对应的字段值,并进行验证。
用法:
//利用反射和注解自行实现的参数检查 Order order = newOrder(); Map<String, String> configMap = ConfigMap.INSTANCE.getMap(); //需要两个参数:一是需要参数检查的对象,二是参数的限制条件 List<String> 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<String, String> map; ConfigMap() { map = new HashMap<String, String>(); //在配置文件中这样写:check.com.ljn.validation.MyOrder.userId.max=3 //表示MyOrder这个类的userId字段,长度最大为3 map.put("check.com.ljn.validation.MyOrder.userId.max", "3"); map.put("check.com.ljn.validation.MyOrder.name.max", "3"); map.put("check.com.ljn.validation.MyOrder.address.max", "3"); map.put("check.com.ljn.validation.MyOrder.cardNo.reg", "\\d+"); map.put("check.com.ljn.validation.MyOrder.intVal.max", "9"); map.put("check.com.ljn.validation.MyOrder.integerVal.max", "9"); map.put("check.com.ljn.validation.MyOrder.longVal.max", "9"); map.put("check.com.ljn.validation.MyOrder.longGVal.max", "9"); map.put("check.com.ljn.validation.MyOrder.userId.min", "2"); map.put("check.com.ljn.validation.MyOrder.name.min", "2"); map.put("check.com.ljn.validation.MyOrder.address.min", "2"); map.put("check.com.ljn.validation.MyOrder.intVal.min", "4"); map.put("check.com.ljn.validation.MyOrder.integerVal.min", "4"); map.put("check.com.ljn.validation.MyOrder.longVal.min", "4"); map.put("check.com.ljn.validation.MyOrder.longGVal.min", "4"); map.put("check.com.ljn.validation.MyOrder.bigDecimalVal.maxBigDecimalIntegerSize", "5"); map.put("check.com.ljn.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 * @author ljn * */ @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<Class<?>, List<Field>> classFields = new HashMap<Class<?>, List<Field>>(); /** * * @param obj 对obj进行参数检查 * @param configMap 配置值,配置了各字段的限制值,例如最小长度,最大长度 * @return 参数不合法的信息列表 */ public List<String> check(Object obj, Map<String, String> configMap){ List<String> list = new ArrayList<String>(); if (obj == null || configMap == null || configMap.isEmpty()) { return list; } Class<? extends Object> clazz = obj.getClass(); List<Field> 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<Field> getFieldsUpTo(Class<?> startClass, Class<?> exclusiveParent) { List<Field> currentClassFields = new ArrayList<Field>(); Field[] declaredFields = startClass.getDeclaredFields(); for (Field field : declaredFields) { currentClassFields.add(field); } Class<?> parentClass = startClass.getSuperclass(); if (parentClass != null && (exclusiveParent == null || !(parentClass.equals(exclusiveParent)))) { List<Field> parentClassFields = (List<Field>) getFieldsUpTo(parentClass, exclusiveParent); currentClassFields.addAll(parentClassFields); } return currentClassFields; } private static int getInt(Map<String, String> map, String key) { String val = map.get(key); if (val != null) { return Integer.parseInt(val); } return -1; } private static long getLong(Map<String, String> map, String key) { String val = map.get(key); if (val != null) { return Long.parseLong(val); } return -1; } }
发表评论
-
BeanUtils.copyProperties使用笔记
2015-07-06 22:17 32565BeanUtils.copyProperties VS Pro ... -
Haproxy+Keepalived高可用双机单活
2015-01-06 17:37 6588我们的应用MyApp不支持集群,但要求双机单活(两台机器:ma ... -
返回null还是empty
2014-05-16 15:35 100第一个问题,函数是应当返回null还是长度为0的数组(或集合) ... -
返回null还是empty
2014-05-16 15:34 2274第一个问题,函数是应当返回null还是长度为0的数组(或集合) ... -
返回null还是empty
2014-05-16 15:34 152第一个问题,函数是应当返回null还是长度为0的数组(或集合) ... -
返回null还是empty
2014-05-16 15:34 114第一个问题,函数是应当返回null还是长度为0的数组(或集合) ... -
返回null还是empty
2014-05-16 15:33 100第一个问题,函数是应当返回null还是长度为0的数组(或集合) ... -
Spring源码学习-JdbcTemplate queryForObject
2014-05-09 19:45 2988JdbcTemplate中有两个可能会混淆的queryForO ... -
Spring源码学习-JdbcTemplate batchUpdate批量操作
2014-05-07 16:21 18746Spring JdbcTemplate的batch操作最后还是 ... -
Spring源码学习-PropertyPlaceholderHelper
2014-04-25 18:47 2590今天在看Spring 3.0.0.RELEASE的源码,发现P ... -
J2EE设计模式-Intercepting Filter
2013-11-27 16:56 1500Intercepting Filter类似于职责链模式 有两种 ... -
CAS实现单点登录(SSO)
2013-07-29 18:08 1440参考以下两篇文章,对原作者表示感谢: http://blog. ... -
《重构,改善现有代码的设计》第八章 Duplicate Observed Data
2012-12-04 20:34 1466import java.awt.Color; impor ... -
org.apache.tools.zip实现文件的压缩和解压,支持中文
2012-08-08 19:32 5056刚开始用java.util.Zip,发 ...
相关推荐
这是java和xml联合编程可使用的文档!
主要介绍了Java Validation Api实现原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
IT is a input validation system in java
主要介绍了Java Validation Api如何实现自定义注解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
Java Validation A lib to make validations on java objects How add it Add the repository to your build.gradle with: repositories { maven { url "https://jitpack.io" } } and on your project ...
标签:javax、api、validation、jar包、java、API文档、中文版; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准...
配置简单,可自由扩展验证器,实际只要实现IValidator接口,以及在rules.fo.xml中添加相关的配置即可; 支持Spring接口; 使用过程中,你会感觉好像只用了 IValidateService.validate() 一个方法,这会让人感觉良好...
主要介绍了Java Validation Api使用方法实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
标签:jakarta、validation、api、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请...
本篇文章主要介绍了java validation 后台参数验证的使用详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
面对瞬息万变的业务需求,规则每天都在变化。 我们如何处理这种变化,同时保持我们的系统有效地可维护、可重用和可扩展?
标签:api、jakarta、validation、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请...
JGoodies ::Java User Interface Design-->Application -->Validation Demo
使用Java实现的灵活验证库。 最新版本: 安装 Gradle是唯一受支持的构建配置。 步骤1.将JitPack存储库添加到构建文件中将其添加到存储库末尾的root build.gradle中: allprojects { repositories { maven { url...
Springboot SpringMVC thymeleaf页面提交Validation实现实例.pdfSpringboot SpringMVC thymeleaf页面提交Validation实现实例.pdfSpringboot SpringMVC thymeleaf页面提交Validation实现实例.pdfSpringboot SpringMVC...
這是一個基於最新版本的Struts2.2.3.8+國際化+驗證的J2EE完整登錄項目源碼。
Struts1.2中的validation验证框架的实现步骤
Bean Validation 规范对 Java Bean 的验证流程如下:在实际使用中调用 Validator.validate(JavaBeanInstance) 方法后,Bean Validation 会查找在 JavaBeanInstance上所有的约束声明,对每一个约束调用对应的约束验证...
标签:jakarta、validation、api、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译...
< artifactId>graphql-java-extended-validation < version>16.0.0 < type>pom compile ' com.graphql-java:graphql-java-extended-validation:16.0.0 ' 笔记: 对于graphql-java 13.x和更低版本使用0.0.3或更...