Validation.FO 使用指南
框架說明
這是一個驗證框架,並且是一個 獨立的驗證框架 ,不依賴與其他已有的框架;
可以自由的嵌入到其他框架,比如Spring、Struts等流行框架,但實質來說他是獨立的,所以無所謂嵌入到哪裏,如果需要在GUI桌面應用中,也是完美的;
配置簡單,可自由擴展驗證器,實際只要實現IValidator接口,以及在rules.fo.xml中添加相關的配置即可;
支持Spring接口
使用過程中,你會感覺好像只用了
IValidateService.validate()
一個方法,這會讓人感覺良好
優點
不與任何對象做綁定,最大限度解耦
只要規則配置寫的合理,規則可以複用到多個對象
擴展驗證器很簡單
以Map存儲驗證結果,非常簡單的導出JSON,只要你願意
相關文檔
DEMO案例源代碼,Validation.FO Demo
如何下載
Maven依賴 或 直接下載Validation.FO包
<dependency> <groupId>cc.fozone.validation</groupId> <artifactId>fo-validation</artifactId> <version>0.9.1.RELEASE</version> </dependency>
(必須) 下載配置文件 Validation.FO-CONFIGURATION
快速開始
使用Validation.FO的步驟如下:
配置驗證規則
rules.fo.xml
實例化
IValidateService
對象調用
IValidateService.validate
方法
基本的使用方法
源代碼地址:Basic Usage
1. 創建POJO對象 User.java
package validationfo.basic; import java.sql.Timestamp; /** * 用戶對象 * @author Jimmy Song * */ public class User { // 用戶名 private String username; // 密碼 private String password; // 再次輸入密碼 private String passwordOne; // 郵箱 private String email; // 開始與結束時間 private Timestamp starttime; private Timestamp endtime; /** * Setter & Getter */ ... }
2. 配置驗證規則 rules.fo.xml
<include file=""/>
導入其他規則文件<group name=""></group>
驗證分組,name應該爲全局唯一的<field name=""></field>
驗證的字段,name是被驗證對象的屬性字段名<rule name="" message=""></rule>
驗證規則,name是驗證器名稱,message是錯誤後返回的消息<param name="" value=""></param>
是驗證規則時可能需要傳入的參數,name是參數名,value是參數值
<?xml version="1.0" encoding="UTF-8"?> <fozone-validation> <!-- include 標籤導入其他配置 --> <include file="validationinfo/basic/another-rules.fo.xml"/> <!-- 驗證組ID,全局唯一 --> <group name="user.validate"> <!-- 驗證字段 --> <field name="email"> <!-- 規則列表 --> <rule name="required" message="郵件必須填寫"/> <rule name="between" message="郵件長度應該3-100之間"> <param name="min" value="3"/> <param name="max" value="100"/> </rule> <rule name="match" message="郵件格式不正確"> <param name="regex" value="^[A-Za-z]+[\.\-_A-Za-z0-9]*@[A-Za-z0-9]+[\.\-_A-Za-z0-9]*$"/> </rule> </field> ... </group> </fozone-validation>
3. 實例化測試 BasicTest.java
主要步驟:
創建配置讀取對象
IValidateConfig
創建驗證服務對象
IValidateService
執行驗證方法
IValidateService.validate(object, groupId)
package validationfo.basic; ... /** * 最基本的測試 * @author Jimmy Song * */ public class BasicTest { public static void main(String[] args) { /** * Validation.FO的配置資源 */ // 驗證器配置,系統默認配置 String validatorsXML = "validationfo/basic/validators.fo.xml"; // 規則配置 String rulesXML = "validationfo/basic/rules.fo.xml"; /** * 實例化配置對象 */ IValidateConfig config =new BasicValidateConfig(validatorsXML, rulesXML); /** * 實例化驗證服務層 */ IValidateService validateService = new BasicValidateService(config); // 實例化用戶 User user = createUser(); /** * 執行驗證 */ Map<String,String> map = validateService.validate(user, "user.validate"); // 輸出結果 if(map == null || map.size() == 0) { System.out.println("驗證成功"); } else { System.out.println("驗證失敗,結果如下"); System.out.println(map); } } }
4. 結果輸出
12:31:41,084 INFO BasicValidateConfig:44 - read validation main file , validationfo/basic/rules.fo.xml 驗證失敗,結果如下 {email=郵件格式不正確, password=兩次密碼輸入不正確, starttime=開始時間不能大於結束時間, endtime=結束時間不能小於開始時間}
如何在Spring中使用
在Spring中需要使用
SpringValidateConfg
配置對象需要額外配置
SpringValidator
Bean對象
1. 配置Spring配置 context.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <!-- 基於 Spring 配置讀取 --> <bean id="springValidateConfig" class="cc.fozone.validation.config.SpringValidateConfig"> <property name="validators"> <value>validationfo/spring/validators.fo.xml</value> </property> <property name="rules"> <value>validationfo/spring/rules.fo.xml</value> </property> </bean> <!-- 配置驗證服務 --> <bean id="basicValidateService" class="cc.fozone.validation.BasicValidateService"> <constructor-arg index="0" ref="springValidateConfig"/> </bean> <!-- 配置基於Spring的驗證器 --> <bean class="cc.fozone.validation.validators.SpringValidator"/> </beans>
2. 如何通過Spring進行驗證,SpringTest.java
public class SpringTest { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "validationfo/spring/context.xml"); // 獲取驗證服務 IValidateService service = context.getBean(IValidateService.class); // 創建用戶對象 User user = createUser(); // 執行驗證 Map<String, String> map = service.validate(user, "user.validate"); // 輸出結果 if (map == null || map.size() == 0) { System.out.println("驗證成功"); } else { System.out.println("驗證失敗,結果如下"); System.out.println(map); } } }
3. 執行結果
13:26:00,150 INFO ClassPathXmlApplicationContext:510 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@283b4947: startup date [Tue Oct 07 13:26:00 CST 2014]; root of context hierarchy 13:26:00,194 INFO XmlBeanDefinitionReader:315 - Loading XML bean definitions from class path resource [validationfo/spring/context.xml] 13:26:00,373 INFO DefaultListableBeanFactory:598 - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@212b0f8a: defining beans [springValidateConfig,basicValidateService,cc.fozone.validation.validators.SpringValidator#0]; root of factory hierarchy 13:26:00,442 INFO BasicValidateConfig:44 - read validation main file , validationfo/spring/rules.fo.xml 驗證失敗,結果如下 {email=郵件格式不正確, password=兩次密碼輸入不正確, starttime=開始時間不能大於結束時間, endtime=結束時間不能小於開始時間}
Validator驗證器與規則
系統默認的驗證器文件 validators.fo.xml
<?xml version="1.0" encoding="UTF-8"?> <fozone-validators> <validator name="required" class="cc.fozone.validation.validators.RequiredValidator"/> <validator name="match" class="cc.fozone.validation.validators.MatchValidator"/> <validator name="between" class="cc.fozone.validation.validators.BetweenValidator"/> <validator name="min" class="cc.fozone.validation.validators.MinValidator"/> <validator name="max" class="cc.fozone.validation.validators.MaxValidator"/> <validator name="equals" class="cc.fozone.validation.validators.EqualsValidator"/> <validator name="timestampLessEqual" class="cc.fozone.validation.validators.TimestampLessEqualValidator"/> <validator name="timestampCreaterEqual" class="cc.fozone.validation.validators.TimestampCreaterEqualValidator"/> <validator name="spring" useSpring="true" class="cc.fozone.validation.validators.SpringValidator"/> </fozone-validators>
默認驗證規則
required
- 必填字段
消息message: 必填
參數param: 無
案例:
<group name="user.validate"> <field name="username"> <rule name="required" message="姓名必須填寫。"/> </field> </group>
match
- 正則匹配
消息message: 必填
參數param: 有
Name | Must | Description |
---|---|---|
regex | Yes | 正則表達式,如果爲空,驗證直接返回true |
案例:
<group name="user.validate"> <field name="email"> <rule name="match" message="郵件格式不正確"> <param name="regex" value="^[A-Za-z]+[\.\-_A-Za-z0-9]*@[A-Za-z0-9]+[\.\-_A-Za-z0-9]*$"/> </rule> </field> </group>
between
- 判斷字符串或數組非空長度是否介於兩者之間,min <= length <= max
消息message: 必填
參數param: 有
Name | Must | Description |
---|---|---|
min | Yes | 最小長度(包含) |
max | Yes | 最大長度(包含) |
案例:
<group name="user.validate"> <field name="email"> <rule name="between" message="郵件長度應該3-100之間"> <param name="min" value="3"/> <param name="max" value="100"/> </rule> </field> </group>
min
- 判斷字符串或數組非空長度是否大於等於最小長度,length >= min
消息message: 必填
參數param: 有
Name | Must | Description |
---|---|---|
value | Yes | 最小長度(包含) |
案例:
<group name="user.validate"> <field name="password"> <rule name="min" message="密碼至少5個字符"> <param name="value" value="5"/> </rule> </field> </group>
max
- 判斷字符串或數組非空長度是否小於等於最大長度,length <= max
消息message: 必填
參數param: 有
Name | Must | Description |
---|---|---|
value | Yes | 最大長度(包含) |
案例:
<group name="user.validate"> <field name="password"> <rule name="max" message="密碼最多20個字符"> <param name="value" value="20"/> </rule> </field> </group>
equals
- 判斷字段是否與指定的字段值是否相同
消息message: 必填
參數param: 有
Name | Must | Description |
---|---|---|
target | Yes | 指定的字段名稱,並非確定的值 |
案例:
POJO對象部分字段
public class User { private String password; private String passwordOne; }
<group name="user.validate"> <field name="password"> <rule name="equals" message="兩次輸入的密碼不相同"> <param name="target" value="passwordOne"/> </rule> </field> </group>
注:這裏會將
password
與目標passwordOne
字段的值進行equals
比較
有些時候你可能需要重寫equals
方法
timestampLessEqual
- 時間戳是否小於等於指定的目標時間字段
消息message: 必填
參數param: 有
Name | Must | Description |
---|---|---|
target | Yes | 指定的時間字段名稱,並非確定的值 |
案例:
POJO對象部分字段
public class User { private Timestamp starttime; private Timestamp endtime; }
<group name="user.validate"> <field name="starttime"> <rule name="timestampLessEqual" message="開始時間不能大於結束時間"> <param name="target" value="endtime"/> </rule> </field> </group>
注:
這裏會將
starttime
與目標endtime
字段的值進行大小比較這裏的字段必須是
java.sql.Timestamp
類型
timestampCreaterEqual
- 時間戳是否大於等於指定的目標時間字段
消息message: 必填
參數param: 有
Name | Must | Description |
---|---|---|
target | Yes | 指定的時間字段名稱,並非確定的值 |
案例:
POJO對象部分字段
public class User { private Timestamp starttime; private Timestamp endtime; }
<group name="user.validate"> <field name="endtime"> <rule name="timestampCreaterEqual" message="結束時間不能小於開始時間"> <param name="target" value="starttime"/> </rule> </field> </group>
注:
這裏會將
endtime
與目標starttime
字段的值進行大小比較這裏的字段必須是
java.sql.Timestamp
類型
spring
- 通過Spring調用其他對象的指定方法進行判斷
DEMO: 點擊查看
消息message: 必填
參數param: 有
Name | Must | Description |
---|---|---|
beanName | Yes | Spring Context中的Bean標識 |
methodName | Yes | Bean對象中的指定執行方法,該方法必須返回 boolean 類型 |
parameterName | No | 執行方法中傳遞的參數,**默認** 傳遞被驗證字段的值,如果使用**this** 表示傳遞被驗證的對象, 其他 表示傳遞對象指定的字段 |
案例:
POJO對象部分字段
public class User { private String username; private int usernameLength; }
驗證配置
<group name="user.validate"> <field name="username"> <rule name="spring" message="該用戶已存在"> <param name="beanName" value="userService"/> <param name="methodName" value="exist"/> </rule> </field> <field name="usernameLength"> <!-- 使用 this 關鍵字 --> <rule name="spring" message="用戶名長度驗證錯誤"> <param name="beanName" value="userService"/> <param name="methodName" value="length"/> <param name="parameter" value="this"/> </rule> <!-- 指定字段 --> <rule name="spring" message="用戶名長度不能小於5個字符"> <param name="beanName" value="userService"/> <param name="methodName" value="lengthByName"/> <param name="parameter" value="username"/> </rule> </field> </group>
Spring中的配置
<beans> <!-- 通過Spring進行驗證 --> <bean id="userService" class="validationfo.springadvance.UserService"/> </beans>
通過Spring驗證的接口
package validationfo.springadvance; public class UserService { public boolean exist(String value) { return !"superman".equals(value); } public boolean length(User user){ return user.getUsername().length() == user.getUsernameLength(); } public boolean lengthByName(String username){ return username.length() >= 5; } }
注:
要啓用spring配置,需要參照上述的 如何在Spring使用 進行Spring與Validation.FO的整合配置
指定的對象方法必須返回 boolean 類型
高級部分:如何自定義驗證器 IValidator
實現
IValidator
接口在
validators.fo.xml
驗證器配置中添加已實現的驗證器
一個簡單的例子
POJO對象
package validationfo.custom; public class Money { private int number; private String text; ... }
CustomValidator實現
package validationfo.custom; /** * 構造一個判斷 參數 是否能夠被 指定的值 整出的驗證器 * 例如:對象值爲4 ,驗證參數爲2,那麼 4可以被2整除,表示成功 * * @author Jimmy Song * */ public class CustomValidator implements IValidator { private static final Logger logger = Logger.getLogger(CustomValidator.class); /** * 要處理的對象 * @param context 上下文 * @param type 對象類型 * @param value 對象值 * @param rule 對象參數 * @return 是否成功 */ public boolean execute(Object context, Class type, Object value, Rule rule) { // TODO Auto-generated method stub /** * 這裏只是演示一下context的用處 * 可以通過context以及反射獲取對象的屬性值 * 舉個例子 */ try { System.out.println("TEXT = "+PropertyUtils.getProperty(context, "text")); } catch (Exception e1) { // TODO Auto-generated catch block } /** * 通過 value 實際驗證的值 */ if(value == null) return true; /** * 通過 type 獲取值的類型 */ if(!(type == Integer.class || type == int.class)) { return false; } int objectValue = ((Integer)value).intValue(); /** * 通過 rule 獲取規則參數 */ String toValue = rule.getParameter("value"); if(StringUtils.isBlank(toValue)) return false; int intValue = -1; try { intValue = Integer.parseInt(toValue); } catch(NumberFormatException e){ logger.error("倍數值轉換錯誤!"); return false; } if(intValue <= 0) { logger.warn("倍數值不能小於等於0"); return false; } return objectValue % intValue == 0; } }
配置 validators.fo.xml 中添加自定義驗證器
關於validators.fo.xml配置的參數說明
語法 : <validator name="" useSpring="true|false" class="" beanId=""/>
參數名 | 必填 | 含義 |
---|---|---|
name | 是 | 驗證器名稱 |
useSpring | 否 | 是否通過 Spring 實例化驗證器,這樣做可以爲驗證器注入 ApplicationContext |
class | 否 | 當 useSpring=false 時,按照正常的方式進行實例化;當 useSpring=true 時,且使用了 beanId ,則 class 無效,如果沒有使用 beanId ,那麼 Spring 通過 class 進行實例化 |
beanId | 否 | Spring中的bean id |
<?xml version="1.0" encoding="UTF-8"?> <fozone-validators> ... <validator name="custom" class="validationfo.custom.CustomValidator"/> </fozone-validators>
配置驗證規則
<?xml version="1.0" encoding="UTF-8"?> <fozone-validation> <!-- 驗證組ID,全局唯一 --> <group name="money.validate"> <!-- 驗證字段 --> <field name="number"> <rule name="custom" message="驗證失敗,不能被指定的數整除"> <param name="value" value="3"/> </rule> </field> </group> </fozone-validation>
執行測試
package validationfo.custom; public class CustomTest { public static void main(String[] args) { /** * Validation.FO的配置資源 */ // 驗證器配置,系統默認配置 String validatorsXML = "validationfo/custom/validators.fo.xml"; // 規則配置 String rulesXML = "validationfo/custom/rules.fo.xml"; /** * 實例化配置對象 */ IValidateConfig config =new BasicValidateConfig(validatorsXML, rulesXML); /** * 實例化驗證服務層 */ IValidateService validateService = new BasicValidateService(config); // 實例化數據 Money money = new Money(); money.setNumber(7); money.setText("演示Context使用的Text"); /** * 執行驗證 */ Map<String,String> map = validateService.validate(money, "money.validate"); // 輸出結果 if(map == null || map.size() == 0) { System.out.println("驗證成功"); } else { System.out.println("驗證失敗,結果如下"); System.out.println(map); } } }
結果輸出
16:44:17,178 INFO BasicValidateConfig:44 - read validation main file , validationfo/custom/rules.fo.xml TEXT = 演示Context使用的Text 驗證失敗,結果如下 {number=驗證失敗,不能被指定的數整除}