如何读取消息并将参数传递给JSF 2.0中的message.properties文件

时间:2012-02-22 07:24:01

标签: jsf-2

假设我有一个像

这样的messages.properties文件
windowTitle=Accessing Form Elements with JavaScript
namePrompt=Name:
passwordPrompt=Password:
confirmPasswordPrompt=Confirm Password:

我在faces-config.xml中有这样的条目,就像这样

<faces-config version="2.0"
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">

    <application>
        <resource-bundle>
            <base-name>pk.mazars.basitMahmood.messages</base-name>
            <var>msgs</var>
        </resource-bundle>
    </application>

</faces-config>

在我的xhtml页面上,我可以像这样访问它

<h:panelGrid columns="2" columnClasses="evenColumns, oddColumns">
    #{msgs.namePrompt}
    <h:inputText/>
    #{msgs.passwordPrompt}
    <h:inputSecret id="password"/>
    #{msgs.confirmPasswordPrompt}
    <h:inputSecret id="passwordConfirm"/>
</h:panelGrid>

但我如何从Java读取此文件。比如,假设我必须打印这样的消息,或提示用户像名称必须输入

System.out.println(msgs.namePrompt + "must be entered")

如何从我的java代码中读取msgs.namePrompt值。

还假设我的消息文件中有一个条目,如此

sure=Are you sure, you want to delete the <Field>?
remove=Are you sure you want to remove the<Field> and <Field>?
close=Are you sure you want to mark the <Field> as Closed?
created=<Field> is successfully created
updated=<Field> is successfully updated

是否有任何技术可以将参数传递给我的messages.properties文件。就像我想在我的java代码中做这样的事情

System.out.println(msgs.sure("Name"));   //<Field> is replace with Name
System.out.println(msgs.remove("Age", "Gender"));  //  First Field replace by Age, and second is replace by Gender

谢谢。

2 个答案:

答案 0 :(得分:59)

facelets中的参数化资源字符串:

this tutorial中所述,您可以使用h:outputFormatf:param替换资源包字符串中的参数:

<h:outputFormat value="#{msg['message.param1']}">
   <f:param value="param0" />
</h:outputFormat>
<h:outputFormat value="#{msg['message.param2']}">
   <f:param value="param0" />
   <f:param value="param1" />
</h:outputFormat>

//properties file
message.param1 = This is "message.param1" - {0}
message.param2 = This is "message.param2" - {0} and {1}

在Java中,您可以访问如下属性文件:

import java.util.ResourceBundle;
...
ResourceBundle rb = ResourceBundle.getBundle("pk.mazars.basitMahmood.messages");

可以使用javax.text.MessageFormat类处理参数化属性:

MessageFormat.format(rb.getString(key), params);

如果您正在使用不同的区域设置以及参数化和非参数化属性,则可以使用这样的简短帮助方法:

public static String getMessageResourceString(String bundleName, String key, Object params[], Locale locale) {

        String text;
        ResourceBundle bundle = ResourceBundle.getBundle(bundleName, locale);

        try {
            text = bundle.getString(key);
        } catch (MissingResourceException e) {
            text = "?? key " + key + " not found ??";
        }

        if (params != null) {
            MessageFormat mf = new MessageFormat(text, locale);
            text = mf.format(params, new StringBuffer(), null).toString();
        }

        return text;
    }

答案 1 :(得分:4)

谢谢Matt Handy :)。我在这里发布我的答案。我也使用了与你的方法相同但添加了描述(注释)的方法。这是我正在使用的代码。这是任何人都可以使用的完整示例:)

messages.properties文件

windowTitle=Accessing Form Elements with JavaScript
namePrompt=Name:
passwordPrompt=Password:
confirmPasswordPrompt=Confirm Password:
message.param1 = This is "message.param1" - {0}
message.param2 = This is "message.param2" - {0} and {1}

faces-config.xml文件

<application>
    <resource-bundle>
        <base-name>pk.mazars.basitMahmood.messages</base-name>
        <var>msgs</var>
    </resource-bundle>
</application>

index.xhtml文件

<h:body>

    <h:form>

        <h:panelGrid columns="2" columnClasses="evenColumns, oddColumns">
            #{msgs.namePrompt}
            <h:inputText id="name" value="#{readMessages.name}" />
            #{msgs.passwordPrompt}
            <h:inputSecret id="password" value="#{readMessages.password}"/>
            #{msgs.confirmPasswordPrompt}
            <h:inputSecret id="passwordConfirm"/>

        </h:panelGrid>

        <!--A normal way to access the message.

                <h:outputText value="{msg.message}" />

                //properties file
                message = This is "message"

            For a key that has a dot “.” as name, you can’t use the normal way {msg.message.test1}, it
            will not work. Instead, you should use bracket like {msg['message.test1']}.

                <h:outputText value="{msg['message.test1']}" />

                //properties file
                message.test1 = This is "message.test1"

            To display HTML tag in the message, just add the “escape” attribute and set it to false.

                <h:outputText value="{msg['message.test2']}" />
                <h:outputText value="{msg['message.test2']}" escape="false" />
                <h:outputText value="{msg['message.test3']}" />
                <h:outputText value="{msg['message.test3']}" escape="false" />

                //properties file
                message.test2 = This is "<h2>message.test3</h2>"
                message.test3 = This is "&lt;h2&gt;message.test4&lt;/h2&gt;"

        -->
        <h:outputFormat value="#{msgs['message.param1']}">
            <f:param value="param0" />
        </h:outputFormat>

        <h:outputFormat value="#{msgs['message.param2']}">
            <f:param value="param0" />
            <f:param value="param1" />
        </h:outputFormat>

        <h:commandButton  type="button" value="Submit Form" 
                          onclick="checkPassword(this.form)"/>

    </h:form>

</h:body>

java文件

@Named(value="readMessages")
@RequestScoped
public class ReadMessages {

    private String name;
    private String password;

    /** Creates a new instance of ReadMessages */
    public ReadMessages() {

        String[] message1 = {"Basit", "Masood"};

        //FacesMessage message = getMessage(
               // "pk.mazars.basitMahmood.messages", "message.param2", new Object[]{new String("arg1")});

        String message = getMessage(
                "pk.mazars.basitMahmood.messages", "message.param2", message1);

        System.out.println();

    } // end of constructor

    public String getName() {
        return name;
    }

    public String getPassword() {
        return password;
    }

    /**
     * For proper localization, you will want to retrieve error messages from a message bundle.
     * Doing that involves some busywork with locales and class Loader.
     *
     * @param bundleName
     * @param resourceId
     * @param params
     * @return
     */
    public static String getMessage(String bundleName, String resourceId, Object[] params) {

        /**
         * Get the current locale.
         *     FacesContext context = FacesContext.getCurrentInstance();
         *     UIViewRoot viewRoot = context.getViewRoot();
         *     Locale locale = viewRoot.getLocale();
         *
         */
        FacesContext context = FacesContext.getCurrentInstance();

        /**
         * Recall that an application can supply a bundle name in a configuration file,
         * such as
         *
         *     <faces-config>
         *         <application>
         *             <message-bundle>pk.mazars.basitMahmood.messages</message-bundle>
         *         </application>
         *         ...
         *     </faces-config>
         *
         * The following code snippet retrieves that bundle name:
         *
         *     Application app = context.getApplication();
         *     String appBundleName = app.getResourceBundle();
         */
        Application app = context.getApplication();
        String appBundle = app.getMessageBundle();

        //get Locale
        Locale locale = getLocale(context);

        /**
         * Get the current class loader.  You need it to locate the resource bundle
         *
         *     ClassLoader loader = Thread.currentThread().getContextClassLoader();
         *
         */
        ClassLoader loader = getClassLoader();

        /**
         * Get the resource bundle with the given name, locale and class loader
         *
         *     ResourceBundle bundle = ResourceBundle.getBundle(bundleName, locale, loader);
         *
         */
        String summary = getString(appBundle, bundleName, resourceId, locale, loader, params);

        if (summary != null) {

            //summary = "????" + resourceId + "????";
            return summary ;

        }

        String detail = getString(appBundle, bundleName, resourceId + "detail", locale, loader, params);
        return detail;
        //return new FacesMessage(summary, detail);

    } //end of getMessage()

