随笔-1  评论-8  文章-1  trackbacks-0

基于JAVA标注实现统一的前台(JS层)后台(JAVA层)想法

原创,非转
基于JAVA标注实现统一的前台(JS层)后台(JAVA层)想法[/b]
通过标注的方式进行前后台的统一验证的好处是很多的,增强前后台验证的一致性,减少代码的重复,不需要前台与一份验证,后台再写一份了。

本人想基于这种方式写一个基于Annotation的完整的Validator的开源的小框架,但发现要做的事情很多,工作量很大,要一点一点的来,一点一点的完善,最后闲时写了个大 概,与大家一起探讨
  1. 通过JAVA标注将前台和后台的验证规则标到JAVA的值对象的类中。
  2. Validator在初始化的过程中,一次性读入JAVA的值对象的类中验证规则的标注信息,并生成前台需要的校验的JS文件。
  3. 前台页面可以直接引入自动生成的校验的JS文件,进行校验。a
  4. 后台得到从前台请求request绑定好值的JAVA的值对象,通过AnnotationValidator类进行验证。

以下是Annotation标注的代码。

进行不可以为空的校验标注
  1. @Retention (RetentionPolicy.RUNTIME)   
  2. @Target(ElementType.FIELD)   
  3.   
  4. public @interface CanNotNull {     
  5.   
  6. }  
进行是否是整数的校验标注
  1. @Retention(RetentionPolicy.RUNTIME)   
  2. @Target(ElementType.FIELD)   
  3. public @interface IsInteger {   
  4.     public int minWidth() default 1;   
  5.     public int maxWidth() default Integer.MAX_VALUE;   
  6.     public  int minValue() default Integer.MIN_VALUE;   
  7.     public  int maxValue() default Integer.MAX_VALUE;   
  8.   
  9. }  
用于添写字段中文的标注


  1. @Retention(RetentionPolicy.RUNTIME)   
  2. @Target(ElementType.FIELD)   
  3. public @interface FieldDesc {   
  4.     public String value();   
  5.   
  6. }  

