2012-03-22 190 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