【问题标题】:Freemarker Templates Caching Shared Variable after refreshFreemarker 模板在刷新后缓存共享变量
【发布时间】:2012-11-27 12:20:58
【问题描述】:

我有一个 Spring MVC Web 应用程序,它使用 FreeMarker 来呈现视图并提出了以下问题。

在我的 FreeMarker 配置中,我将 Singleton Spring bean 声明为 FreeMarker 变量,并且在我的应用程序中,我为 Singleton Bean 提供了动态刷新的机制(该 bean 包含从 DB 检索到的应用程序配置)。

现在的问题是,当刷新之前渲染的 FreeMarker 模板使用旧版本中的值时,如果我导航到自容器启动后未渲染的页面,它会使用新值。

以下是我的 FreeMarker 配置的 sn-p:

<!-- FreeMarker config -->

<bean id="freemarkerViewConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
    <property name="templateLoaderPaths">
        <array>
            <value>/WEB-INF/freemarker</value>
            <value>classpath:/WEB-INF/freemarker</value>
        </array>
    </property>
    <property name="freemarkerSettings">
        <props>
            <prop key="datetime_format">dd/MM/yyyy</prop>
            <prop key="number_format">#</prop>
            <prop key="whitespace_stripping">true</prop>
            <prop key="auto_import">
                spring.ftl as spring,
                custom-macros.ftl as custom,
            </prop>
        </props>
    </property>
    <property name="freemarkerVariables">
        <map>
            <entry key="xml_escape" value-ref="fmXmlEscape"/>
            <entry key="html_escape" value-ref="fmHtmlEscape"/>
            <entry key="config" value-ref="config"/>
        </map>
    </property>
</bean>

要刷新配置模型,我在 Controller 类中执行以下操作:

((XmlWebApplicationContext)applicationContext).refresh();

当访问尚未呈现但无法识别已访问页面上的更改的页面时,具有此配置会选择刷新的配置模型。

我尝试了以下方法来强制执行变量的“刷新”,但没有成功:

  1. 在刷新上下文后的控制器中,我清除了 FreeMarker 配置中的 templateCache,该模板缓存已自动装配:

    freeMarkerConfig.getConfiguration().clearTemplateCache();

  2. 我还尝试使用 freeMarkerSettings 中的以下属性禁用 FreeMarker 配置中的模板缓存:

    freemarker.cache.NullCacheStorage

最后,值得指出的是,在调试和查看缓存和配置时,共享变量确实引用了最新的配置模型,但页面使用旧版本呈现。

关于如何解决这个问题的任何建议/指导?

ps 我正在使用 Spring v3.1.1.RELEASE 和 FreeMarker v2.3.19

【问题讨论】:

    标签: java spring templates caching freemarker


    【解决方案1】:

    不是一个很好的解决方案,但我已经解决了我的问题,但老实说,这更像是一个 hack。

    我使用以下命令更改了代码以刷新我的配置,因此只重新创建了配置 bean:

    ((DefaultListableBeanFactory) beanFactory).destroySingleton("config");
    

    然后通过删除对配置模型的引用来修改 freemarker 配置,因为无论我尝试了什么,我都无法刷新它。因此,我的问题的解决方案是修改 BaseController,应用程序中的每个控制器都扩展了 BaseController,将可用的配置模型作为 @ModelAttribute 公开,以便所有视图都可以使用它。

    正如我所说并没有真正解决根本问题,但我已经解决了我的问题,尽管是以一种非正统的方式。

    【讨论】:

      猜你喜欢
      • 2010-09-19
      • 2012-05-08
      • 2018-06-06
      • 1970-01-01
      • 1970-01-01
      • 2019-07-13
      • 1970-01-01
      • 2011-09-03
      • 1970-01-01
      相关资源
      最近更新 更多