验证器的代码:
  1. package com.javaest.validity.process;   
  2.   
  3. import java.io.BufferedWriter;   
  4. import java.io.File;   
  5. import java.io.FileWriter;   
  6. import java.io.IOException;   
  7. import java.lang.reflect.Field;   
  8. import java.lang.reflect.InvocationTargetException;   
  9. import java.lang.reflect.Method;   
  10. import java.util.ArrayList;   
  11. import java.util.HashMap;   
  12. import java.util.List;   
  13. import java.util.Map;   
  14.   
  15. import com.javaest.util.StringUtils;   
  16. import com.javaest.validity.annotation.CanNotNull;   
  17. import com.javaest.validity.annotation.FieldDesc;   
  18. import com.javaest.validity.annotation.IsInteger;   
  19. import com.javaest.validity.test.pojo.Student;   
  20.   
  21. public class PojoBeanAnnotationValiditer {   
  22.     private static Map<String, Map> allValidityRuleMap = new HashMap<String, Map>();   
  23.     private static Map<String, Map> allFieldDescMap = new HashMap<String, Map>();   
  24.     private static String jsValiditerFilePath;   
  25.     private static String[] pojoBeanPackageName;   
  26.     /**  
  27.      *   
  28.         将指定的包下边的所有Pojo类的标注信息一次性的读取到Map中,以备以后验证对象时使用  
  29.      */  
  30.     public static void loadAllClassAnnotationValidityInfoInPackage(String[] packageNameArr)   
  31.             throws IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchMethodException,   
  32.             InvocationTargetException, ClassNotFoundException, IOException {   
  33.         for (int i = 0; i < packageNameArr.length; i++) {   
  34.             List<Class> classList = ReflectUtils.getAllClassInPackage(packageNameArr[i]);   
  35.             for (int j = 0; j < classList.size(); j++) {   
  36.                 Class currClass = classList.get(j);   
  37.                 String classFullName = currClass.getPackage().getName() + "." + currClass.getName();   
  38.                 Map[] validityRuleMapAndFieldDescMap = loadValidityRuleAndCreateValidityJsFile(currClass);   
  39.                 allValidityRuleMap.put(classFullName, validityRuleMapAndFieldDescMap[0]);   
  40.                 allFieldDescMap.put(classFullName, validityRuleMapAndFieldDescMap[1]);   
  41.             }   
  42.         }   
  43.     }   
  44.     /*  
  45.      * 对具体的一个类的标注做处理,读入字段描述 信息,读入非空验证信息,读入整数验证信息,并根据这些信息生成JS代码。  
  46.      */  
  47.   
  48.     private static Map[] loadValidityRuleAndCreateValidityJsFile(Class currClass) throws IllegalArgumentException,   
  49.             IllegalAccessException, SecurityException, NoSuchMethodException, InvocationTargetException, IOException {   
  50.         StringBuffer validityCanNotNullJsStrBuf = new StringBuffer();   
  51.         StringBuffer validityIsIntegerJsStrBuf = new StringBuffer();   
  52.         Field[] fieldArr = currClass.getDeclaredFields();   
  53.         List<String> canNotNullFieldNameList = new ArrayList<String>();   
  54.         List<IsIntegerValiditerRuleInfo> isIntegerValiditerRuleInfoList = new ArrayList<IsIntegerValiditerRuleInfo>();   
  55.         Map<String, String> fieldDescMap = new HashMap<String, String>();   
  56.         for (int i = 0; i < fieldArr.length; i++) {   
  57.             String currFieldName = fieldArr[i].getName();   
  58.             //读入字段描述 信息   
  59.             FieldDesc fieldDescAnnotation = fieldArr[i].getAnnotation(FieldDesc.class);   
  60.             if (fieldDescAnnotation != null) {   
  61.                 String fieldDesc = fieldDescAnnotation.value();   
  62.                 System.out.println(fieldDesc);   
  63.                 fieldDescMap.put(currFieldName, fieldDesc);   
  64.             }   
  65.             else {   
  66.                 fieldDescMap.put(currFieldName, currFieldName);   
  67.             }   
  68.             //读入非空验证信息   
  69.             if (fieldArr[i].isAnnotationPresent(CanNotNull.class)) {                   
  70.                 canNotNullFieldNameList.add(currFieldName);   
  71.                 validityCanNotNullJsStrBuf.append("if(document.all." + currFieldName + ".value.trim()==\"\"){alert('"  
  72.                         + fieldDescMap.get(currFieldName) + "不可以为空');}\n");   
  73.             }   
  74.             //读入整数验证信息   
  75.             IsInteger isIntegerAnnotation = fieldArr[i].getAnnotation(IsInteger.class);   
  76.             if (isIntegerAnnotation != null) {   
  77.                 int minWidth = isIntegerAnnotation.minWidth();   
  78.                 int maxWidth = isIntegerAnnotation.maxWidth();   
  79.                 int minValue = isIntegerAnnotation.minValue();   
  80.                 int maxValue = isIntegerAnnotation.maxValue();   
  81.                 IsIntegerValiditerRuleInfo isIntegerValiditerRuleInfo = new IsIntegerValiditerRuleInfo(currFieldName,   
  82.                         minWidth, maxWidth, minValue, maxValue);   
  83.                 isIntegerValiditerRuleInfoList.add(isIntegerValiditerRuleInfo);   
  84.                 if (minWidth > 0) {   
  85.                     validityIsIntegerJsStrBuf.append("if(document.all." + currFieldName   
  86.                             + ".value.length()<minWidth){alert('" + fieldDescMap.get(currFieldName) + "宽度不够!');}\n");   
  87.                 }   
  88.                 if (maxWidth < Integer.MAX_VALUE) {   
  89.                     validityIsIntegerJsStrBuf.append("if(document.all." + currFieldName   
  90.                             + ".value.length()>maxWidth){alert('" + fieldDescMap.get(currFieldName) + "宽度太长!');}\n");   
  91.                 }   
  92.                 if (minValue > Integer.MIN_VALUE) {   
  93.                     validityIsIntegerJsStrBuf.append("if(document.all." + currFieldName + ".value*1<minValue){alert('"  
  94.                             + fieldDescMap.get(currFieldName) + "的数值太小!');}\n");   
  95.                 }   
  96.                 if (maxValue < Integer.MAX_VALUE) {   
  97.                     validityIsIntegerJsStrBuf.append("if(document.all." + currFieldName + ".value*1>maxValue){alert('"  
  98.                             + fieldDescMap.get(currFieldName) + "的数值太大!');}\n");   
  99.                 }   
  100.             }   
  101.         }   
  102.         Map<String, List> classValidityRuleMap = new HashMap<String, List>();   
  103.         classValidityRuleMap.put("canNotNullFieldNameList", canNotNullFieldNameList);   
  104.         classValidityRuleMap.put("isIntegerValiditerRuleInfoList", isIntegerValiditerRuleInfoList);   
  105.         //根据这些信息生成JS代码   
  106.         BufferedWriter jsFileWriter = new BufferedWriter(new FileWriter(new File(jsValiditerFilePath   
  107.                 + java.io.File.separator + currClass.getName() + ".js")));   
  108.         jsFileWriter.write(validityCanNotNullJsStrBuf.toString());   
  109.         jsFileWriter.write(validityIsIntegerJsStrBuf.toString());   
  110.         jsFileWriter.close();   
  111.         return new Map[] { classValidityRuleMap, fieldDescMap };   
  112.   
  113.     }   
  114.     /*  
  115.      * 具体的后台验证过程  
  116.      */  
  117.   
  118.     public static ValidityResult validity(Object currObj) throws IllegalArgumentException, IllegalAccessException,   
  119.             SecurityException, NoSuchMethodException, InvocationTargetException {   
  120.         Class aClass = currObj.getClass();   
  121.         String classFullName = aClass.getPackage().getName() + "." + aClass.getName();   
  122.         Field[] fieldArr = aClass.getDeclaredFields();   
  123.   
  124.         Map validityRuleMap = allValidityRuleMap.get(classFullName);   
  125.         Map fieldDescMap = allFieldDescMap.get(classFullName);   
  126.         List canNotNullFieldNameList = (List) validityRuleMap.get("canNotNullFieldNameList");   
  127.         List isIntegerValiditerRuleInfoList = (List) validityRuleMap.get("isIntegerValiditerRuleInfoList");   
  128.         ValidityResult validityResult = new ValidityResult();   
  129.         for (int j = 0; j < canNotNullFieldNameList.size(); j++) {   
  130.             String currFieldName = (String) canNotNullFieldNameList.get(j);   
  131.             String getMethodName = "get" + currFieldName.substring(01).toUpperCase() + currFieldName.substring(1);   
  132.             Method getFieldValueMethod = aClass.getMethod(getMethodName);   
  133.             String fieldValue = ((String) getFieldValueMethod.invoke(currObj));   
  134.             if (fieldValue == null || fieldValue.equals("")) {   
  135.                 System.out.println(fieldDescMap.get(currFieldName) + " 不可以为空 ! ");   
  136.                 validityResult.addValidityInfo(fieldDescMap.get(currFieldName) + " 不可以为空 ! ");   
  137.             }   
  138.         }   
  139.   
  140.         for (int j = 0; j < isIntegerValiditerRuleInfoList.size(); j++) {   
  141.             IsIntegerValiditerRuleInfo isIntegerValiditerRuleInfo = (IsIntegerValiditerRuleInfo) isIntegerValiditerRuleInfoList   
  142.                     .get(j);   
  143.             String currFieldName = isIntegerValiditerRuleInfo.getFieldName();   
  144.             String getMethodName = "get" + currFieldName.substring(01).toUpperCase() + currFieldName.substring(1);   
  145.             Method getFieldValueMethod = aClass.getMethod(getMethodName);   
  146.             String fieldValue = ((String) getFieldValueMethod.invoke(currObj));   
  147.             int minWidth = isIntegerValiditerRuleInfo.getMinWidth();   
  148.             int maxWidth = isIntegerValiditerRuleInfo.getMaxWidth();   
  149.             int minValue = isIntegerValiditerRuleInfo.getMinValue();   
  150.             int maxValue = isIntegerValiditerRuleInfo.getMaxValue();   
  151.   
  152.             if (StringUtils.isInteger(fieldValue)) {   
  153.                 if (fieldValue.length() < minWidth) {   
  154.                     validityResult.addValidityInfo(fieldDescMap.get(currFieldName) + " 宽度不可以小于 " + minWidth + "! ");   
  155.                 }   
  156.                 if (fieldValue.length() > maxWidth) {   
  157.                     validityResult.addValidityInfo(fieldDescMap.get(currFieldName) + " 宽度不可以大于 " + maxWidth + "! ");   
  158.                 }   
  159.                 if (Integer.parseInt(fieldValue) < minValue) {   
  160.                     validityResult.addValidityInfo(fieldDescMap.get(currFieldName) + " 的值不可以小于 " + minValue + "! ");   
  161.                 }   
  162.                 if (Integer.parseInt(fieldValue) > maxValue) {   
  163.                     validityResult.addValidityInfo(fieldDescMap.get(currFieldName) + " 的值不可以大于 " + maxValue + "! ");   
  164.                 }   
  165.   
  166.             }   
  167.             else {   
  168.   
  169.                 validityResult.addValidityInfo(fieldDescMap.get(currFieldName) + " 必须是整数格式 ! ");   
  170.   
  171.             }   
  172.         }   
  173.         return validityResult;   
  174.   
  175.     }   
  176.   
  177.     public static String[] getPojoBeanPackageName() {   
  178.         return pojoBeanPackageName;   
  179.     }   
  180.   
  181.     public static void setPojoBeanPackageName(String[] pojoBeanPackageName) {   
  182.         PojoBeanAnnotationValiditer.pojoBeanPackageName = pojoBeanPackageName;   
  183.     }   
  184.   
  185.     public static String getJsValiditerFilePath() {   
  186.         return jsValiditerFilePath;   
  187.     }   
  188.   
  189.     public static void setJsValiditerFilePath(String jsValiditerFilePath) {   
  190.         PojoBeanAnnotationValiditer.jsValiditerFilePath = jsValiditerFilePath;   
  191.     }   
  192.   
  193.     public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, SecurityException,   
  194.             NoSuchMethodException, InvocationTargetException, ClassNotFoundException, IOException {   
  195.         PojoBeanAnnotationValiditer.setPojoBeanPackageName(new String[] { "com.javaest.validity.test.pojo" });   
  196.         PojoBeanAnnotationValiditer.setJsValiditerFilePath("JS\\VALIDITY");   
  197.         PojoBeanAnnotationValiditer   
  198.                 .loadAllClassAnnotationValidityInfoInPackage(new String[] { "com.javaest.validity.test.pojo" });   
  199.         Student aStudent = new Student();   
  200.         aStudent.setAddress("吉林省长春市二道区");   
  201.         aStudent.setId("");   
  202.         aStudent.setAge("9");   
  203.         ValidityResult validityResult = PojoBeanAnnotationValiditer.validity(aStudent);   
  204.     }   
  205.   
  206. }</SPAN>  


