資源包技巧和最佳實踐

今天是資源捆綁日。 通常,這是Java中最著名的國際化機制(i18n)。 使用它應該很容易。 但是,在弄臟手時會出現許多小問題。 如果您有相同的想法,則此文章適合您。

基本

java.util.ResourceBundle定義了用于訪問Java中翻譯的標準化方法。 它們包含特定于語言環境的資源。 資源束屬于其成員具有相同基本名稱的族,但是其名稱還具有標識
他們的語言環境。 族中的每個資源束都包含相同的項目,但是這些項目已針對該資源束所代表的語言環境進行了翻譯。 這些是鍵/值對。 這些鍵唯一地標識捆綁軟件中特定于語言環境的對象。

最基本的示例使用以下知識:
Messages.properties
Messages_de.properties Messages_en.properties

如果您需要在應用程序中查詢包,則只需調用

ResourceBundle bundle = ResourceBundle.getBundle("Messages");

方法并查詢返回的包:

bundle.getString("welcome.message");

如果您想在此處使用哪種語言環境,那是對的。 String構造函數隱式使用Locale.getDefault()解析語言。 那可能不是您想要的。 所以你應該ResourceBundle bundle =

ResourceBundle.getBundle("Messages", locale);

檢索捆綁軟件后,您將無法設置語言環境。 每個ResourceBundle都有一個定義的語言環境。

命名的東西
?
關于命名的一些想法。 用其內容命名捆綁屬性。 您可以通過簡單地將它們命名為“消息”和“錯誤”等來采用更通用的方式。但是,每個子系統或組件也可以具有捆綁軟件。 無論您需要什么。 要維護內容,要輸入大量條目并不容易。 因此,任何類型的上下文拆分都會使開發人員感到高興。 捆綁軟件屬性文件等效于類。 相應地命名。 進一步,您應該找到一個用于命名密鑰的通用系統。 根據為屬性文件選擇的拆分,還可能在密鑰中引入某種子系統或組件名稱空間。 頁面前綴也是可能的。 明智地考慮一下,并加以解決。 您的目標是盡量減少密鑰重復。

封裝
?
如您所見,您經常使用包的字符串表示形式。 這些實際上是文件名(或更好的類名),您可以通過一個簡單的枚舉來更好地封裝所有內容:

public enum ResourceBundles {MESSAGES("Messages"),ERRORS("Errors");private String bundleName;  ResourceBundles(String bundleName) {this.bundleName = bundleName;}public String getBundleName() {return bundleName;}@Overridepublic String toString() {return bundleName;}
}

有了這個你就可以寫

ResourceBundle bundle = ResourceBundle.getBundle(MESSAGES.getBundleName());

Java Server Faces和ResourceBundle
?
要在基于jsf的應用程序中使用資源包,您只需在faces-config.xml中定義它們,并使用xhtml文件中的快捷方式。

<resource-bundle>
<base-name>Messages</base-name>
<var>msgs</var>
<h:outputLabel value="#{msgs['welcome.general']}" />

JSF負責其余的工作。 那么參數替換呢? 考慮如下的鍵值對:

welcome.name=Hi {0}! How are you?

您可以通過f:param標簽傳遞參數:

<h:outputFormat value="#{msgs['welcome.name']}"><f:param value="Markus" /></h:outputFormat>

要更改語言,您必須為當前的FacesContext實例設置特定的語言環境。 最好通過值更改偵聽器執行此操作:

