Java 如何清除ResourceBundle缓存

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9819999/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 08:06:30  来源:igfitidea点击:

How to clear ResourceBundle cache

javatomcatguiceresourcebundle

提问by Ben George

This is a webapp running on Tomcat, using Guice. According to the docs we should be able to call ResourceBundle.clearCache();to clear the ResourceBundle cache and presumably get the latest from the bundle property files.

这是一个运行在 Tomcat 上的 web 应用程序,使用 Guice。根据文档,我们应该能够调用ResourceBundle.clearCache();以清除 ResourceBundle 缓存并大概从包属性文件中获取最新信息。

We have also tried the following:

我们还尝试了以下方法:

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!

and

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

The behavior that I am expecting is:

我期待的行为是:

  1. Start up tomcat and hit a page and it says 'Hello World'
  2. Change the properties file containing 'Hello World' to 'Goodbye Earth'
  3. Clear the cache using a servlet
  4. Hit the page and expect to see 'Goodbye Earth'
  1. 启动 tomcat 并点击一个页面,它显示“Hello World”
  2. 将包含“Hello World”的属性文件更改为“Goodbye Earth”
  3. 使用 servlet 清除缓存
  4. 点击页面并期待看到“再见地球”

So question is, how is ResourceBundle.clearCache() actually working ? And is there some generic file cache we need to clear also ?

所以问题是,ResourceBundle.clearCache() 实际上是如何工作的?还有一些我们需要清除的通用文件缓存吗?

回答by Perception

I do not believe you can effect the reloading of an already created ResourceBundle instance since its internal control class has already been created. You may try this as an alternative for initializing your bundle:

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

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

回答by prongs

maybe this postcan solve your problem.

也许这篇文章可以解决你的问题。

回答by izanat

I have found this solution (works with tomcat):

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

  • use a custom ResourceBundle.Control (because I need UTF8)
  • add the getTimeToLive as "Perception" description
  • force the reload flag
  • the "ResourceBundle.clearCache" doesn't work
  • 使用自定义 ResourceBundle.Control (因为我需要 UTF8)
  • 将 getTimeToLive 添加为“感知”描述
  • 强制重新加载标志
  • “ResourceBundle.clearCache”不起作用

How to call :

如何调用:

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

The custom class :

自定义类:

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;
    }
}

回答by sudhakar tokala

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);
        }

回答by Devrim

This worked for me:

这对我有用:

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

Notes:

笔记:

  1. ResourceBundle.clearCache()is added at Java 1.6
  2. Do not use a static resourceBundle property, use ResourceBundle.getBundle()method after invoking clearCache()method.
  1. ResourceBundle.clearCache()在 Java 1.6 中添加
  2. 不要使用静态资源包属性,ResourceBundle.getBundle()调用clearCache()方法后使用 方法。

回答by gabor

This works, iff you can intercept the very first creation of the resource bundle:

这是有效的,如果您可以拦截资源包的第一次创建:

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);
}