如何清除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’

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

这对我有用:

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

笔记:

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

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

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

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

我找到了这个解决方案(适用于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; } } 
 this is one more possibility to clear cache Class 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); } 

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

 while (true) { ResourceBundle resourceBundle = ResourceBundle.getBundle("SystemMessages", new Locale("hu", "HU"), new ResourceBundle.Control() { @Override public List 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); }