public void countryLocaleCodeChanged(ValueChangeEvent e) {String newLocaleValue = e.getNewValue().toString();//loop country map to compare the locale codefor (Map.Entry<String, Object> entry : countries.entrySet()) {if (entry.getValue().toString().equals(newLocaleValue)) {FacesContext.getCurrentInstance().getViewRoot().setLocale((Locale) entry.getValue());}}}

EJB中的資源包
?
JSF顯然很容易集成。 在EJB中使用這些捆綁包怎么辦? 基本上是一樣的。 您可以使用相同的機制來使用和使用捆綁包。 您應該記住一件事。 您可能不想始終使用默認語言環境。 因此,您必須找到一種從UI向下傳遞語言環境的方法。 如果您想通過@Produces批注@Injecting MessageBundle,則必須考慮多次。 尤其是在使用@Stateless EJB時。 這些實例將合并,您必須將語言環境傳遞給需要了解當前語言環境的任何業務方法。 通常,您可以使用參數對象或某種用戶會話配置文件來執行此操作。 不要將語言環境全部添加為方法簽名。

來自數據庫的資源包
?
在大多數情況下,我看到您需要從數據庫中提取密鑰。 鑒于ResourceBundle的內部工作原理(每個語言環境一個“類”),您最終不得不在自己的ResourceBundle實現中實現邏輯。 您在網絡上找到的大多數示例都是通過重寫handleGetObject(String key)方法來實現的。 我不喜歡這種方法,尤其是因為我們有一個更好的方法來使用ResourceBundle.Control機制。 現在,您可以覆蓋newBundle()方法并返回自己的ResourceBundle實現。 您所要做的就是將自己的Control設置為DatabaseResourceBundle的父級:

public DatabaseResourceBundle() {setParent(ResourceBundle.getBundle(BUNDLE_NAME,FacesContext.getCurrentInstance().getViewRoot().getLocale(), new DBControl()));}

DBControl返回MyResourceBundle,它是一個ListResourceBundle:

protected class DBControl extends Control {@Overridepublic ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)throws IllegalAccessException, InstantiationException, IOException {return new MyResources(locale);}/*** A simple ListResourceBundle*/protected class MyResources extends ListResourceBundle {private Locale locale;/*** ResourceBundle constructor with locale** @param locale*/public MyResources(Locale locale) {this.locale = locale;}@Overrideprotected Object[][] getContents() {TypedQuery<ResourceEntity> query = _entityManager.createNamedQuery("ResourceEntity.findForLocale", ResourceEntity.class);query.setParameter("locale", locale);List<ResourceEntity> resources = query.getResultList();Object[][] all = new Object[resources.size()][2];int i = 0;for (Iterator<ResourceEntity> it = resources.iterator(); it.hasNext();) {ResourceEntity resource = it.next();all[i] = new Object[]{resource.getKey(), resource.getValue()};values.put(resource.getKey(), resource.getValue());i++;}return all;}}}

如您所見,這由一個entitymanager和一個簡單的ResourceEntity作為后盾,該ResourceEntity具有構建不同捆綁軟件所需的所有字段和NamedQueries。

@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;@Column(name = "i18n_key")private String key;@Column(name = "i18n_value")private String value;@Column(name = "i18n_locale")private Locale locale;

通過將捆綁包放入私有Map <String,String>值= new HashMap <String,String>(); 在首次構建捆綁包之后,您還可以使用一種很好的方法來緩存結果。

這仍然不是最好的解決方案,因為ResourceBundles具有緩存的方式。 但我稍后可能會更詳細地探討這一點。 到現在為止,此捆綁包將被永久緩存(或至少直到下一次重新部署為止)。

改寫為語言切換
?
最后要提到的是,您還可以在此處添加一些精美的插件。 如果您已經有了JSF語言切換魔術,則可以輕松地將ocpsoft的重寫添加到您的應用程序中。 這是一種將網址中的語言編碼的簡單方法,例如http://yourhost.com/Bundle-Provider-Tricks/en/index.html 您要做的就是通過添加兩個簡單的依賴關系來向游戲添加重寫:

<dependency><groupId>org.ocpsoft.rewrite</groupId><artifactId>rewrite-servlet</artifactId><version>1.1.0.Final</version></dependency><dependency><groupId>org.ocpsoft.rewrite</groupId><artifactId>rewrite-integration-faces</artifactId><version>1.1.0.Final</version></dependency>

重寫需要您添加自己的ConfigurationProvider,這是保存重寫規則的中心位置。 執行以下操作:

public class BundleTricksProvider extends HttpConfigurationProvider {@Overridepublic Configuration getConfiguration(ServletContext context) {return ConfigurationBuilder.begin()// Locale Switch.addRule(Join.path("/{locale}/{page}.html").to("/{page}.xhtml").where("page").matches(".*").where("locale").bindsTo(PhaseBinding.to(El.property("#{languageSwitch.localeCode}")).after(PhaseId.RESTORE_VIEW)));}@Overridepublic int priority() {return 10;}
}

接下來是將一個名為“ org.ocpsoft.rewrite.config.ConfigurationProvider”的文件添加到您的META-INF / services文件夾,并在其中放置您的ConfigurationProvider實現的標準名稱。 最后要調整的是LanguageSwitch bean中的邏輯。 重寫不能觸發ValueChangeEvent(據我所知:)),因此您必須在調用setter時添加一些魔術來更改Locale。 就是這樣..非常簡單!

