如何清除ResourceBundle缓存

时间:2012-03-22 10:02:27

标签: java tomcat guice resourcebundle

这是使用Guice在Tomcat上运行的webapp。根据文档,我们应该能够调用ResourceBundle.clearCache();来清除ResourceBundle缓存,并且可能从bundle属性文件中获取最新信息。

我们还尝试了以下方法:

Class klass = ResourceBundle.getBundle("my.bundle").getClass().getSuperclass();
Field field = klass.getDeclaredField("cacheList");
field.setAccessible(true);
ConcurrentHashMap cache = (ConcurrentHashMap) field.get(null);
cache.clear(); // If i debug here I can see the cache is now empty!

ResourceBundle.clearCache(this.class.getClassLoader());

我期待的行为是:

  1. 启动tomcat并点击页面,然后显示“Hello World”
  2. 将包含“Hello World”的属性文件更改为“Goodbye Earth”
  3. 使用servlet清除缓存
  4. 点击页面,期待看到'Goodbye Earth'
  5. 所以问题是,ResourceBundle.clearCache()实际上是如何工作的?还有一些我们需要清除的通用文件缓存吗?

6 个答案:

答案 0 :(得分:6)

这对我有用:

ResourceBundle.clearCache();
ResourceBundle resourceBundle= ResourceBundle.getBundle("YourBundlePropertiesFile");
String value = resourceBundle.getString("your_resource_bundle_key");

备注:

    在Java 1.6 中添加了
  1. ResourceBundle.clearCache()
  2. 不要使用静态resourceBundle属性,请使用 调用ResourceBundle.getBundle()后的clearCache()方法 方法

答案 1 :(得分:4)

我不相信你可以影响已经创建的ResourceBundle实例的重新加载,因为它已经创建了它的内部控件类。您可以尝试将此作为初始化捆绑包的替代方法:

ResourceBundle.getBundle("my.bundle", new ResourceBundle.Control() {
    @Override
    public long getTimeToLive(String arg0, Locale arg1) {
        return TTL_DONT_CACHE;
    }
});

答案 2 :(得分:1)

我找到了这个解决方案(适用于tomcat):

  • 使用自定义ResourceBundle.Control(因为我需要UTF8)
  • 将getTimeToLive添加为“Perception”描述
  • 强制重装标志
  • “ResourceBundle.clearCache”不起作用

如何致电:

ResourceBundle bundle = ResourceBundle.getBundle("yourfile", new UTF8Control());

自定义类:

public class UTF8Control extends Control
{
    public ResourceBundle newBundle(
        String baseName,
        Locale locale,
        String format,
        ClassLoader loader,
        boolean reload)
    throws IllegalAccessException, InstantiationException, IOException
    {
        // The below is a copy of the default implementation.
        String bundleName = toBundleName(baseName, locale);
        String resourceName = toResourceName(bundleName, "properties");
        ResourceBundle bundle = null;
        InputStream stream = null;

        // FORCE RELOAD because needsReload doesn't work and reload is always false
        reload = true;

        if (reload) {
            URL url = loader.getResource(resourceName);
            if (url != null) {
                URLConnection connection = url.openConnection();
                if (connection != null) {
                    connection.setUseCaches(false);
                    stream = connection.getInputStream();
                }
            }
        }
        else {
            stream = loader.getResourceAsStream(resourceName);
        }

        if (stream != null) {
            try {
                // Only this line is changed to make it to read properties files as UTF-8.
                bundle = new PropertyResourceBundle(new InputStreamReader(stream, "UTF-8"));
            }
            finally {
                stream.close();
            }
        }
        return bundle;
    }

    // ASK NOT TO CACHE
    public long getTimeToLive(String arg0, Locale arg1) {
        return TTL_DONT_CACHE;
    }
}

答案 3 :(得分:0)

也许this post可以解决您的问题。

答案 4 :(得分:0)

this is one more possibility to clear cache 
Class<ResourceBundle> type = ResourceBundle.class;
        try {
            Field cacheList = type.getDeclaredField("cacheList");
            cacheList.setAccessible(true);

            ((Map<?, ?>) cacheList.get(ResourceBundle.class)).clear();
        }
        catch (Exception e) {

           system.out.print("Failed to clear ResourceBundle cache" + e);
        }

答案 5 :(得分:0)

如果您可以拦截资源包的第一次创建,则此方法有效:

while (true) {
    ResourceBundle resourceBundle = ResourceBundle.getBundle("SystemMessages", new Locale("hu", "HU"),
            new ResourceBundle.Control() {
                @Override
                public List<String> getFormats(String baseName) {
                    return ResourceBundle.Control.FORMAT_PROPERTIES;
                }

                @Override
                public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException {
                    System.err.println(this.toBundleName(baseName, locale) + ": " + format + " - " + reload);
                    return super.newBundle(baseName, locale, format, loader, reload);
                }

                @Override
                public long getTimeToLive(String baseName, Locale locale) {
                    long ttl = 1000;
                    System.err.println(this.toBundleName(baseName, locale) + " - " + ttl + "ms");
                    return ttl;
                }

                @Override
                public boolean needsReload(String baseName, Locale locale, String format, ClassLoader loader, ResourceBundle bundle, long loadTime) {
                    System.err.println(baseName + "_" + locale + " - " + new Date(loadTime));
                    return true;
                }
            });
    System.out.println(resourceBundle.getString("display.first_name") + ": John");
    System.out.println(resourceBundle.getString("display.last_name") + ": Doe");
    Thread.sleep(5000);
}