2012-03-22 120 views
4

这是一个使用Guice在Tomcat上运行的webapp。根据文档,我们应该能够调用ResourceBundle.clearCache();来清除ResourceBundle缓存,并可能从捆绑软件属性文件中获取最新版本。如何清除ResourceBundle缓存

我们也试过如下:

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. 更改属性文件包含'你好世界”到“再见地球
  3. 清除使用servlet
  4. 点击的页面,希望看到缓存”再见地球

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

+0

你发现了这个解决方案的任何? – prongs 2012-06-13 05:52:59

+0

ResourceBundle.clearCache()在Java 1.6中添加。我正在研究Java 1.4服务器,这就是clearCache()未按预期工作的原因。 – Devrim 2014-11-03 12:16:04

回答

4

我不相信你可以重新加载已经创建的ResourceBundle实例,因为它的内部控制类已经被创建。你可以试试这个为初始化你包的替代:

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

尽管这种解决方案是关闭缓存,但我仍尝试过,但仍然无效。我的感觉是Tomcat缓存属性文件?讨厌...... – 2012-03-22 10:47:52

+0

这很可能是这种情况。让我想想另一种解决方法。 – Perception 2012-03-22 10:59:47

+0

@Perception:你有没有找到解决方案? – prongs 2012-06-13 05:56:34

1

我发现这个解决方案(使用Tomcat作品):

  • 使用自定义的ResourceBundle.Control(因为我需要UTF8)
  • 添加getTimeToLive为 “感知” 的描述
  • 力的重装标志
  • 的 “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; 
    } 
} 
+0

我喜欢这种方法。我已经将一个ConcurrentHashMap资源缓存与一个文件观察器捆绑在一起,在文件更改时删除一个包。卵石模板引擎实现它自己的副本,所以我不得不重写它。 – 2017-07-18 01:50:02

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

这为我工作:

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

注:

  1. 012在Java 1.6中添加了
  2. 不要使用静态resourceBundle属性,使用 ResourceBundle.getBundle()方法调用clearCache() 方法。
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); 
} 
+0

如果可能,或者只是使用spring的ReloadableResourceBundleMessageSource。 – gabor 2016-11-01 22:55:01