java 如何在 Web 应用程序中重新加载资源包?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4325164/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to reload resource bundle in web application?
提问by marioosh
I have resource bundle as Java class that read values from database. When i update db i need to reload bundle, but i don't know how. Anybody helps ?
我有资源包作为从数据库读取值的 Java 类。当我更新数据库时,我需要重新加载包,但我不知道如何。有人帮忙吗?
package model.helpers;
public class Messages_en extends ListResourceBundle {
protected Object[][] getContents() {
// from DB
// ...
}
}
In view i use bundle as below:
鉴于我使用捆绑包如下:
<f:loadBundle basename="model.helpers.Messages" var="m" />
采纳答案by Jigar Joshi
回答by Arjan Tijms
This is not exactly trivial.
这并不完全是微不足道的。
For one just clearing the ResourceBundle
via clearCache()
doesn't always yield the desired results. Often you need at least also try to clear using the context class loader:
对于仅清除过ResourceBundle
孔的人来说clearCache()
,并不总能产生预期的结果。通常,您至少还需要尝试使用上下文类加载器进行清除:
ResourceBundle.clearCache(Thread.currentThread().getContextClassLoader());
ResourceBundle.clearCache(Thread.currentThread().getContextClassLoader());
This however will still not reload the resource bundle defined in a faces-config.xml file. At least the Mojarra JSF 1.2 implementation privately caches the resource bundle internally. This happens in:
但是,这仍然不会重新加载faces-config.xml 文件中定义的资源包。至少 Mojarra JSF 1.2 实现在内部私下缓存资源包。这发生在:
FacesContext -> Application -> associate (ApplicationAssociate) -> resourceBundles (Map<String, ApplicationResourceBundle>()) -> resources (Map<Locale, ResourceBundle>)
It's possible to clear this cache via reflection (at the end of the day, it's just an entry in a Map), or you might wanna replace the Application. Both are not things you normally do lightheartedly.
可以通过反射清除此缓存(归根结底,它只是 Map 中的一个条目),或者您可能想要替换应用程序。两者都不是您通常会轻松做的事情。
Purely for development you could use JRebel, which probably already has knowledge of Mojarra and most likely does the reflection trick mentioned above.
纯粹为了开发,您可以使用 JRebel,它可能已经了解 Mojarra,并且很可能会执行上面提到的反射技巧。
After some experimenting, I came to the following code which does the trick on JBoss AS 5/JSF 1.2. It does tie your code to Mojarra (imports sun packages) and can break with any upgrade because of reflective tricks being used. But anyway, this is the code:
经过一些试验,我找到了以下代码,它在 JBoss AS 5/JSF 1.2 上发挥了作用。它确实将您的代码绑定到 Mojarra(导入 sun 包),并且由于使用了反射技巧,可能会因任何升级而中断。但无论如何,这是代码:
public static void reloadBundle() {
ResourceBundle.clearCache(Thread.currentThread().getContextClassLoader());
ApplicationResourceBundle appBundle = ApplicationAssociate.getCurrentInstance().getResourceBundles().get("your_bundle_name");
Map<Locale, ResourceBundle> resources = getFieldValue(appBundle, "resources");
resources.clear();
}
@SuppressWarnings("unchecked")
private static <T> T getFieldValue(Object object, String fieldName) {
try {
Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return (T) field.get(object);
} catch (Exception e) {
return null;
}
}
(replace the getFieldValue helper method with your own favorite reflective util if necessary and sprinkle with exception and null handlers where appropriate)
(如有必要,将 getFieldValue 辅助方法替换为您自己喜欢的反射实用程序,并在适当的情况下撒上异常和空处理程序)
回答by menotyou
You can even avoid to have to import weld and jsf-impl classes in your module with some more lines of reflection:
你甚至可以避免在你的模块中使用更多的反射线导入weld和jsf-impl类:
Class<?> applicationAssociateClass = Class.forName("com.sun.faces.application.ApplicationAssociate");
Method getCurrentInstance = applicationAssociateClass.getMethod("getCurrentInstance");
Object applicationAssociate = getCurrentInstance.invoke(null);
Method getResourceBundles = applicationAssociate.getClass().getMethod("getResourceBundles");
Map<String, ?> resourceBundles = (Map<String, ?>)getResourceBundles.invoke(applicationAssociate);
Object appBundle = resourceBundles.get(name);
Map<Locale, ResourceBundle> resources = getFieldValue(appBundle, "resources");
resources.clear();
(works well with Wildfly 10)
(适用于 Wildfly 10)