Java注解Annotation用起來很方便,也越來越流行,由于其簡單、簡練且易于使用等特點,很多開發工具都提供了注解功能,不好的地方就是代碼入侵比較嚴重,所以使用的時候要有一定的選擇性。
這篇文章將利用注解,來做一個Bean的數據校驗。
下載
http://download.csdn.net/download/hanghangaidoudou/10139375
項目結構?
定義注解
該注解可以驗證成員屬性是否為空,長度,提供了幾種常見的正則匹配,也可以使用自定義的正則去判斷屬性是否合法,同時可以為該成員提供描述信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | package ?org.xdemo.validation.annotation; import ?java.lang.annotation.ElementType; import ?java.lang.annotation.Retention; import ?java.lang.annotation.RetentionPolicy; import ?java.lang.annotation.Target; import ?org.xdemo.validation.RegexType; /** ? *?數據驗證 ? *?@author?Goofy ? */ @Retention (RetentionPolicy.RUNTIME) @Target ({ElementType.FIELD,ElementType.PARAMETER}) public ?@interface ?DV?{ ???? ????? //是否可以為空 ???? boolean ?nullable()? default ?false ; ???? ????? //最大長度 ???? int ?maxLength()? default ?0 ; ???? ????? //最小長度 ???? int ?minLength()? default ?0 ; ???? ????? //提供幾種常用的正則驗證 ???? RegexType?regexType()? default ?RegexType.NONE; ???? ????? //自定義正則驗證 ???? String?regexExpression()? default ?"" ; ???? ????? //參數或者字段描述,這樣能夠顯示友好的異常信息 ???? String?description()? default ?"" ; } |
注解的解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | package ?org.xdemo.validation.annotation.support; import ?java.lang.reflect.Field; import ?org.xdemo.validation.RegexType; import ?org.xdemo.validation.annotation.DV; import ?org.xdemo.validation.utils.RegexUtils; import ?org.xdemo.validation.utils.StringUtils; /** ? *?注解解析 ? *?@author?Goofy ? */ public ?class ?ValidateService?{ ???? ????? private ?static ?DV?dv; ???? ????? public ?ValidateService()?{ ???????? super (); ???? } ???? ????? //解析的入口 ???? public ?static ?void ?valid(Object?object)? throws ?Exception{ ???????? //獲取object的類型 ???????? Class<?? extends ?Object>?clazz=object.getClass(); ???????? //獲取該類型聲明的成員 ???????? Field[]?fields=clazz.getDeclaredFields(); ???????? //遍歷屬性 ???????? for (Field?field:fields){ ???????????? //對于private私有化的成員變量,通過setAccessible來修改器訪問權限 ???????????? field.setAccessible( true ); ???????????? validate(field,object); ???????????? //重新設置會私有權限 ???????????? field.setAccessible( false ); ???????? } ???? } ???? ????? ????? public ?static ?void ?validate(Field?field,Object?object)? throws ?Exception{ ???????? String?description; ???????? Object?value; ???????? //獲取對象的成員的注解信息 ???????? dv=field.getAnnotation(DV. class ); ???????? value=field.get(object); ???????? ????????? if (dv== null ) return ; ???????? ????????? description=dv.description().equals( "" )?field.getName():dv.description(); ???????? ????????? /*************注解解析工作開始******************/ ???????? if (!dv.nullable()){ ???????????? if (value== null ||StringUtils.isBlank(value.toString())){ ???????????????? throw ?new ?Exception(description+ "不能為空" ); ???????????? } ???????? } ???????? ????????? if (value.toString().length()>dv.maxLength()&&dv.maxLength()!= 0 ){ ???????????? throw ?new ?Exception(description+ "長度不能超過" +dv.maxLength()); ???????? } ???????? ????????? if (value.toString().length()<dv.minLength()&&dv.minLength()!= 0 ){ ???????????? throw ?new ?Exception(description+ "長度不能小于" +dv.minLength()); ???????? } ???????? ????????? if (dv.regexType()!=RegexType.NONE){ ???????????? switch ?(dv.regexType())?{ ???????????????? case ?NONE: ???????????????????? break ; ???????????????? case ?SPECIALCHAR: ???????????????????? if (RegexUtils.hasSpecialChar(value.toString())){ ???????????????????????? throw ?new ?Exception(description+ "不能含有特殊字符" ); ???????????????????? } ???????????????????? break ; ???????????????? case ?CHINESE: ???????????????????? if (RegexUtils.isChinese2(value.toString())){ ???????????????????????? throw ?new ?Exception(description+ "不能含有中文字符" ); ???????????????????? } ???????????????????? break ; ???????????????? case ?EMAIL: ???????????????????? if (!RegexUtils.isEmail(value.toString())){ ???????????????????????? throw ?new ?Exception(description+ "地址格式不正確" ); ???????????????????? } ???????????????????? break ; ???????????????? case ?IP: ???????????????????? if (!RegexUtils.isIp(value.toString())){ ???????????????????????? throw ?new ?Exception(description+ "地址格式不正確" ); ???????????????????? } ???????????????????? break ; ???????????????? case ?NUMBER: ???????????????????? if (!RegexUtils.isNumber(value.toString())){ ???????????????????????? throw ?new ?Exception(description+ "不是數字" ); ???????????????????? } ???????????????????? break ; ???????????????? case ?PHONENUMBER: ???????????????????? if (!RegexUtils.isPhoneNumber(value.toString())){ ???????????????????????? throw ?new ?Exception(description+ "不是數字" ); ???????????????????? } ???????????????????? break ; ???????????????? default : ???????????????????? break ; ???????????? } ???????? } ???????? ????????? if (!dv.regexExpression().equals( "" )){ ???????????? if (value.toString().matches(dv.regexExpression())){ ???????????????? throw ?new ?Exception(description+ "格式不正確" ); ???????????? } ???????? } ???????? /*************注解解析工作結束******************/ ???? } } |
用到的幾個類
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package ?org.xdemo.validation; /** ? *?常用的數據類型枚舉 ? *?@author?Goofy ? * ? */ public ?enum ?RegexType?{ ???? ????? NONE, ???? SPECIALCHAR, ???? CHINESE, ???? EMAIL, ???? IP,? ???? NUMBER, ???? PHONENUMBER; ???? ?} |
其中正則驗證類和字符串工具類請參考以下鏈接:
-
SuperUtil之RegexUtils
-
SuperUtil之StringUtils
使用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | package ?org.xdemo.validation.test; import ?org.xdemo.validation.RegexType; import ?org.xdemo.validation.annotation.DV; public ?class ?User?{ ???? ????? @DV (description= "用戶名" ,minLength= 6 ,maxLength= 32 ,nullable= false ) ???? private ?String?userName; ???? ????? private ?String?password; ???? ????? @DV (description= "郵件地址" ,nullable= false ,regexType=RegexType.EMAIL) ???? private ?String?email; ???? ????? ????? public ?User(){} ???? ????? public ?User(String?userName,?String?password,?String?email)?{ ???????? super (); ???????? this .userName?=?userName; ???????? this .password?=?password; ???????? this .email?=?email; ???? } ???? ????? ????? ????? public ?String?getUserName()?{ ???????? return ?userName; ???? } ???? public ?void ?setUserName(String?userName)?{ ???????? this .userName?=?userName; ???? } ???? public ?String?getPassword()?{ ???????? return ?password; ???? } ???? public ?void ?setPassword(String?password)?{ ???????? this .password?=?password; ???? } ???? public ?String?getEmail()?{ ???????? return ?email; ???? } ???? public ?void ?setEmail(String?email)?{ ???????? this .email?=?email; ???? } } |
測試代碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | package ?org.xdemo.validation.test; import ?org.xdemo.validation.annotation.support.ValidateService; /** ? *?@author?Goofy ? */ public ?class ?Test?{ ???? public ?static ?void ?main(String[]?args){ ???????? User?user= new ?User( "張三" ,? "xdemo.org" ,? "252878950@qq.com" ); ???????? try ?{ ???????????? ValidateService.valid(user); ???????? }? catch ?(Exception?e)?{ ???????????? e.printStackTrace(); ???????? } ???????? user= new ?User( "zhangsan" , "xdemo.org" , "xxx@" ); ???????? try ?{ ???????????? ValidateService.valid(user); ???????? }? catch ?(Exception?e)?{ ???????????? e.printStackTrace(); ???????? } ???????? user= new ?User( "zhangsan" , "xdemo.org" , "" ); ???????? try ?{ ???????????? ValidateService.valid(user); ???????? }? catch ?(Exception?e)?{ ???????????? e.printStackTrace(); ???????? } ???? } } |
運行效果