|
每個(gè)應(yīng)用程序的開(kāi)發(fā)都是為了解決某個(gè)領(lǐng)域的問(wèn)題。而每個(gè)領(lǐng)域都有自己的一套約束數(shù)據(jù)的規(guī)則和規(guī)范。應(yīng)用程序?qū)⑦@些約束應(yīng)用于數(shù)據(jù)時(shí),約束也就成了驗(yàn)證。所有應(yīng)用程序都需要驗(yàn)證用戶(hù)輸入的數(shù)據(jù)。
目前,應(yīng)用程序一般都使用 if-else 語(yǔ)句組合來(lái)驗(yàn)證數(shù)據(jù)。這些語(yǔ)句包含了開(kāi)發(fā)人員硬編碼或通過(guò)服務(wù)器端代碼置入的驗(yàn)證數(shù)據(jù)。通常,開(kāi)發(fā)人員會(huì)使用服務(wù)器端代碼來(lái)避免可能導(dǎo)致 JavaServer Page(JSP)的細(xì)微數(shù)據(jù)更改。
您可以使用 JavaScript Object Notation(JSON)來(lái)分組和緩存元數(shù)據(jù),并使用 JavaScript 函數(shù)來(lái)訪問(wèn)元數(shù)據(jù)以驗(yàn)證用戶(hù)輸入。
JavaScript 中有分散的元數(shù)據(jù)時(shí),您無(wú)法控制服務(wù)器將評(píng)估多少數(shù)據(jù)以及有多少數(shù)據(jù)傳遞到客戶(hù)機(jī)。所有服務(wù)器端代碼片段都將被評(píng)估并發(fā)送到服務(wù)器上。但是,使用 JSON 緩存數(shù)據(jù)時(shí),您可以完全控制向客戶(hù)機(jī)發(fā)送的元數(shù)據(jù)量,因?yàn)?a href=/yuedu/fuwuqi/ target=_blank class=infotextkey>服務(wù)器端代碼將生成 JSON 形式的元數(shù)據(jù)。這有助于僅將元數(shù)據(jù)發(fā)送至與看到或輸入數(shù)據(jù)的用戶(hù)相對(duì)應(yīng)的客戶(hù)機(jī)上。
您還可以使用 JSON 來(lái)緩存用戶(hù)輸入的數(shù)據(jù)。程序緩存數(shù)據(jù)后,將擦除數(shù)據(jù)字段而不是刷新屏幕,這與 Ajax 類(lèi)似。通過(guò)這種方法,用戶(hù)可以為同一屬性輸入另一組數(shù)據(jù)。
讓我們一起來(lái)探究一下如何使用 JSON 來(lái)緩存元數(shù)據(jù)。
JSON 概覽
使用 JSON(即 JavaScript Object Notation),將以一種特定的字符串形式來(lái)表示 JavaScript 對(duì)象。如果將具有這樣一種形式的字符串賦給任意一個(gè) JavaScript 變量,該變量隨后將引用一個(gè)通過(guò)指定給該變量的字符串構(gòu)建的對(duì)象。
例如,假定有一個(gè) policy 對(duì)象,它擁有以下屬性:
計(jì)劃名稱(chēng)
描述
持續(xù)時(shí)間
您可以使用以下這種 JSON 形式的字符串來(lái)表示該 policy 對(duì)象:
{"Plane":{"Full Life Cover"}, "Description":{"The best life insurance plan"}, "Term":{"20 years"}}
如果將此字符串賦給任意一個(gè) JavaScript 變量,則該變量將接受以這種對(duì)象為單位的數(shù)據(jù)。要訪問(wèn)數(shù)據(jù),請(qǐng)?zhí)峁┬枰L問(wèn)的屬性所在的路徑。對(duì)于本例,將以上字符串賦給一個(gè)名為 policy 的變量:
var policy = {"Plane":{"Full Life Cover"}, "Description":{"The best life insurance plan"}, "Term":{"20 years"}}
將此字符串粘貼到 HTML 頁(yè)面的標(biāo)題部分中,然后編寫(xiě)以下警報(bào):
alert(policy.Plan)
如果在任何支持 JavaScript 的瀏覽器中查看此頁(yè)面,您都會(huì)看到顯示策略計(jì)劃的警報(bào)。
示例
為了演示 JSON 的性能,我們來(lái)看一個(gè)有 vehicle 對(duì)象列表的 person 對(duì)象和一個(gè)可以擁有一臺(tái)或多臺(tái)車(chē)輛的 person 對(duì)象。每臺(tái)車(chē)輛都有以下屬性:
品牌
注冊(cè)碼
CC
瀏覽器 UI 應(yīng)當(dāng)允許用戶(hù)添加多臺(tái)具有優(yōu)秀應(yīng)用性能的車(chē)輛(通常為固有要求)。每個(gè)屬性都有一些與之關(guān)聯(lián)的限制或驗(yàn)證規(guī)則。您需要指定以下規(guī)則:
品牌名稱(chēng)
品牌名稱(chēng)決不能包含數(shù)字。
品牌名稱(chēng)最多可包含兩個(gè)單詞,中間可加一個(gè)空格。
注冊(cè)碼
注冊(cè)碼必須全都是數(shù)字。
CC
CC 必須全都是數(shù)字。
CC 的最小值為 50,最大值為 5000。
將有三個(gè)與車(chē)輛屬性相對(duì)應(yīng)的輸入字段,用戶(hù)可在其中輸入信息。接下來(lái),您將看到如何將驗(yàn)證消息分組到 JSON 組中以及如何訪問(wèn)這些驗(yàn)證消息。
傳統(tǒng)方法
現(xiàn)在,當(dāng)用戶(hù)輸入的車(chē)輛數(shù)據(jù)為 40CC 時(shí),程序必須顯示一條消息,說(shuō)明輸入的數(shù)據(jù)不在有效的 CC 范圍內(nèi)。您可以用 清單 1 中的代碼簡(jiǎn)單地顯示這條消息:
清單 1. 傳統(tǒng)代碼
if(cc < <%= minCC %> || cc > <%= maxCC %>) {
alert(<%= ResourceList.vehicleCCRangeMsg >);
}
ResourceList 是一個(gè)服務(wù)器端類(lèi),該類(lèi)中含有關(guān)于車(chē)輛的國(guó)際化消息(如 vehicleCCRangeMsg)。這種方法解決問(wèn)題時(shí)略顯混亂:
在這種方法中,您將把服務(wù)器端代碼添加到所有客戶(hù)端驗(yàn)證函數(shù)中,以檢查條件并顯示消息。
如果更改了元數(shù)據(jù)和消息(例如服務(wù)器端類(lèi)或變量)的組織方法,您將會(huì)為更改使用這些元數(shù)據(jù)和消息的客戶(hù)機(jī)腳本驗(yàn)證函數(shù)感到十分頭痛。
JSON 能幫助您做什么?
如果只需在條件語(yǔ)句和警報(bào)中引用一個(gè) JavaScript 變量而不是服務(wù)器端代碼,您感覺(jué)怎么樣?不需要把服務(wù)器端代碼包含在 JavaScript 中,而保存的服務(wù)器端元數(shù)據(jù)和消息中的更改也不會(huì)影響客戶(hù)端腳本。這種方法太棒了,是不是?好的,那就是使用基于 JSON 緩存元數(shù)據(jù)時(shí)要做的。
您將使用一個(gè) JavaScript 對(duì)象把我們的驗(yàn)證數(shù)據(jù)和消息分組到一個(gè)層級(jí)中。然后就像訪問(wèn)層級(jí)的 JavaScript 對(duì)象一樣訪問(wèn)這些消息。就是這樣,您已經(jīng)做到了!
當(dāng)此 JSON 元數(shù)據(jù)對(duì)象就緒后,先前的 JavaScript 代碼片段將類(lèi)似于 清單 2。
清單 2. 帶有 JSON 元數(shù)據(jù)緩存對(duì)象的警報(bào)
if(cc < vehicleValidationsMetadata.CC.minCC ||
cc > vehicleValidationsMetadata.CC.maxCC) {
alert(vehicleValidationsMetadata.CC.RangeMessage);
}
現(xiàn)在,問(wèn)題是誰(shuí)來(lái)準(zhǔn)備 JSON 元數(shù)據(jù)對(duì)象?嗯,只有服務(wù)器能做這項(xiàng)工作。服務(wù)器必須生成這個(gè) JSON 對(duì)象,并將其提供給客戶(hù)機(jī)(瀏覽器)。一些 Java API 可以幫助您準(zhǔn)備此類(lèi)(事實(shí)上是任意一類(lèi))JSON 對(duì)象。請(qǐng)參閱 參考資料 來(lái)查看那些 API。
生成 JSON 元數(shù)據(jù)對(duì)象的典型方法為:
為實(shí)體及其驗(yàn)證消息準(zhǔn)備一個(gè)層級(jí) Java 對(duì)象。
對(duì)這些實(shí)體及其驗(yàn)證消息調(diào)用 toString()。這些實(shí)體及其驗(yàn)證消息最有可能把一個(gè) JSON 形式的字符串提供給您。
將該字符串另存到一個(gè)請(qǐng)求范圍內(nèi)。
在 JSP 中,獲取該字符串,并將其指派到 JavaScript 變量值的大括號(hào)內(nèi)。
最終的車(chē)輛元數(shù)據(jù)對(duì)象看上去就會(huì)像 清單 3 一樣。
清單 3. 驗(yàn)證元數(shù)據(jù) JSON 對(duì)象
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"}
}
}
服務(wù)器必須生成整個(gè)字符串,第一行和最后一行除外,因?yàn)楫?dāng)前的用戶(hù)語(yǔ)言環(huán)境可能要求使用這些消息(并且只有服務(wù)器端代碼能完成這項(xiàng)工作)。在這里,需要注意的一點(diǎn)是此元數(shù)據(jù)對(duì)象僅用于驗(yàn)證車(chē)輛。更理想的情況是將 vehicle 元數(shù)據(jù)對(duì)象封裝到 person 元數(shù)據(jù)對(duì)象中。那樣,您就不需要再創(chuàng)建另一個(gè) JavaScript 變量,而只需將該元數(shù)據(jù)對(duì)象包含到 person 元數(shù)據(jù)對(duì)象中。
在將此元數(shù)據(jù)對(duì)象準(zhǔn)備好后,您可以使用該對(duì)象中的元數(shù)據(jù)和消息來(lái)驗(yàn)證數(shù)據(jù)輸入和顯示消息。現(xiàn)在,驗(yàn)證車(chē)輛輸入信息的 JavaScript 函數(shù)看上去就會(huì)跟 清單 4 一樣。
清單 4. 車(chē)輛數(shù)據(jù)驗(yàn)證函數(shù)
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);
}
}
這段代碼看上去是不是好多了?它沒(méi)有在 JavaScript 中混入服務(wù)器代碼。如果服務(wù)器端更改存儲(chǔ)元數(shù)據(jù)的方法,則無(wú)需再重寫(xiě)客戶(hù)機(jī)腳本。這會(huì)使 JSP 編程人員的日子更輕松些。
擴(kuò)展客戶(hù)端數(shù)據(jù)緩存
某些 Web 應(yīng)用程序要求用戶(hù)為同一個(gè)屬性或?qū)ο筝斎攵鄠€(gè)數(shù)據(jù)。例如,person-vehicle 要求人員為其擁有的每臺(tái)車(chē)輛都輸入數(shù)據(jù)。如果此人擁有多臺(tái)車(chē)輛,應(yīng)用程序必須允許輸入多臺(tái)車(chē)輛的數(shù)據(jù)。我將把此類(lèi)對(duì)象作為一個(gè) 多組屬性 來(lái)引用。如果多組屬性包含任何可以保存多個(gè)數(shù)據(jù)實(shí)例的屬性,我將稱(chēng)之為 多值屬性。
現(xiàn)在,多組屬性和多值屬性面臨的問(wèn)題是必須將數(shù)據(jù)輸入到相同的輸入字段中。那意味著在輸入第二臺(tái)車(chē)輛的數(shù)據(jù)之前,必須先保存已輸入的第一臺(tái)車(chē)輛的數(shù)據(jù)。您可以通過(guò)兩種方法來(lái)解決此問(wèn)題:
將第一臺(tái)車(chē)輛的數(shù)據(jù)發(fā)送到服務(wù)器上并清空輸入字段,以允許用戶(hù)輸入下一臺(tái)車(chē)輛的數(shù)據(jù)。
將數(shù)據(jù)緩存到客戶(hù)機(jī)上并清空輸入字段,以允許用戶(hù)輸入下一臺(tái)車(chē)輛的數(shù)據(jù)。
第一種方法存在的問(wèn)題是每輸入一臺(tái)車(chē)輛的數(shù)據(jù)就需要訪問(wèn)一次服務(wù)器。這不太好;如果在輸入車(chē)輛數(shù)據(jù)后都必須等待服務(wù)器響應(yīng),用戶(hù)會(huì)覺(jué)得很失望。換種方法,第二種方法的響應(yīng)時(shí)間幾乎為零。用戶(hù)可以快速輸入所有車(chē)輛數(shù)據(jù)而無(wú)需等待。但這里需要考慮的是如何將數(shù)據(jù)存儲(chǔ)到客戶(hù)端上。這里有更多方法可將數(shù)據(jù)存儲(chǔ)到客戶(hù)機(jī)上:
在用戶(hù)單擊以添加下一臺(tái)車(chē)輛的數(shù)據(jù)時(shí)將數(shù)據(jù)以某種形式緩存到隱藏的表字段中。
將數(shù)據(jù)緩存到一個(gè) JavaScript 對(duì)象中。
如果要將數(shù)據(jù)存儲(chǔ)到隱藏字段中,您會(huì)為用戶(hù)每次輸入新的車(chē)輛數(shù)據(jù)都要處理很多隱藏字段或處理隱藏字段數(shù)據(jù)而感到煩惱。這就像有字符串操作就需要頻繁處理字符串一樣。
但是第二種緩存數(shù)據(jù)的方法提供了一種面向?qū)ο蟮姆椒▉?lái)緩存。當(dāng)用戶(hù)輸入新車(chē)輛數(shù)據(jù)時(shí),您將在數(shù)組對(duì)象中創(chuàng)建一個(gè)新元素。不需要任何笨拙的字符串操作。當(dāng)用戶(hù)輸完所有車(chē)輛數(shù)據(jù)后,您只需構(gòu)建一個(gè)源于該對(duì)象的 JSON 字符串,并通過(guò)存儲(chǔ)到某個(gè)隱藏字段中的方式將該字符串發(fā)送至服務(wù)器。這種方法要比第一種方法好得多。
JSON、數(shù)據(jù)緩存和 Ajax 功能
當(dāng)使用 JSON 將數(shù)據(jù)緩存到客戶(hù)端時(shí),系統(tǒng)將在用戶(hù)每次單擊 Add Vehicle 按鈕時(shí)更新數(shù)據(jù)緩存對(duì)象。用于完成此項(xiàng)任務(wù)的 JavaScript 函數(shù)看起來(lái)可能跟 清單 5 一樣。
清單 5. 用于將車(chē)輛數(shù)據(jù)添加到 JavaScript 對(duì)象中以進(jìn)行客戶(hù)端緩存的函數(shù)
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 是用于在用戶(hù)裝入頁(yè)面時(shí)進(jìn)行初始化的 JavaScript 變量。它被初始化為一個(gè)新的數(shù)組對(duì)象,該數(shù)組對(duì)象為空或者含有用戶(hù)先前輸入的車(chē)輛的車(chē)輛元素。
當(dāng)此函數(shù)將數(shù)據(jù)保存到 JavaScript 對(duì)象中后,程序可以調(diào)用另一個(gè)函數(shù)來(lái)清空輸入字段以允許用戶(hù)輸入新數(shù)據(jù)。
在此類(lèi)應(yīng)用程序中,要求用戶(hù)輸入出現(xiàn)次數(shù)最少或出現(xiàn)次數(shù)最多的多組或多值屬性。您可以將這些限制置入 JSON 元數(shù)據(jù)對(duì)象中。在這種情況下,先前的元數(shù)據(jù)對(duì)象將變?yōu)?nbsp;清單 6 中所示的代碼。
清單 6. 帶有出現(xiàn)次數(shù)限制的 JSON 元數(shù)據(jù)對(duì)象
var vehicleValidationsMetadata = {
"MIN_OCC":{0},
"MAX_OCC":{10},
"MAX_OCC_MSG":{"...."},
"MIN_OCC_MSG":{".....},
//Everything else is the same
}
然后,addVehicleData() 函數(shù)將先驗(yàn)證數(shù)據(jù)的出現(xiàn)次數(shù),然后在僅當(dāng)總出現(xiàn)次數(shù)未超出允許的限制時(shí)再將數(shù)據(jù)添加到 JavaScript 對(duì)象中。清單 7 顯示了檢查方法。
清單 7. JSON 元數(shù)據(jù)對(duì)象限制檢查
function addVehicleData() {
if(vehicleData.length == vehicleValidationsMetadata.MAX_OCC-1) {
alert(vehicleValidationsMetadata.MAX_OCC_MSG);
} //Everything else is the same
}
當(dāng)用戶(hù)提交一個(gè)頁(yè)面時(shí)調(diào)用的函數(shù)實(shí)際上用于驗(yàn)證最少的出現(xiàn)次數(shù)。這種方法的最大好處是屏幕不需要刷新以輸入新車(chē)輛數(shù)據(jù)。提供此類(lèi)靜態(tài)屏幕曾經(jīng)是 Ajax 技術(shù)的主要目標(biāo),而您現(xiàn)在用 JSON 也能完成此目標(biāo)。這是關(guān)于更新 JSON 數(shù)據(jù)對(duì)象和通過(guò) JavaScript 處理 HTML DOM 樹(shù)的全部?jī)?nèi)容。用戶(hù)響應(yīng)時(shí)間是最小值,因?yàn)樗胁僮鲀H在客戶(hù)端上執(zhí)行。您可以使用 JSON 來(lái)為應(yīng)用程序提供 Ajax 功能。
當(dāng)用戶(hù)單擊 Save 按鈕時(shí),程序?qū)⒄{(diào)用另一個(gè) JavaScript 函數(shù),該函數(shù)將把此 JSON 對(duì)象 字符串化 并將其存儲(chǔ)到程序提交到服務(wù)器上的隱藏表字段中。JSON.js(請(qǐng)參閱 參考資料)有一個(gè) JSON.stringify() 函數(shù),該函數(shù)將獲取 JavaScript 對(duì)象作為輸入并返回字符串輸出。
服務(wù)器端必須能夠理解 JSON 形式的字符串并生成一個(gè)服務(wù)器端對(duì)象,以處理和保存數(shù)據(jù)。Web 站點(diǎn) http://www.json.org/Java/i... 提供了一個(gè) Java API,該 API 用于處理基于 Java 的應(yīng)用程序的大部分需求。
結(jié)束語(yǔ)
您在本文中看到了 JSON 的強(qiáng)大用途。歸結(jié)如下:
JSON 提供了一種優(yōu)秀的面向?qū)ο蟮姆椒ǎ员銓⒃獢?shù)據(jù)緩存到客戶(hù)機(jī)上。
JSON 幫助分離了驗(yàn)證數(shù)據(jù)和邏輯。
JSON 幫助為 Web 應(yīng)用程序提供了 Ajax 的本質(zhì)。
JavaScript技術(shù):用 JSON 處理緩存,轉(zhuǎn)載需保留來(lái)源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。