參考:來自JCG合作伙伴 Markus Eisele的Resource Bundle技巧和最佳實踐 ,位于Enterprise Software Development with Java博客上。


翻譯自: https://www.javacodegeeks.com/2012/09/resource-bundle-tricks-and-best.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/371351.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/371351.shtml
英文地址,請注明出處:http://en.pswp.cn/news/371351.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

springMvc-文件上傳

趕時間&#xff0c;又在寫垃圾博客&#xff0c;在心里給自己一耳巴 1.單文件上傳 2.多文件上傳 代碼&#xff1a; 頁面&#xff1a; <!DOCTYPE html><html><head><meta charset"UTF-8"><title>Insert title here</title></he…

c cuda 指定gpu_GPU并行編程:熟練使用CUDA C語言

【IT168 專稿】一個大任務通常可能被分解成許多可以一起處理的小任務&#xff0c;以便創建一個解決方案&#xff0c;這和粉刷房子的道理是一樣的&#xff0c;在粉刷之前&#xff0c;假設你需要買5公升油漆和5把刷子&#xff0c;你可以自己一個人干完采購和粉刷的活&#xff0c;…

js中使用0 “” null undefined {}需要注意

注意&#xff1a;在js中0為空&#xff08;false&#xff09; &#xff0c;代表空的還有“”&#xff0c;null &#xff0c;undefined&#xff1b; 如果做判斷if(&#xff01;上面的四種值)&#xff1b;返回均為false console.log(!null);// true console.log(!0);//true consol…

PhpStorm 10.0.3破解版下載

漢化破解版軟件下載&#xff1a; http://pan.baidu.com/s/1geNO24r 密碼: d5ci 這個漢化破解軟件解決了大綱視圖里空白的問題。 先安裝騰訊電腦管家&#xff0c;然后安裝這個軟件&#xff0c;安裝到最后提示有個文件有病毒已刪除&#xff0c;點確定后正常使用。轉載于:https://…

Jenkins:部署JEE工件

隨著持續集成和持續交付的出現 &#xff0c;我們的構建被分為不同的步驟&#xff0c;以創建部署管道。 這些步驟中的一些步驟可以是例如編譯和運行快速測試&#xff0c;運行慢速測試&#xff0c;運行自動驗收測試或發布應用程序等。 部署流程的最后一步意味著將我們的產品&…

seafile 部署_Seafile開啟webdav及讀寫性能測試

為什么要在seafile搞webdavSeafile 一直是一款可靠的文件同步web應用&#xff0c;經過個人測試&#xff0c;同一臺機器上&#xff0c;seafile在傳輸文件時的速度比nextcloud要快&#xff08;可能也與php的設置有關系&#xff09;&#xff0c;這是seafile的優勢。但是&#xff0…

Python--校園網爬蟲記

查成績&#xff0c;算分數&#xff0c;每年的綜合測評都是個固定的過程&#xff0c;作為軟件開發者&#xff0c;這些過程當然可以交給代碼去做&#xff0c;通過腳本進行網絡請求獲取數據&#xff0c;然后直接進行計算得到基礎分直接填表就好了&#xff0c;查成績再手動計算既容…

Spring–添加SpringMVC –第1部分

歡迎來到本教程的第四部分。 在這一部分中&#xff0c;我們將使用Spring MVC編寫控制器和視圖&#xff0c;并考慮我們的REST模型。 我們必須做的第一件事&#xff0c;就是根據目前的情況制作一個Web應用程序。 我們將web / WEB-INF文件夾添加到我們的項目根目錄。 在WEB-INF內創…

[Linux] 權限與指令間的關系

我們知道權限對于使用者帳號來說是非常重要的&#xff0c;因為他可以限制使用者能不能讀取/創建/刪除/修改文件或目錄&#xff01; 在這一章我們介紹了很多文件系統的管理指令&#xff0c;第五章則介紹了很多文件權限的意義。在這個小節當中&#xff0c; 我們就將這兩者結合起來…

access month函數用法_學會了這7個EXCEL日期函數技巧,老板再讓你加班,你找我!...

日期函數&#xff0c;常用年月日&#xff0c;時分秒&#xff0c;星期&#xff0c;季度&#xff0c;求差值等&#xff0c;學會以下幾個函數&#xff0c;老板再讓你加班&#xff0c;你找我&#xff01;1、記錄當前時間(不隨系統時間變化)NOW()函數與數據有效性結合&#xff0c;記…

