读取托管 bean 中的资源包属性
Posted
技术标签:
【中文标题】读取托管 bean 中的资源包属性【英文标题】:Read resource bundle properties in a managed bean 【发布时间】:2012-11-19 06:47:42 【问题描述】:使用<resource-bundle>
文件,我可以在我的JSF 页面中包含i18n 文本。
但是是否可以在我的托管 bean 中访问这些相同的属性,以便我可以使用 i18n 值设置面孔消息?
【问题讨论】:
【参考方案1】:假设您已将其配置如下:
<resource-bundle>
<base-name>com.example.i18n.text</base-name>
<var>text</var>
</resource-bundle>
如果您的 bean 是请求范围内的,您可以通过 <var>
将 <resource-bundle>
注入为 @ManagedProperty
:
@ManagedProperty("#text")
private ResourceBundle text;
public void someAction()
String someKey = text.getString("some.key");
// ...
或者,如果您只需要一些特定的密钥:
@ManagedProperty("#text['some.key']")
private String someKey;
public void someAction()
// ...
但是,如果您的 bean 处于更广泛的范围内,则在方法本地范围内以编程方式评估 #text
:
public void someAction()
FacesContext context = FacesContext.getCurrentInstance();
ResourceBundle text = context.getApplication().evaluateExpressionGet(context, "#text", ResourceBundle.class);
String someKey = text.getString("some.key");
// ...
或者如果你只需要一些特定的键:
public void someAction()
FacesContext context = FacesContext.getCurrentInstance();
String someKey = context.getApplication().evaluateExpressionGet(context, "#text['some.key']", String.class);
// ...
您甚至可以通过标准的ResourceBundle
API 来获取它,就像 JSF 本身已经在幕后所做的那样,您只需要在代码中重复基本名称:
public void someAction()
FacesContext context = FacesContext.getCurrentInstance();
ResourceBundle text = ResourceBundle.getBundle("com.example.i18n.text", context.getViewRoot().getLocale());
String someKey = text.getString("some.key");
// ...
或者,如果您通过 CDI 而不是 JSF 管理 bean,那么您可以为此创建一个 @Producer
:
public class BundleProducer
@Produces
public PropertyResourceBundle getBundle()
FacesContext context = FacesContext.getCurrentInstance();
return context.getApplication().evaluateExpressionGet(context, "#text", PropertyResourceBundle.class);
并注入如下:
@Inject
private PropertyResourceBundle text;
或者,如果您使用 JSF 实用程序库 OmniFaces 的 Messages
类,那么您只需设置其解析器一次,即可让所有 Message
方法使用该捆绑包。
Messages.setResolver(new Messages.Resolver()
public String getMessage(String message, Object... params)
ResourceBundle bundle = ResourceBundle.getBundle("com.example.i18n.text", Faces.getLocale());
if (bundle.containsKey(message))
message = bundle.getString(message);
return MessageFormat.format(message, params);
);
另请参阅javadoc 和showcase page 中的示例。
【讨论】:
If your bean is request scoped
是唯一可以访问属性文件的范围吗?
@Kuriel:JSF @ManagedProperty
无法在更广的范围内注入更窄的范围。只有 CDI @Inject
是。如果您碰巧使用 CDI,请前往 ***.com/q/28045667
@BalusC 在资源包文件中写入带参数的文本时应使用哪种语法形式?
@séan35:只需将捆绑值(不是键!)传递给MessageFormat#format()
。
@ManagedProperty("#text")
也适用于 @ViewScoped
和 @FlowScoped
beans。【参考方案2】:
另一种可能性:
faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<faces-config ...>
<application>
<locale-config>
<default-locale>de</default-locale>
</locale-config>
<resource-bundle>
<base-name>de.fhb.resources.text.backend</base-name>
<var>backendText</var>
</resource-bundle>
</application>
</faces-config>
YourBean.java
FacesContext context = FacesContext.getCurrentInstance();
Application app = context.getApplication();
ResourceBundle backendText = app.getResourceBundle(context, "backendText");
backendText.getString("your.property.key");
【讨论】:
【参考方案3】:这是我正在使用的解决方案,不是那么简单,但至少可以工作:
头等舱:
package com.spectotechnologies.website.util;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;
/**
*
* @author Alexandre Lavoie
*/
public class MessageInterpolator extends ResourceBundleMessageInterpolator
public static final String LANGUAGE_TAG_PATTERN = "\\[^]*\\";
@Override
public String interpolate(String p_sMessage, Context p_oContext)
return super.interpolate(replaceMessages(p_sMessage),p_oContext);
@Override
public String interpolate(String p_sMessage, Context p_oContext, Locale p_oLocale)
StringManager.setLocale(p_oLocale);
return super.interpolate(replaceMessages(p_sMessage),p_oContext,p_oLocale);
private String replaceMessages(String p_sMessage)
Matcher oMatcher;
String sKey;
String sReplacement;
StringBuffer sbTemp = new StringBuffer();
oMatcher = Pattern.compile(LANGUAGE_TAG_PATTERN).matcher(p_sMessage);
while(oMatcher.find())
sKey = oMatcher.group().substring(1,oMatcher.group().length() - 1);
sReplacement = StringManager.getString(sKey);
if(!sReplacement.startsWith("???"))
oMatcher.appendReplacement(sbTemp,sReplacement);
oMatcher.appendTail(sbTemp);
return sbTemp.toString();
二等:
package com.spectotechnologies.website.util;
import com.spectotechnologies.util.BundleManager;
import com.spectotechnologies.util.FacesSessionManager;
import java.util.Locale;
/**
* set-up and interface a BundleManager
* save the bundleManager into the session
* @author Charles Montigny
*/
public final class StringManager
/** the session name of this class bundle manager */
public static final String BUNDLE_MANAGER_SESSION_NAME = "StringManager_BundleManager";
/** List of ResourceBundle names to load.
* Will be load in order.
* The last ones values may overrite the first ones values. */
private final static String[] BUNDLE_LIST =
"com.spectotechnologies.hibernate.validation.resources.ValidationMessages",
"com.spectotechnologies.website.general.resources.ValidationMessages",
"com.spectotechnologies.website.general.resources.General";
/** bundle manager */
private static BundleManager m_oBundleManager = null;
private static BundleManager getBundleManager()
if(m_oBundleManager == null)
// get the bundle into the session
m_oBundleManager = (BundleManager)FacesSessionManager.getObject(BUNDLE_MANAGER_SESSION_NAME);
if(m_oBundleManager == null)
// session was empty, load a new one
m_oBundleManager = new BundleManager();
for(int iIndex = 0; iIndex < BUNDLE_LIST.length; iIndex++)
m_oBundleManager.addBundle(BUNDLE_LIST[iIndex]);
// add the bundle to the session
FacesSessionManager.setObject(BUNDLE_MANAGER_SESSION_NAME, m_oBundleManager);
return m_oBundleManager;
/**
* get a string value in the bundle manager by a string key
* @param p_sKey the string key
* @return the value of the string key
*/
public static String getString(String p_sKey)
return getBundleManager().getStringValue(p_sKey);
/**
* set the locale
* @param p_oLocale the locale to set
*/
public static void setLocale(Locale p_oLocale)
getBundleManager().setLocale(p_oLocale);
// update the session
FacesSessionManager.setObject(BUNDLE_MANAGER_SESSION_NAME,
getBundleManager());
在您需要使用属性文件覆盖 BUNDLE_LIST 之后。完成后,像这样使用它:
sMessage = StringManager.getString("website.validation.modifySystem.modified");
如果您有任何问题,请不要犹豫!
编辑:
你还需要声明MessageInterpolator
META-INF/validation.xml
<validation-config
xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration">
<message-interpolator>com.spectotechnologies.website.util.MessageInterpolator</message-interpolator>
</validation-config>
【讨论】:
以上是关于读取托管 bean 中的资源包属性的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot系列四:SpringBoot开发(改变环境属性读取资源文件Bean 配置模版渲染profile 配置)
com.sun.faces.mgbean.ManagedBeanCreationException:在托管 bean 上执行资源注入时发生错误