下边是一个加好了标注的Student类

  1. public class Student {   
  2.     @CanNotNull    
  3.     @FieldDesc("姓名")   
  4.     private String name;   
  5.     @CanNotNull    
  6.     @FieldDesc("性别")   
  7.     private String sex;   
  8.     @IsInteger(minValue=18,maxValue=60)   
  9.     @CanNotNull  
  10.     @FieldDesc("年龄")   
  11.     private String age;   
  12.     @CanNotNull  
  13.     @FieldDesc("编码")   
  14.     private String id;   
  15.     private String address;   
  16.     public String getName() {   
  17.         return name;   
  18.     }   
  19.     public void setName(String name) {   
  20.         this.name = name;   
  21.     }   
  22.     public String getSex() {   
  23.         return sex;   
  24.     }   
  25. 。。。。。。。。。。   
  26. }  


在家闲着写代码真好。
posted on 2008-04-17 09:37 javaest 阅读(1875) 评论(7)  编辑  收藏

评论:
# re: 基于JAVA标注实现统一的前台(JS层)后台(JAVA层) 2008-04-17 10:57 | Libo
这个思路不错.hibernate validator 只是实现后台的验证.如果能和这个结合起来可能用途会更广泛.  回复  更多评论
  
# re: 基于JAVA标注实现统一的前台(JS层)后台(JAVA层) 2008-06-02 17:57 | 懒人
你家是二道区的么?  回复  更多评论
  
# re: 基于JAVA标注实现统一的前台(JS层)后台(JAVA层)[未登录] 2008-06-05 13:12 | javaest
@懒人
对,你如果知道?
  回复  更多评论
  
# re: 基于JAVA标注实现统一的前台(JS层)后台(JAVA层) 2008-08-04 09:52 | 残梦追月
不错,是不是可以使用正则表达式来验证呢?就是说在使用的时候,只有一个标记,里面有个参数,输入正则表达式…………就可用验证了。  回复  更多评论
  
# re: 基于JAVA标注实现统一的前台(JS层)后台(JAVA层) 2008-08-04 09:53 | 残梦追月
他看的这里:

aStudent.setAddress("吉林省长春市二道区");   回复  更多评论
  
# re: 基于JAVA标注实现统一的前台(JS层)后台(JAVA层)[未登录] 2010-04-14 09:59 | fangjava
能看到  回复  更多评论
  
# re: 基于JAVA标注实现统一的前台(JS层)后台(JAVA层)[未登录] 2010-04-14 10:00 | fangjava
能看到我的留言么??  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: