How to clear ResourceBundle cache

人走茶凉 提交于 2019-12-07 10:30:02

问题


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.

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'

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


回答1:


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.



回答2:


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.getBundle("my.bundle", new ResourceBundle.Control() {
    @Override
    public long getTimeToLive(String arg0, Locale arg1) {
        return TTL_DONT_CACHE;
    }
});



回答3:


I have found this solution (works with 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

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



回答4:


maybe this post can solve your problem.




回答5:


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



回答6:


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


来源:https://stackoverflow.com/questions/9819999/how-to-clear-resourcebundle-cache

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!