數據驗證是每個企業 Web 應用程序中最富於挑戰性、日新月異的部分。通常驗證元數據會使 JavaScript 模塊中混入服務器端代碼。在本文中,您將了解如何在服務器代碼的幫助下將元數據緩存在客戶端的優秀方法,服務器代碼將提供 JSON(JavaScript Object Notation)形式的字符串化元數據。這種方法還允許以類似 Ajax 的方式來處理多值和多組屬性。
每個應用程序的開發都是為了解決某個領域的問題。而每個領域都有自己的一套約束數據的規則和規范。應用程序將這些約束應用於數據時,約束也就成了驗證。所有應用程序都需要驗證用戶輸入的數據。
目前,應用程序一般都使用 if-else 語句組合來驗證數據。這些語句包含了開發人員硬編碼或通過服務器端代碼置入的驗證數據。通常,開發人員會使用服務器端代碼來避免可能導致 JavaServer Page(JSP)的細微數據更改。
您可以使用 JavaScript Object Notation(JSON)來分組和緩存元數據,並使用 JavaScript 函數來訪問元數據以驗證用戶輸入。
JavaScript 中有分散的元數據時,您無法控制服務器將評估多少數據以及有多少數據傳遞到客戶機。所有服務器端代碼片段都將被評估並發送到服務器上。但是,使用 JSON 緩存數據時,您可以完全控制向客戶機發送的元數據量,因為服務器端代碼將生成 JSON 形式的元數據。這有助於僅將元數據發送至與看到或輸入數據的用戶相對應的客戶機上。
您還可以使用 JSON 來緩存用戶輸入的數據。程序緩存數據後,將擦除數據字段而不是刷新屏幕,這與 Ajax 類似。通過這種方法,用戶可以為同一屬性輸入另一組數據。
讓我們一起來探究一下如何使用 JSON 來緩存元數據。
JSON 概覽
使用 JSON(即 JavaScript Object Notation),將以一種特定的字符串形式來表示 JavaScript 對象。如果將具有這樣一種形式的字符串賦給任意一個 JavaScript 變量,該變量隨後將引用一個通過指定給該變量的字符串構建的對象。
例如,假定有一個 policy 對象,它擁有以下屬性:
計劃名稱
描述
持續時間
您可以使用以下這種 JSON 形式的字符串來表示該 policy 對象:
{"Plane":{"Full Life Cover"}, "Description":{"The best life insurance plan"}, "Term":{"20 years"}}
如果將此字符串賦給任意一個 JavaScript 變量,則該變量將接受以這種對象為單位的數據。要訪問數據,請提供需要訪問的屬性所在的路徑。對於本例,將以上字符串賦給一個名為 policy 的變量:
var policy = {"Plane":{"Full Life Cover"}, "Description":{"The best life insurance plan"}, "Term":{"20 years"}}
將此字符串粘貼到 HTML 頁面的標題部分中,然後編寫以下警報:
alert(policy.Plan)
如果在任何支持 JavaScript 的浏覽器中查看此頁面,您都會看到顯示策略計劃的警報。
示例
為了演示 JSON 的性能,我們來看一個有 vehicle 對象列表的 person 對象和一個可以擁有一台或多台車輛的 person 對象。每台車輛都有以下屬性:
品牌
注冊碼
CC
浏覽器 UI 應當允許用戶添加多台具有優秀應用性能的車輛(通常為固有要求)。每個屬性都有一些與之關聯的限制或驗證規則。您需要指定以下規則:
品牌名稱
品牌名稱決不能包含數字。
品牌名稱最多可包含兩個單詞,中間可加一個空格。
注冊碼
注冊碼必須全都是數字。
CC
CC 必須全都是數字。
CC 的最小值為 50,最大值為 5000。
將有三個與車輛屬性相對應的輸入字段,用戶可在其中輸入信息。接下來,您將看到如何將驗證消息分組到 JSON 組中以及如何訪問這些驗證消息。
傳統方法
現在,當用戶輸入的車輛數據為 40CC 時,程序必須顯示一條消息,說明輸入的數據不在有效的 CC 范圍內。您可以用 清單 1 中的代碼簡單地顯示這條消息:
清單 1. 傳統代碼
if(cc < <%= minCC %> || cc > <%= maxCC %>) {
alert(<%= ResourceList.vehicleCCRangeMsg >);
}
ResourceList 是一個服務器端類,該類中含有關於車輛的國際化消息(如 vehicleCCRangeMsg)。這種方法解決問題時略顯混亂:
在這種方法中,您將把服務器端代碼添加到所有客戶端驗證函數中,以檢查條件並顯示消息。
如果更改了元數據和消息(例如服務器端類或變量)的組織方法,您將會為更改使用這些元數據和消息的客戶機腳本驗證函數感到十分頭痛。
JSON 能幫助您做什麼?
如果只需在條件語句和警報中引用一個 JavaScript 變量而不是服務器端代碼,您感覺怎麼樣?不需要把服務器端代碼包含在 JavaScript 中,而保存的服務器端元數據和消息中的更改也不會影響客戶端腳本。這種方法太棒了,是不是?好的,那就是使用基於 JSON 緩存元數據時要做的。
您將使用一個 JavaScript 對象把我們的驗證數據和消息分組到一個層級中。然後就像訪問層級的 JavaScript 對象一樣訪問這些消息。就是這樣,您已經做到了!
當此 JSON 元數據對象就緒後,先前的 JavaScript 代碼片段將類似於 清單 2。
清單 2. 帶有 JSON 元數據緩存對象的警報
if(cc < vehicleValidationsMetadata.CC.minCC ||
cc > vehicleValidationsMetadata.CC.maxCC) {
alert(vehicleValidationsMetadata.CC.RangeMessage);
}
現在,問題是誰來准備 JSON 元數據對象?嗯,只有服務器能做這項工作。服務器必須生成這個 JSON 對象,並將其提供給客戶機(浏覽器)。一些 Java API 可以幫助您准備此類(事實上是任意一類)JSON 對象。請參閱 參考資料 來查看那些 API。
生成 JSON 元數據對象的典型方法為:
為實體及其驗證消息准備一個層級 Java 對象。
對這些實體及其驗證消息調用 toString()。這些實體及其驗證消息最有可能把一個 JSON 形式的字符串提供給您。
將該字符串另存到一個請求范圍內。
在 JSP 中,獲取該字符串,並將其指派到 JavaScript 變量值的大括號內。
最終的車輛元數據對象看上去就會像 清單 3 一樣。
清單 3. 驗證元數據 JSON 對象
var vehicleValidationsMetadata = {
"BrandName":{
"CanContainDigits":{false},
"MaxWords":{2},
"FormatMessage":{"Brand Name cannot contain digits."},
"WordLimitMessage":{"Brand Name cannot contain more than two words"}
},
"RegistrationNumber":{
"CanContainAlphabets":{false},
"CanContainDigits":{"true"},
"FormatMessage":{"Registration Number can contain only digits."}
},
"CC":{
"minCC":{50},
"maxCC":{5000},
"FormatMessage":
{"CC can only be numeric"},
"RangeMessage":{"CC can be within range of 50 and 5000"}
}
}
服務器必須生成整個字符串,第一行和最後一行除外,因為當前的用戶語言環境可能要求使用這些消息(並且只有服務器端代碼能完成這項工作)。在這裡,需要注意的一點是此元數據對象僅用於驗證車輛。更理想的情況是將 vehicle 元數據對象封裝到 person 元數據對象中。那樣,您就不需要再創建另一個 JavaScript 變量,而只需將該元數據對象包含到 person 元數據對象中。
在將此元數據對象准備好後,您可以使用該對象中的元數據和消息來驗證數據輸入和顯示消息。現在,驗證車輛輸入信息的 JavaScript 函數看上去就會跟 清單 4 一樣。
清單 4. 車輛數據驗證函數
function validateVehicleData() {
var brandName = //get brand name from form field
var registrationNumber = //get Registration Number from form field.
var CC = //get CC from form field
var brandNameTokens = brandName.split(' ');
if(brandNameTokens.length > vehicleValidationsMetadata.BrandName.MaxWords) {
alert(vehicleValidationMessages.BrandName.WordLimitMessage);
}
.
.
.
if((!vehicleValidationsMetadata.RegistrationNumber.CanContainAlphabets) &&
isNaN(parseInt(registrationNumber))) {
alert(vehicleValidationMessages.RegistrationNumber.FormatMessage);
}
var ccNum = parseInt(CC);
if(ccNum < vehicleValidationMessages.CC.minCC ||
ccNum > vehicleValidationMessages.CC.maxCC) {
alert(vehicleValidationMessages.CC.RangeMessage);
}
}
這段代碼看上去是不是好多了?它沒有在 JavaScript 中混入服務器代碼。如果服務器端更改存儲元數據的方法,則無需再重寫客戶機腳本。這會使 JSP 編程人員的日子更輕松些。
擴展客戶端數據緩存
某些 Web 應用程序要求用戶為同一個屬性或對象輸入多個數據。例如,person-vehicle 要求人員為其擁有的每台車輛都輸入數據。如果此人擁有多台車輛,應用程序必須允許輸入多台車輛的數據。我將把此類對象作為一個 多組屬性 來引用。如果多組屬性包含任何可以保存多個數據實例的屬性,我將稱之為 多值屬性。
現在,多組屬性和多值屬性面臨的問題是必須將數據輸入到相同的輸入字段中。那意味著在輸入第二台車輛的數據之前,必須先保存已輸入的第一台車輛的數據。您可以通過兩種方法來解決此問題:
將第一台車輛的數據發送到服務器上並清空輸入字段,以允許用戶輸入下一台車輛的數據。
將數據緩存到客戶機上並清空輸入字段,以允許用戶輸入下一台車輛的數據。
第一種方法存在的問題是每輸入一台車輛的數據就需要訪問一次服務器。這不太好;如果在輸入車輛數據後都必須等待服務器響應,用戶會覺得很失望。換種方法,第二種方法的響應時間幾乎為零。用戶可以快速輸入所有車輛數據而無需等待。但這裡需要考慮的是如何將數據存儲到客戶端上。這裡有更多方法可將數據存儲到客戶機上:
在用戶單擊以添加下一台車輛的數據時將數據以某種形式緩存到隱藏的表字段中。
將數據緩存到一個 JavaScript 對象中。
如果要將數據存儲到隱藏字段中,您會為用戶每次輸入新的車輛數據都要處理很多隱藏字段或處理隱藏字段數據而感到煩惱。這就像有字符串操作就需要頻繁處理字符串一樣。
但是第二種緩存數據的方法提供了一種面向對象的方法來緩存。當用戶輸入新車輛數據時,您將在數組對象中創建一個新元素。不需要任何笨拙的字符串操作。當用戶輸完所有車輛數據後,您只需構建一個源於該對象的 JSON 字符串,並通過存儲到某個隱藏字段中的方式將該字符串發送至服務器。這種方法要比第一種方法好得多。
JSON、數據緩存和 Ajax 功能
當使用 JSON 將數據緩存到客戶端時,系統將在用戶每次單擊 Add Vehicle 按鈕時更新數據緩存對象。用於完成此項任務的 JavaScript 函數看起來可能跟 清單 5 一樣。
清單 5. 用於將車輛數據添加到 JavaScript 對象中以進行客戶端緩存的函數
function addVehicleData() {
var brand = //get vehicle brand;
var regNo = //get registration number;
var cc = //get cc;
vehicleData[vehicleData.length] = new Object();
vehicleData[vehicleData.length].brandName = new Object();
vehicleData[vehicleData.length].brandName = brand;
//same way update other two properties
}
在這裡,vehicleData 是用於在用戶裝入頁面時進行初始化的 JavaScript 變量。它被初始化為一個新的數組對象,該數組對象為空或者含有用戶先前輸入的車輛的車輛元素。
當此函數將數據保存到 JavaScript 對象中後,程序可以調用另一個函數來清空輸入字段以允許用戶輸入新數據。
在此類應用程序中,要求用戶輸入出現次數最少或出現次數最多的多組或多值屬性。您可以將這些限制置入 JSON 元數據對象中。在這種情況下,先前的元數據對象將變為 清單 6 中所示的代碼。
清單 6. 帶有出現次數限制的 JSON 元數據對象
var vehicleValidationsMetadata = {
"MIN_OCC":{0},
"MAX_OCC":{10},
"MAX_OCC_MSG":{"...."},
"MIN_OCC_MSG":{".....},
//Everything else is the same
}
然後,addVehicleData() 函數將先驗證數據的出現次數,然後在僅當總出現次數未超出允許的限制時再將數據添加到 JavaScript 對象中。清單 7 顯示了檢查方法。
清單 7. JSON 元數據對象限制檢查
function addVehicleData() {
if(vehicleData.length == vehicleValidationsMetadata.MAX_OCC-1) {
alert(vehicleValidationsMetadata.MAX_OCC_MSG);
}
//Everything else is the same
}
當用戶提交一個頁面時調用的函數實際上用於驗證最少的出現次數。這種方法的最大好處是屏幕不需要刷新以輸入新車輛數據。提供此類靜態屏幕曾經是 Ajax 技術的主要目標,而您現在用 JSON 也能完成此目標。這是關於更新 JSON 數據對象和通過 JavaScript 處理 HTML DOM 樹的全部內容。用戶響應時間是最小值,因為所有操作僅在客戶端上執行。您可以使用 JSON 來為應用程序提供 Ajax 功能。
當用戶單擊 Save 按鈕時,程序將調用另一個 JavaScript 函數,該函數將把此 JSON 對象 字符串化 並將其存儲到程序提交到服務器上的隱藏表字段中。JSON.js(請參閱 參考資料)有一個 JSON.stringify() 函數,該函數將獲取 JavaScript 對象作為輸入並返回字符串輸出。
服務器端必須能夠理解 JSON 形式的字符串並生成一個服務器端對象,以處理和保存數據。Web 站點 http://www.json.org/java/index.html 提供了一個 Java API,該 API 用於處理基於 Java 的應用程序的大部分需求。
結束語
您在本文中看到了 JSON 的強大用途。歸結如下:
JSON 提供了一種優秀的面向對象的方法,以便將元數據緩存到客戶機上。
JSON 幫助分離了驗證數據和邏輯。
JSON 幫助為 Web 應用程序提供了 Ajax 的本質。