1

ビューのレンダリングに FreeMarker を使用する Spring MVC Web アプリがあり、次の問題が発生しました。

FreeMarker 構成内で、Singleton Spring Bean を FreeMarker 変数として宣言し、アプリケーション内で、Singleton Bean を動的に更新するメカニズムを提供しました (Bean には、DB から取得したアプリケーション構成が含まれています)。

ここでの問題は、以前にレンダリングされた FreeMarker テンプレートが更新されたときに古いバージョン内の値を使用しているにもかかわらず、コンテナーが開始されてからレンダリングされていないページに移動すると、新しい値が使用されることです。

以下は、私の FreeMarker 構成のスニペットです。

<!-- 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 Config 内の templateCache をクリアします。

    freeMarkerConfig.getConfiguration().clearTemplateCache();

  2. また、freeMarkerSettings 内の次のプロパティを使用して、FreeMarker 構成内のテンプレートのキャッシュを無効にしようとしました。

    freemarker.cache.NullCacheStorage

最後に、デバッグ中にキャッシュと構成を調べたときに、共有変数が実際に最新の構成モデルを参照しているにもかかわらず、ページが古いバージョンを使用してレンダリングされることを指摘する価値があります。

これを解決する方法に関するアドバイス/ガイダンスはありますか?

ps Spring v3.1.1.RELEASE と FreeMarker v2.3.19 を使用しています

4

1 に答える 1

0

完全な解決策ではありませんが、問題は修正されましたが、正直に言うとハックです。

次のコマンドを使用して構成を更新するようにコードを変更したため、構成Beanのみが再作成されました。

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

次に、構成モデルへの参照を削除してfreemarker構成を変更しました。これは、何を試したかに関係なく、これを更新することができなかったためです。したがって、私の問題の解決策は、アプリケーション内のすべてのコントローラーが拡張するBaseControllerを変更して、@ ModelAttributeとして使用可能な構成モデルを公開し、すべてのビューで使用できるようにすることでした。

私が言ったように、根本的な問題を実際に解決するわけではありませんが、私は非正統的な方法ではありますが、私の問題を解決しました。

于 2012-12-13T14:05:41.600 に答える