css樣式表的選擇器與分類

css 樣式表的作用&#xff1a; 主要用于結構,樣式與行為,CSS主要的作用就是美化網頁的一個語言,它的特點: 1.結構與樣式分離的方式,便于后期維護與改版; 2.樣式定義精確到像素的級別; css樣式表的結構&#xff1a;CSS 稱為層疊樣式表 用于給網頁設置各種樣式 css樣式的語法由3部…

Spring 3.1緩存和@Cacheable

緩存在軟件領域已經存在很長時間了。 它們是那些真正有用的東西之一&#xff0c;一旦您開始使用它們&#xff0c;您會想知道如果沒有它們&#xff0c;您是如何相處的&#xff0c;所以似乎讓Spring的家伙們只是在版本中向Spring核心添加緩存實現有點奇怪。 3.1。 我猜想以前沒有…

pytorchyolov4訓練_使用pytorch-yolov5 訓練自己的數據集-2020.6.15

make yolov5 pytorch train datasets訓練所需環境 python3.5, pytorch1.3, torchvision 0.4.1 , tensorboard 1.14.0 , tensorflow-gpu1.14.0本例制作yolov5數據集 并進行數據訓練從VOC數據集轉為訓練所需的coco數據集代碼有待改進包含文件夾voc2coco/(Annotations/ JPEGImages…

meta 的作用 搜集

Meta標簽中的format-detection屬性及含義 format-detection翻譯成中文的意思是“格式檢測”&#xff0c;顧名思義&#xff0c;它是用來檢測html里的一些格式的&#xff0c;那關于meta的format-detection屬性主要是有以下幾個設置&#xff1a;<meta name"format-detecti…

Web服務安全性和SOA路線圖的人為維度

在大多數非平凡的SOA環境中&#xff0c;很難跟蹤系統之間不斷發展的集成&#xff0c;除非有明確的發布和查找適當信息的方法。 概述IT環境&#xff0c;定義當前或將要連接的內容&#xff0c;是維護環境的先決條件。 缺少這種情況通常會導致“面向意大利面條的環境”的感覺&…

pccad自定義圖框_(PCCAD自定義標題欄詳細方法.doc

PCCAD2011自定義標題欄詳細方法下面以圖3-1為例說明標題欄的自定義過程。圖3-11&#xff0e;新建文件(用New 命令)。2&#xff0e;用繪圖和文字中的相關命令設計出圖3-1所示的圖形。其中在使用中不變的內容&#xff0c;如廠名等均用“文字”命令標出&#xff0c;而需臨時填充的…

ThinkPHP 3.2.x 集成極光推送指北

3.2版本已經過了維護生命周期&#xff0c;官方已經不再維護&#xff0c;請及時更新至5.0版本 —— ThinkPHP 官方倉庫 以上&#xff0c;如果有條件&#xff0c;請關閉這個頁面&#xff0c;然后升級至 ThinkPHP 5&#xff0c;如果由于各種各樣的原因無法升級至 TP 5 &#xff0c…

Java:選擇正確的集合

這是在應用程序中選擇Set &#xff0c; List或Map的正確實現的快速指南。 最好的通用或“主要”實現可能是ArrayList&#xff0c;LinkedHashMap和LinkedHashSet。 它們的整體性能更好&#xff0c;除非您需要其他實現提供的特殊功能&#xff0c;否則應使用它們。 該特殊功能通常…

Java多線程——不變性與安全發布

1、不變性 某個對象在被創建后其狀態就不能被修改&#xff0c;那么這個對象就稱為不可變對象&#xff0c;不可變對象一定是線程安全的。不可變對象很簡單。他們只有一種狀態&#xff0c;并且該狀態由構造函數來控制。 當滿足以下條件時&#xff0c;對象才是不可變的&#xff1a…

中tr不能顯示字符_垃圾文本識別中基本操作指南和錯誤總結,第三部分

創建模型需要用到機器學習的庫&#xff0c;所以我們先下載sklearn庫sklearn庫下載完成后再輸入庫文件&#xff0c;就可以完美運行。然后就是劃分測試集和訓練集&#xff0c;需要注意的是&#xff0c;在從數據處理函數中導入數據時&#xff0c;足足運行了有將近30多秒&#xff0…