javascript
在Spring MVC中使用多个属性文件
每個人都聽說過將單個Web應用程序組合成一個大型應用程序的門戶。 門戶軟件的工作原理類似于mashup -來自多個來源的內容在單個服務中被拾取,大部分顯示在單個網頁中。 門戶軟件還允許在嵌入到門戶軟件中的所有單個Web應用程序(獨立模塊)之間更改用戶設置,例如語言或主題。 此外,預計將實現單點登錄(SSO),它也應能正常工作。 這意味著一次登錄即可使用戶訪問所有嵌入式Web應用程序。 知道在JEE世界中是否有一個簡單而輕巧的解決方案來開發模塊化JSF 2應用程序,以自動將其收集并呈現在一個類似門戶的Web應用程序中,將是很有趣的。 當然,有OSGi和復雜的Portals Bridge為JSR-168或JSR-286兼容的Portlet開發提供支持。 但是幸運的是,JSF 2已經為“幕后”提供了一種簡單的可能性。 我們可以用更少的精力來構建類似于門戶的軟件。 我們需要的只是JSF 2和CDI – Java世界中事實上的標準DI框架。
這篇文章的主題不是新的。 您可以在網上找到一些討論和想法。 我只在這里提到兩個鏈接。 第一個是ocpsoft博客中的文章“操作方法:具有CDI和PrettyFaces的模塊化Java EE應用程序” 。 第二個“使用JSF2的模塊化Web應用程序”在JBoss的Wiki中進行了介紹。 這個想法是創建包含單個Web應用程序的JAR文件,并為其提供主要的WAR文件。 WAR文件在構建過程中(例如,通過Maven依賴項)將JAR捆綁在一起。 這意味著JAR位于WAR中的WEB-INF / lib /下。 JAR中的XHTML文件放置在/ META-INF / resources /下,并且將由JSF 2自動獲取。JSF可以使用它們,就像它們在/ webapp / resources /文件夾中一樣。 例如,您可以使用非常常見的ui:include來包含JAR中的facelets。 這就像一個魅力。 為了能夠在運行時獲取有關每個JSF模塊的一般信息,我們還需要JARs文件中的空CDI的beans.xml。 它們通常位于
META-INF文件夾。
現在讓我們開始編碼。 但是首先,讓我們定義項目的結構。 您可以在GitHub上找到完整的實現示例 。 這只是使用演示Web應用程序(用JSF 2.2編寫)的類似于JSF 2門戶的輕量級實現的概念證明。 有5個子項目:
- jsftoolkit-jar基本框架,為模塊化JSF應用程序提供接口和實用程序。
- modA-jar第一個Web應用程序(模塊A),它依賴于jsftoolkit-jar。
- modB-jar依賴jsftoolkit-jar的第二個Web應用程序(模塊B)。
- portal-jar Java,類似于門戶的軟件的一部分。 它還取決于jsftoolkit-jar。
- portal-war類門戶軟件的Web部分。 它匯總了所有文物,并且是可部署的WAR。
基本框架(jsftoolkit-jar)具有應由每個單個模塊實現的接口。 最重要的是
/*** Interface for modular JSF applications. This interface should be implemented by every module (JSF app.)* to allow a seamless integration into a "portal" software.*/ public interface ModuleDescription {/*** Provides a human readable name of the module.** @return String name of the module*/String getName();/*** Provides a description of the module.** @return String description*/String getDescription();/*** Provides a module specific prefix. This is a folder below the context where all web pages and* resources are located.** @return String prefix*/String getPrefix();/*** Provides a name for a logo image, e.g. "images/logo.png" (used in h:graphicImage).** @return String logo name*/String getLogoName();/*** Provides a start (home) URL to be navigated for the module.** @return String URL*/String getUrl(); }/*** Any JSF app. implementing this interface can participate in an unified message handling* when all keys and messages are merged to a map and available via "msgs" EL, e.g. as #{msgs['mykey']}.*/ public interface MessagesProvider {/*** Returns all mesages (key, text) to the module this interface is implemented for.** @param locale current Locale or null* @return Map with message keys and message text.*/Map<String, String> getMessages(Locale locale); }模塊A的可能實現如下所示:
/*** Module specific implementation of the {@link ModuleDescription}.*/ @ApplicationScoped @Named public class ModADescription implements ModuleDescription, Serializable {@Injectprivate MessagesProxy msgs;@Overridepublic String getName() {return msgs.get("a.modName");}@Overridepublic String getDescription() {return msgs.get("a.modDesc");}@Overridepublic String getPrefix() {return "moda";}@Overridepublic String getLogoName() {return "images/logo.png";}@Overridepublic String getUrl() {return "/moda/views/hello.jsf";} }/*** Module specific implementation of the {@link MessagesProvider}.*/ @ApplicationScoped @Named public class ModAMessages implements MessagesProvider, Serializable {@Overridepublic Map<String, String> getMessages(Locale locale) {return MessageUtils.getMessages(locale, "modA");} }該模塊的前綴是moda。 這意味著網頁和資源位于文件夾META-INF / resources / moda /下。 這樣可以避免所有單個Web應用程序之間的路徑沖突(相同路徑)。 實用程序類MessageUtils(來自jsftoolkit-jar)不在此處公開。 我將只顯示MessagesProxy類。 MessagesProxy類是一個應用程序范圍的Bean,可訪問模塊化JSF Web應用程序中的所有可用消息。 由于它實現了Map接口,因此可以在Java和XHTML中使用。 CDI在運行時會自動注入MessagesProvider接口的所有可用實現。 我們使用Instance <MessagesProvider>。
@ApplicationScoped @Named(value = "msgs") public class MessagesProxy implements Map<String, String>, Serializable {@Injectprivate UserSettingsData userSettingsData;@Any@Injectprivate Instance<MessagesProvider> messagesProviders;/** all cached locale specific messages */private Map<Locale, Map<String, String>> msgs = new ConcurrentHashMap<Locale, Map<String, String>>();@Overridepublic String get(Object key) {if (key == null) {return null;}Locale locale = userSettingsData.getLocale();Map<String, String> messages = msgs.get(locale);if (messages == null) {// no messages to current locale are available yetmessages = new HashMap<String, String>();msgs.put(locale, messages);// load messages from JSF impl. firstmessages.putAll(MessageUtils.getMessages(locale, MessageUtils.FACES_MESSAGES));// load messages from providers in JARsfor (MessagesProvider messagesProvider : messagesProviders) {messages.putAll(messagesProvider.getMessages(locale));}}return messages.get(key);}public String getText(String key) {return this.get(key);}public String getText(String key, Object... params) {String text = this.get(key);if ((text != null) && (params != null)) {text = MessageFormat.format(text, params);}return text;}public FacesMessage getMessage(FacesMessage.Severity severity, String key, Object... params) {String summary = this.get(key);String detail = this.get(key + "_detail");if ((summary != null) && (params != null)) {summary = MessageFormat.format(summary, params);}if ((detail != null) && (params != null)) {detail = MessageFormat.format(detail, params);}if (summary != null) {return new FacesMessage(severity, summary, ((detail != null) ? detail : StringUtils.EMPTY));}return new FacesMessage(severity, "???" + key + "???", ((detail != null) ? detail : StringUtils.EMPTY));}/// java.util.Map interface/public int size() {throw new UnsupportedOperationException();}// other methods ... }好。 但是,在何處獲取ModuleDescription的實例? 邏輯位于門戶jar中。 我對CDI實例使用相同的機制。 CDI將為我們找到ModuleDescription的所有可用實現。
/*** Collects all available JSF modules.*/ @ApplicationScoped @Named public class PortalModulesFinder implements ModulesFinder {@Any@Injectprivate Instance<ModuleDescription> moduleDescriptions;@Injectprivate MessagesProxy msgs;private List<FluidGridItem> modules;@Overridepublic List<FluidGridItem> getModules() {if (modules != null) {return modules;}modules = new ArrayList<FluidGridItem>();for (ModuleDescription moduleDescription : moduleDescriptions) {modules.add(new FluidGridItem(moduleDescription));}// sort modules by names alphabeticallyCollections.sort(modules, ModuleDescriptionComparator.getInstance());return modules;} }現在,我們可以在UI中創建動態圖塊,這些圖塊表示相應Web模塊的入口點。
<pe:fluidGrid id="fluidGrid" value="#{portalModulesFinder.modules}" var="modDesc"fitWidth="true" hasImages="true"><pe:fluidGridItem styleClass="ui-widget-header"><h:panelGrid columns="2" styleClass="modGridEntry" columnClasses="modLogo,modTxt"><p:commandLink process="@this" action="#{navigationContext.goToPortlet(modDesc)}"><h:graphicImage library="#{modDesc.prefix}" name="#{modDesc.logoName}"/></p:commandLink><h:panelGroup><p:commandLink process="@this" action="#{navigationContext.goToPortlet(modDesc)}"><h:outputText value="#{modDesc.name}" styleClass="linkToPortlet"/></p:commandLink><p/><h:outputText value="#{modDesc.description}"/></h:panelGroup></h:panelGrid></pe:fluidGridItem> </pe:fluidGrid>磁貼是由PrimeFaces Extensions中的 pe:fluidGrid組件創建的。 它們具有響應能力,這意味著它們在調整瀏覽器窗口大小時會重新排列。 下圖演示了啟動后門戶網站應用程序的外觀。 它顯示了在類路徑中找到的兩個模塊化演示應用程序。 每個模塊化Web應用程序都顯示為包含徽標,名稱和簡短描述的圖塊。 徽標和名稱是可單擊的。 單擊將重定向到相應的單個Web應用程序。
如您所見,您可以在門戶的主頁上切換當前語言和主題。 第二張圖片顯示了如果用戶單擊模塊A會發生什么。顯示了模塊A的Web應用程序。 您可以看到“返回門戶”按鈕,因此可以向后導航到門戶的主頁。
最后有兩個注釋:
翻譯自: https://www.javacodegeeks.com/2013/12/using-more-than-one-property-file-in-spring-mvc.html
總結
以上是生活随笔為你收集整理的在Spring MVC中使用多个属性文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 施工员证备案怎么自己退出(施工员证备案)
- 下一篇: 小米14配置细节曝光:搭载1mm极窄边框