    public static String getString(String bundle, String resourceId, Object[] params) {

        FacesContext context = FacesContext.getCurrentInstance();
        Application app = context.getApplication();
        String appBundle = app.getMessageBundle();
        Locale locale = getLocale(context);
        ClassLoader loader = getClassLoader();
        return getString(appBundle, bundle, resourceId, locale, loader, params);

    } //end of getString()

    public static Locale getLocale(FacesContext context) {

        Locale locale = null;
        UIViewRoot viewRoot = context.getViewRoot();

        if (viewRoot != null) {

            locale = viewRoot.getLocale();

        } //end of if (viewRoot != null)

        if (locale == null) {

            locale = Locale.getDefault();

        } //end of if (locale == null)

        return locale;

    } //end of getLocale()

    public static ClassLoader getClassLoader() {

        /**
         * The Java ClassLoader is a crucial, but often overlooked, component of the Java run-time system.
         * It is the class responsible for finding and loading class files at run time.
         *
         * Among commercially popular programming languages, the Java language distinguishes itself by
         * running on a Java virtual machine (JVM). This means that compiled programs are expressed in
         * a special, platform-independent format, rather than in the format of the machine they are
         * running on. This format differs from traditional executable program formats in a number of
         * important ways.
         *
         * In particular, a Java program, unlike one written in C or C++, isn't a single executable file,
         * but instead is composed of many individual class files, each of which corresponds to a single
         * Java class.
         *
         * Additionally, these class files are not loaded into memory all at once, but rather are loaded
         * on demand, as needed by the program. The ClassLoader is the part of the JVM that loads
         * classes into memory.
         */
        ClassLoader loader = Thread.currentThread().getContextClassLoader();

        if (loader == null) {

            /**
             * Whether you override findClass or loadClass, getSystemClassLoader gives you direct
             * access to the system ClassLoader in the form of an actual ClassLoader object (instead
             * of accessing it implicitly through the findSystemClass call).
             */
            loader = ClassLoader.getSystemClassLoader();

        } //end of if (loader == null)

        return loader;

    } //end of getClassLoader()

    public static String getString(String bundle1, String bundle2, String resourceId,
        Locale locale, ClassLoader loader, Object[] params) {

        String resource = null;
        ResourceBundle bundle;

        if (bundle1 != null) {

            bundle = ResourceBundle.getBundle(bundle1, locale, loader);

            if (bundle != null) {

                try {

                    /**
                     * Get the resource string with the given ID from the bundle.
                     *
                     *     String resource = bundle.getString(resourceId);
                     *
                     */
                    resource = bundle.getString(resourceId);

                } catch (MissingResourceException e) {
                }

            } //end of if (bundle != null)

        } //end of if (bundle1 != null)

        if (resource == null) {

            bundle = ResourceBundle.getBundle(bundle2, locale, loader);

            if (bundle != null) {

                try {

                    /**
                     * Get the resource string with the given ID from the bundle.
                     *
                     *     String resource = bundle.getString(resourceId);
                     *
                     */
                    resource = bundle.getString(resourceId);

                } catch (MissingResourceException e) {
                }

            } //end of if (bundle != null)

        } //end of if (resource == null)

        if (resource == null) {

            return null;  // no match

        }

        if (params == null) {

            return resource;

        }

        /**
         * Finally, you may want some messages to provide detailed information about the
         * nature of the error. For example, you want to tell the user which character
         * in the credit card number was objectionable. Message strings can contain
         * place-holders {0}, {1} and so on - for exanple
         *
         *     The card number contains the invalid character {0}.
         *
         * The java.text.MessageFormat class can substitute values for the placeholders:
         *
         *     Object[] params = ...;
         *     MessageFormat formatter = new MessageFormat(resource, locale);
         *     String message = formatter.format(params);
         *
         * Here, the params array contains the values that should be substituted.
         */
        MessageFormat formatter = new MessageFormat(resource, locale);
        return formatter.format(params);

    } //end of getString()

} //end of class ReadMessages