2012-03-22 4 views
4

Это webapp работает на Tomcat, используя Guice. В соответствии с документами мы можем позвонить 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. Включать кот и ударили страницу и говорят 'Hello World'
  2. Изменить файл свойств, содержащий «Hello Мир»до„Прощайте Земли“
  3. Очистить кэш с помощью сервлета
  4. Хита страницы и ожидать, чтобы увидеть„Прощайте Землю“

Так вопрос, как ResourceBundle.clearCache() на самом деле работает? И есть ли общий кеш-файл, который нужно очистить?

+0

вы найдете какие-либо решения этого? – prongs

+0

ResourceBundle.clearCache() добавлен в Java 1.6. Я работал на сервере Java 1.4, и именно поэтому clearCache() работает не так, как ожидалось. – Devrim

ответ

4

Я не верю, что вы можете выполнить перезагрузку уже созданного экземпляра ResourceBundle, поскольку его внутренний класс управления уже создан. Вы можете попробовать это в качестве альтернативы для инициализации вашего сверток:

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

Несмотря на то, что это решение состоит в том, чтобы отключить кеширование вместе, я попробовал его, и он все еще не работал. Мое ощущение, что Tomcat кэширует файлы свойств? Раздражающий .... –

+0

Это может быть очень хорошо. Позвольте мне подумать об этом. – Perception

+0

@Perception: вы нашли решение? – prongs

1

Я нашел это решение (работает с котом):

  • использовать пользовательские 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; 
    } 
} 
+0

Мне нравится этот подход. Я объединился с кешем ConcurrentHashMap ресурсов, связанным с наблюдателем файлов, который удаляет пакет при смене файла. Шаблонный движок Pebble реализует свою собственную копию выше, поэтому мне пришлось переопределить ее. –

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. ResourceBundle.clearCache() добавлен в 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

Смежные вопросы