數據驗證是編寫任何用戶界面時經常要處理的一項雜務
Java? 語言的正則表達式支持可以使數據驗證變得更容易
您可以定義一個正則表達式
用於描述有效數據
然後讓 Java 運行時檢查它是否匹配
但是有些類型的數據在不同地區有不同的格式
而 ResourceBundle 類讓您可以以一種優雅的方式使用特定於地區的數據
本文展示如何結合這兩種技術來解決常見的數據輸入問題
本文討論將正則表達式與 Java ResourceBundle 相結合的一種數據驗證技術
Java 語言對正則表達式的支持可以大大簡化數據驗證
您可以將數據與正則表達式進行比較
如果它們匹配
則知道數據是有效的
另一方面
Java ResourceBundle 包含翻譯好的字符串
用於匹配用戶機器上的當前語言和國家設置
ResourceBundle 中的字符串通常是出現在應用程序中的文本
但是也可以是特定於某個地區的任何東西
您將實踐一個示例應用程序
該應用程序從 ResourceBundles 獲得正則表達式
並將它們用於數據驗證
通過這種方法
就可以用一塊代碼來驗證很多不同類型的數據
更妙的是
隨著更多 ResourceBundle 的添加
還可以驗證更多類型的數據
並且不用更改這段代碼中的任何一行
本文的示例應用程序是在 Eclipse 中用 Visual Editor 構建的
Visual Editor 是一種用於構建圖形化界面的開放源碼工具
為了構建自己的應用程序
您需要在計算機上安裝 Eclipse 和 Visual Editor 包
這個示例應用程序只是舉例說明了驗證數據的一種
技巧所以這種方法可用於任何 Java 應用程序
示例應用程序 我不想花太多的時間討論這個示例應用程序的所有細節
我只關注其中的數據驗證方面的技巧
這個應用程序驗證輸入到輸入域中的郵政編碼
您可能知道
在世界的不同地方
郵政編碼千差萬別
有的是數字
有的則包含字母
即使同是由數字組成的郵政編碼
在不同地方其長度也不盡相同
有的國家以特定的模式排列字母和數字
而另外一些國家則采用更自由的格式
所有這些格式都可以用正則表達式來描述
例如
在美國郵政編碼是一個五位數
後面還可能跟有一個破折號加一個四位數
清單
展示了描述這種格式的正則表達式
清單 用於美國郵政編碼的正則表達式
[]{}([]{})?
除了格式不同外郵政編碼並不總是被稱為郵政編碼例如美國將郵政編碼稱為 ZIP CodeResourceBundle 的一種常見用法就是處理這種類型的與地區有關的差異用於美國的 ResourceBundle 可能包含短語 Enter your ZIP Code而在用於加拿大的 ResourceBundle 中相應的短語可能是 Enter your postal code我在本文中演示的技巧也是從 ResourceBundle 獲得用於有效郵政編碼的正則表達式
為了使這個示例簡單化您將創建一個只有一個輸入域和一個 Validate 按鈕的 Swing 應用程序用戶在輸入域中輸入文本然後單擊該按鈕如果數據與當前的正則表達式匹配則應用程序顯示一條消息表明郵政編碼有效因為應用程序使用不同的 ResourceBundle所以正則表達式隨著有效數據的規則的變化而變化由於正則表達式是從文本文件中裝載的一個字符串所以當添加對新類型的郵政編碼的支持時不需要更改代碼
您將在 Eclipse 中使用 Eclipse Visual Editor 和 Eclipse Java Development Tool 的一些特性來構建這個應用程序您可以在幾乎所有開發環境中使用這種技巧這裡的代碼應該可以在任何基於 Eclipse 的產品中運行例如 Rational Application Developer
圖 展示了該應用程序在 Eclipse Visual Editor 中的樣子
圖 Eclipse Visual Editor 中的示例應用程序
Visual Editor 提供了四種查看應用程序的方式在屏幕的頂端是應用程序的可視化圖像源代碼在底端Eclipse 還提供了兩個視圖 —— Properties 視圖和 Java Beans 視圖 —— 可以通過這兩個視圖來處理應用程序所有這些查看應用程序的方式都是由 Eclipse Modeling Framework (EMF) 控制的由於已經有一些關於 EMF 的完整書籍所以我不會再談更多的細節從程序員的角度來看重要的一點是任何視圖中的變化都會自動發送到其他視圖例如如果您使用 Properties 視圖將一個對象的背景顏色設為綠色那麼可視化圖像和源代碼也會自動更新
運行初始的示例應用程序
首先來看一個已經創建好的應用程序圖 展示了這個應用程序的運行界面
圖 輸入有效數據時的示例應用程序
在圖 中用戶輸入了有效的數據並單擊了 Validate 按鈕如果數據無效那麼將出現圖 所示的界面
圖 輸入無效數據時的示例應用程序
清單 展示了如何使用 清單 中的正則表達式來驗證數據
清單 使用正則表達式
Pattern pc = pile([]{}([]{})?);
Matcher m = pcmatcher(postalCodegetText());
if (mmatches())
{
validLabelsetText(Your postal code is valid);
validLabelsetForeground(ColorBLUE);
}
else
{
validLabelsetText(Your postal code is not valid);
validLabelsetForeground(ColorRED);
}
清單
中的兩條反饋消息通常會被翻譯成其他語言
您還將通過使用這裡展示的技巧來
翻譯
正則表達式
與一般的翻譯不同
將正則表達式轉換成國際化版本是數據格式專家的工作
而不是語言專家的工作
具體化字符串 Eclipse 為代碼的國際化提供了一個方便的特性
首先單擊
Source > Externalize Strings如圖
所示
圖 Externalize Strings 主菜單 Eclipse 查看 Java 代碼
以發現應該放入到 ResourceBundle 中的字符串
您將看到類似圖
所示的對話框
圖 Externalize Strings 對話框 在圖
中列出的所有字符串中
對話框頂部的空白字符串不需要翻譯
(反饋消息的初始值是一個空白字符串
)取消對第一個字符串的選擇
然後單擊
Next 和
FinishEclipse 創建一個新的名為 com
ibm
developerworks
Messages 的類
這個類從 messages
properties 文件獲取字符串
處理國際化代碼
具體化代碼之後Eclipse 修改初始的類將字符串移入 messagesproperties 文件並創建一個名為 Messages 的新類Messages 類有一個名為 getString() 的靜態方法應用程序將使用該方法來獲得字符串的值
Messages 類在內部使用 ResourceBundle清單 展示了生成的用於創建 ResourceBundle 的代碼
清單 創建 ResourceBundle
public class Messages {
private static final String BUNDLE_NAME =
comibssages; //$NONNLS$
private static final ResourceBundle RESOURCE_BUNDLE =
ResourceBundlegetBundle(BUNDLE_NAME);
稍後我將更詳細地談到如何創建 ResourceBundle
所有字符串的值都在 messages
properties 文件中
如清單
所示
清單 messagesproperties 文件
LocalizedValidator=News Gothic
LocalizedValidator=Validate
LocalizedValidator=[]{}([]{})?
LocalizedValidator=Your postal code is valid
LocalizedValidator=Your postal code is not valid
LocalizedValidator=Exit
LocalizedValidator=Localized Data Validator
LocalizedValidator=Enter your postal code then click Validate:
從技術上說
該文件是 com/ibm/developerworks/messages
properties
但是您不必關心這個細節
生成的代碼可以正確無誤地找到該文件
使用 ResourceBundle 來驗證數據 當使用 Eclipse Externalize Strings 功能創建
properties 文件時
它修改了應用程序
以便同時獲取正則表達式和程序中所有其他可翻譯的文本
如清單
所示
清單 通過 ResourceBundle 使用正則表達式
Pattern pc = pile(MessagesgetString(LocalizedValidator));
//$NONNLS$
Matcher m = pcmatcher(postalCodegetText());
if (mmatches())
{
validLabelsetText(MessagesgetString(LocalizedValidator));
//$NONNLS$
validLabelsetForeground(ColorBLUE);
}
else
{
validLabelsetText(MessagesgetString(LocalizedValidator));
//$NONNLS$
validLabelsetForeground(ColorRED);
}
注意
pile() 方法使用 Messages
getString() 方法來獲得正則表達式的值
當需要驗證數據時
代碼首先獲得字符串 LocalizedValidator
然後使用它來驗證郵政編碼
反饋消息也是從 properties 文件獲得的
如何裝載 properties 文件 至此
主應用程序已經可以使用
翻譯
好的正則表達式了
所有字符串的值都來自 messages
properties 文件
那麼
如何裝載這些字符串的不同版本呢?答案取決於 ResourceBundle 是如何創建的
無論何時運行一個 Java 程序
它都有一個特定的
地區地區由兩個字母的語言代碼和兩個字母的國家代碼來指定
這些代碼是由 ISO 標准定義的
地區代碼還有一個不常用的變種部分
用於更精確地指定特定的地區
下面是一些例子
en_US 是 U
S
English 地區
en_CA 是 Canadian English 地區
fr_CA 是 French Canadian 地區
en 是 English 地區
en_US_UNIX 是 U
S
English 地區的 UNIX 變種
至於該變種的意義及其用法
是由應用程序的編寫者定義的
當創建一個新的 ResourceBundle 時Java 運行時根據當前的地區查找文件例如如果當前地區是 en_US那麼 Java 運行時依次查找以下文件
messages_en_USproperties
messages_enproperties
messagesproperties
當 ResourceBundle 收集翻譯好的字符串時在 messages_en_USproperties 中發現的任何字符串都具有比 messages_enproperties 和 messagesproperties 中具有相同名稱的字符串更高的優先級如果運行時沒有發現任何特定於地區的文件那麼它將使用 messagesproperties 中的字符串
記住創建 ResourceBundle 的代碼指定了文件名 messagesproperties該文件名不會隨著地區的改變而改變這意味著您的代碼也不需要做出更改您只需指定這個文件名Java 運行時可以自動得出應該裝載哪個特定於地區的文件
特定於地區的 properties 文件
一個特定於地區的 properties 文件只包含不同於更通用的 properties 文件的字符串例如如果 messages_enproperties 文件包含 LocalizedValidator=What is your favorite color? 這一行那麼 messages_en_GBproperties 文件可能包含 LocalizedValidator=What is your favourite colour?如果只有這個英國化的字符串是 en_GB 地區所特有的那麼 messages_en_GBproperties 文件只需包含這個字符串當代碼向 ResourceBundle 請求任何其他字符串時如果 messages_enproperties 中有這樣的字符串就使用其中的字符串如果 messages_enproperties 文件中沒有那樣的字符串則使用 messagesproperties 中的版本如果這一系列的 properties 文件中都沒有被請求的字符串就會拋出 javautilMissingResourceException 異常
清單 展示了美國地區的 properties 文件所特有的一些行
清單 en_US(美國)地區特有的值
LocalizedValidator=Your ZIP Code is valid
LocalizedValidator=Your ZIP Code is not valid
LocalizedValidator=Enter your ZIP Code then click Validate:
這裡惟一的變化是使用
ZIP Code
代替
postal code
可用默認的正則表達式驗證該數據
英國的郵政編碼有六種不同的格式
還有一個特殊的值 GIR
AA
如清單
所示
(為了便於閱讀
清單
中的正則表達式被分成兩行
實際上只有一行
)
清單 en_GB(英國)地區特有的值
LocalizedValidator=
[AZ]([]|[]{}|[AZ][]|[AZ][]{}|[][AZ]
|[AZ][][AZ]) [][AZ]{}|GIR AA
LocalizedValidator=Enter your postcode then click Validate:
用於澳大利亞的正則表達式包括州或地區的簡稱
需要的空格(一個或兩個)
以及一個四位數
如清單
所示
清單 en_AU(澳大利亞)地區特有的值
LocalizedValidator=(ACT|NSW|NT|QLD|SA|TAS|VIC|WA)( | )[]{}
LocalizedValidator=Enter your Australian postal code then click Validate:
加拿大的郵政編碼格式是字母
數字
字母
一個空格
數字
字母
數字
如清單
所示
清單 en_CA(加拿大)地區特有的值
LocalizedValidator=[AZ][][AZ] [][AZ][]
LocalizedValidator=Enter your Canadian postal code then click Validate:
清單
展示了德國地區特有的值
德國的郵政編碼是一個五位數
清單 de(德國)地區特有的值
LocalizedValidator=Validieren
LocalizedValidator=[]{}
LocalizedValidator=Ihre Postleitzahl ist gültig
LocalizedValidator=Ihre Postleitzahl ist ungültig!
LocalizedValidator=Beenden
LocalizedValidator=NLS Datenvalidatung
LocalizedValidator=Geben Sie Ihre Postleitzahl ein
在運行時設置地區 現在您已經定義了
properties 文件
接下來應該用兩種方法中的一種來測試這些文件
第一種方法是在運行應用程序的時候設置 user
language 和 untry 這兩個系統屬性
在 Eclipse 環境中
可以右鍵單擊一個類名
然後選擇
Run 菜單
如圖
所示
圖 Run 菜單 在 Run 對話框中
可以設置 Java VM 選項
以改變默認的語言和地區
如圖
所示
圖 在 Run 對話框中設置 Java VM 參數 D 選項用於定義系統屬性
您可以在命令行中使用相同的語法
例如
java Duserlanguage=en untry=
AU comibmdeveloperworksLocalizedValidator
第二種方法是在應用程序中設置地區
通過 Locale
setDefault() 方法可以在代碼中設置默認的地區
清單
展示了如何改變 LocalizedValidator 類的 main() 方法
清單 在應用程序中設置默認的地區
public static void main(String[] args) {
String language = ;
String country = ;
if (argslength > )
language = args[];
if (argslength > )
country = args[];
LocalesetDefault(new Locale(language country));
LocalizedValidator nv = new LocalizedValidator();
nvshow();
}
如果在命令行沒有指定參數
則使用用戶計算機的默認地區
如果沒有命令行參數
則代碼 new Locale(
) 只是創建默認的地區
也可以在 Run 對話框中設置命令行參數
如圖
所示
圖 在 Run 對話框中設置命令行參數 圖
展示了指定了參數 en AU 的情況下應用程序的界面
圖 用於澳大利亞地區(en_AU)的示例應用程序 用參數 de 運行示例應用程序時
將得到如圖
所示的界面
圖 用於德國地區(de)的示例應用程序 結束語 本文展示了如何將正則表達式與 Java 語言的國際化支持相結合來驗證不同類型的本地化數據
通過這種技巧
您可以支持新的數據類型
而不用更改任何代碼
例如示例應用程序
如果您想添加對波蘭的郵政編碼的支持
那麼只需創建一個 messages_pl
properties 文件
這樣就在沒有更改任何代碼的情況下添加了對新數據類型的支持
(如果您想知道的話
那麼告訴您
用於波蘭的郵政編碼的正則表達式是 [
]{
}
?[
]{
}
)
示例應用程序原封不動地使用 Eclipse 生成的 Messages 類
這個類能滿足這個例子的要求
但是
應用程序啟動時會裝載 ResourceBundle
並且直到下次運行應用程序時才能重新裝載 ResourceBundle
如果您想更改代碼
以便動態地改變 ResourceBundle
那麼需要修改 Messages 類
使它的字段和方法不是靜態的
這做起來不難
但是您還需要修改和維護 Messages
java 文件
就把這個任務作為練習吧
還應該認識到
Swing 提供了 javax
swing
JFormattedTextField 類
利用這個類可以為文本域定義一個
掩碼例如
您可以使用掩碼 (###) ###
####
使用戶只能在文本域中輸入有效的美國的電話號碼
您可以使用與這裡相同的技巧來從一個本地化的 ResourceBundle 中獲得掩碼字符串
JFormattedTextField 類有明顯的優勢
因為它可以在用戶輸入時驗證數據
為用戶提供直接的反饋
但是掩碼字符串不如正則表達式那麼靈活
例如
您可以為美國的 ZIP Code 編寫掩碼 ##### 或 #####
####
但是不能同時使用這兩個掩碼
如果一個掩碼字符串足以處理一組本地化數據類型
那麼從 ResourceBundle 獲得掩碼字符串就是本技巧的一個很好的用途
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26288.html