章節清單
- 第一章:使用Validator做SpringMVC的驗證架構 - 配置SpringMVC環境
- 第二章:使用Validator做SpringMVC的驗證架構 - 使用Validator
- 第三章:使用Validator做SpringMVC的驗證架構 - Validator前端驗證
- 第四章:使用Validator做SpringMVC的驗證架構 - 自定義驗證元件
前面的幾章已經為大家簡單的介紹了Validator的功能已經使用方法,下面接着為大家介紹怎麼使用Validator自定義驗證元件
Validator架構源碼位址:https://github.com/devefx/validator
1 - 建立背景驗證元件
大家可能發現了,我們前面的注冊功能少了一個很重要的參數,那就是驗證碼。衆所周知驗證是為了防止機器人惡意注冊的,這一步的驗證是需要與伺服器進行資料互動的驗證,不是簡單資料格式判斷就能知道正誤的。下面我讓大家看看Validator架構強大的擴充性
首先修改一下register.jsp,在“個人首頁”下面添加一個”驗證碼“
<tr>
<td>個人首頁:</td>
<td><input name="homepage"></td>
</tr>
<!-- 驗證碼輸入框 -->
<tr>
<td>驗證碼:</td>
<td><input name="code" placeholder="請輸入1234"></td>
</tr>
接着我們建立一個“com.devefx.website.validator.constraints”包用來放我們自定義的背景驗證元件,同時建立一個java源碼檔案“CodeValidator”作為驗證碼驗證元件。
CodeValidator.java
package com.devefx.website.validator.constraints;
import java.io.IOException;
import java.io.Writer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import com.devefx.validation.annotation.BindScript;
import com.devefx.validation.constraints.FieldValidator;
import com.devefx.validation.kit.StrKit;
import com.devefx.validation.script.JavaScript;
/**
* 自定義驗證碼驗證器.
*/
public class CodeValidator extends FieldValidator {
private final String sessionKey;
public CodeValidator(String field, String sessionKey, String errorCode, String errorMessage) {
super(field, errorCode, errorMessage);
this.sessionKey = sessionKey;
}
@Override
public boolean isValid(HttpServletRequest request) throws Exception {
String value = request.getParameter(field);
// 如果是空,就交個NotEmptyValidator元件
if (!StrKit.isEmpty(value)) {
HttpSession session = request.getSession();
// 為了講解友善(實際項目中可不能這麼幹),我直接把‘1234’當做正确的驗證碼
return value.equals(/*session.getAttribute(sessionKey)*/"1234");
}
return true;
}
}
好了,這樣一個背景驗證元件就開發完成了,接着我們就在RegisterValidator.java中使用吧
RegisterValidator.java
package com.devefx.website.validator;
import com.devefx.validation.Validator;
import com.devefx.validation.constraints.impl.EmailValidator;
import com.devefx.validation.constraints.impl.EqualFieldValidator;
import com.devefx.validation.constraints.impl.LengthValidator;
import com.devefx.validation.constraints.impl.MobileValidator;
import com.devefx.validation.constraints.impl.NotBlankValidator;
import com.devefx.validation.constraints.impl.URLValidator;
import com.devefx.website.validator.constraints.CodeValidator;
public class RegisterValidator extends Validator {
@Override
public void setup() {
// 使用者名驗證
add(new NotBlankValidator("username", "username", "使用者名不能為空"));
add(new LengthValidator("username", , , "username", "使用者名長度限制6至20位"));
// 密碼驗證
add(new NotBlankValidator("password", "password", "密碼不能為空"));
add(new LengthValidator("password", , , "password", "密碼長度限制6至20位"));
add(new EqualFieldValidator("password_safe", "password", "password_safe", "兩次密碼不一緻"));
// 手機号驗證
add(new NotBlankValidator("phoneno", "phoneno", "手機号不能為空"));
add(new MobileValidator("phoneno", "phoneno", "請輸入正确的手機号"));
// 郵箱驗證
add(new NotBlankValidator("email", "email", "郵箱不能為空"));
add(new EmailValidator("email", "email", "請輸入正确的郵箱"));
// 個人首頁驗證
add(new URLValidator("homepage", "homepage", "請輸入正确的首頁位址"));
// 驗證碼驗證
add(new NotBlankValidator("code", "code", "驗證碼不能為空"));
add(new CodeValidator("code", "registerCode", "code", "請輸入正确的驗證碼"));
}
}
我們啟動項目試驗一下吧,首先我們輸入一個錯誤的驗證碼
我們可以發現Validator這時候并沒有幫我們立即驗證驗證碼是否正确
上面的圖可以看出:隻有在其他參數正确的情況下,并進行送出的時候才開始檢查出驗證碼有誤,這是因為我們隻為他編寫了背景驗證碼,而沒有前台驗證器的時候實際上分成了兩批驗證。
2 - 編寫前端驗證元件代碼
前端驗證器元件也遵循統一規範,首先我們建立一個“com.devefx.website.validator.constraints.js”包,再建立一個CodeValidator.js檔案
CodeValidator.js
function CodeValidator(field, sessionKey, errorCode, errorMessage) {
FieldValidator.apply(this, [field, errorCode, errorMessage]);
this.isValid = function (request, control) {
var value = request.getParameter(field);
if (!isEmpty(value)) {
// 使用異步
control.async();
// ajax異步請求
$.ajax({
url: "/module/code", // 驗證接口通路位址
type: "post", // 請求方式
data: {"sessionKey": sessionKey, "code": value},
success: function (result) {
// 根據接口傳回結果再同步到驗證器
if (result == "success") {
return control.sync(true);
}
control.sync(false);
}
});
}
return true;
};
}
第一行聲明了一個函數,此函數名稱必須與需要綁定的Java驗證元件名稱相同,參數含義與Java驗證元件的構造函數相同
第二行代碼是js中繼承的實作,我們同樣繼承FieldValidator
第三行實作了驗證方法。
isValid(request[, control]) 方法
參數 | 說明 |
---|---|
request | 用來擷取請求的參數值 |
control | 可選,當此驗證需要異步執行的時候,用來擷取控制權 |
參數
request
類型:Request
Request提供getParameter(name)方法,可以通過input的name擷取input的value
control
類型:Object
提供async、sync(valid)兩個方法,async擷取到控制權;sync(valid)交還控制權同時告知驗證結果
我們可以看到上面定義是前端驗證器需要/module/code接口的支援。
我們在“com.devefx.website”包裡面建立一個Java源碼
ValidatorController.java
package com.devefx.website.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.devefx.validation.ConstraintValidator;
import com.devefx.website.validator.constraints.CodeValidator;
@Controller
@RequestMapping("/module")
public class ValidatorController {
/**
* 檢測驗證碼是否輸入正确
*
* @param sessionKey 會話中驗證碼對應的key
* @return String
*/
@ResponseBody
@RequestMapping(value="/code", method=RequestMethod.POST)
public String codeValidate(HttpServletRequest request,
@RequestParam("sessionKey") String sessionKey) {
try {
ConstraintValidator validator = new CodeValidator("code", sessionKey, null, null);
// 如果驗證通過
if (validator.isValid(request)) {
return "success";
}
} catch (Exception e) {
// ignore
}
return "fail";
}
}
注意:上面的sessionKey,我們是為了友善登入、注冊共用才保留的,你們可以根據實際情況決定是否使用
3 - 為背景驗證元件實作并、綁定前端驗證元件
我們修改一下CodeValidator.java檔案,給他實作Script接口,并綁定前端元件
CodeValidator.java
package com.devefx.website.validator.constraints;
import java.io.IOException;
import java.io.Writer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import com.devefx.validation.Script;
import com.devefx.validation.annotation.BindScript;
import com.devefx.validation.constraints.FieldValidator;
import com.devefx.validation.kit.StrKit;
import com.devefx.validation.script.JavaScript;
/**
* 自定義驗證碼驗證器.
*/
@BindScript("com/devefx/website/validator/constraints/js/CodeValidator.js")
public class CodeValidator extends FieldValidator implements Script {
private final Script script;
private final String sessionKey;
public CodeValidator(String field, String sessionKey, String errorCode, String errorMessage) {
super(field, errorCode, errorMessage);
this.sessionKey = sessionKey;
script = JavaScript.create(this, field, sessionKey, errorCode, errorMessage);
}
@Override
public boolean isValid(HttpServletRequest request) throws Exception {
String value = request.getParameter(field);
// 如果是空,就交個NotEmptyValidator元件
if (!StrKit.isEmpty(value)) {
HttpSession session = request.getSession();
// 為了講解友善(實際項目中可不能這麼幹),我直接把‘1234’當做正确的驗證碼
return value.equals(/*session.getAttribute(sessionKey)*/"1234");
}
return true;
}
public void output(Writer out) throws IOException {
script.output(out);
}
}
通過@BindScript注解将前端驗證元件綁定給背景驗證元件,同時實作Script接口用來輸出前端調用代碼
4 - 注冊自定義元件
做完上面的步驟,我們已經到最後一步了,打開Config.java檔案
Config.java
package com.devefx.website.validator.config;
import com.devefx.validation.web.config.Modules;
import com.devefx.validation.web.config.Routes;
import com.devefx.validation.web.config.ValidatorConfig;
import com.devefx.website.validator.RegisterValidator;
import com.devefx.website.validator.constraints.CodeValidator;
public class Config implements ValidatorConfig {
public void configModules(Modules modules) {
// 這裡可以添加自定義驗證元件
// 注冊自定義元件
modules.add(CodeValidator.class);
}
public void configRoute(Routes routes) {
// 這裡配置驗證器的通路路線
// 設定基準路徑
routes.setBasePath("/validator");
// 注冊驗證器
routes.add("/registerValidator.js", RegisterValidator.class);
}
}
大功告成,重新開機一下項目來看看效果吧。
可以看到我們自定義的驗證元件已經能立即進行驗證了。
5 - 後語
上面我隻為大家介紹了一種自定義驗證元件,大家應該還能想到更多用法。
比如:使用者名是否重名驗證、必須登陸驗證、通路權限驗證等等。
基本上Validator全部的功能我已經接受完畢,由于是第一次寫部落格教程,或許很多地方介紹的不夠詳細,如果大家有什麼不明白之處可以通過下面的評論功能或者加入【Java技術交流群】