如何在Web应用程序中重新加载资源包?

时间:2010-12-01 14:08:00

标签: java web-applications jsf jsf-2

我有资源包作为Java类从数据库中读取值。当我更新数据库我需要重新加载包,但我不知道如何。有人帮忙吗?

package model.helpers;
public class Messages_en extends ListResourceBundle {
      protected Object[][] getContents() {
            // from DB
            // ...
      }
}

在视图中我使用bundle如下:

<f:loadBundle basename="model.helpers.Messages" var="m" />

3 个答案:

答案 0 :(得分:10)

这并非完全无足轻重。

只需通过ResourceBundle清除clearCache()并不总能产生预期效果。通常,您至少还需要尝试清除使用上下文类加载器:

ResourceBundle.clearCache(Thread.currentThread().getContextClassLoader());

然而,这仍然不会重新加载faces-config.xml文件中定义的资源包。至少Mojarra JSF 1.2实现在内部私有地缓存资源包。这发生在:

FacesContext -> Application -> associate (ApplicationAssociate) -> resourceBundles (Map<String, ApplicationResourceBundle>()) -> resources (Map<Locale, ResourceBundle>) 

可以通过反射清除此缓存(在一天结束时,它只是地图中的条目),或者您可能想要替换应用程序。两者都不是你通常轻松愉快的事情。

纯粹为了开发,你可以使用JRebel,它可能已经了解了Mojarra,很可能是上面提到的反射技巧。

经过一些实验,我得到了以下代码,它可以解决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;
    }       
}

(如果需要,用你自己喜欢的反射工具替换getFieldValue辅助方法,并在适当的地方撒上异常和空处理程序)

答案 1 :(得分:5)

ResourceBundle.clearCache();     

OR

Messages_en .clearCache();

调用此方法将重新加载资源,它将刷新包

答案 2 :(得分:1)

您甚至可以避免必须在模块中导入焊接和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();

(适用于Wildfly 10)