【问题标题】:How to set Cache-control: private with applicationContext.xml in Spring 4.2 or later如何在 Spring 4.2 或更高版本中使用 applicationContext.xml 设置 Cache-control: private
【发布时间】:2017-09-11 15:30:59
【问题描述】:

如何在 Spring 4.2 或更高版本中使用 applicationContext.xml 设置 Cache-control: private?

背景:

Cache-control: HTTP 标头可以从 Spring 4.1 中的 applicationContext.xml 设置,如下所示:

<mvc:interceptors>
  <bean id="webContentInterceptor"
        class="org.springframework.web.servlet.mvc.WebContentInterceptor">
    <property name="cacheSeconds" value="0"/>
    <property name="useExpiresHeader" value="true"/>
    <property name="useCacheControlHeader" value="true"/>
    <property name="useCacheControlNoStore" value="true"/>
  </bean>
</mvc:interceptors>

有一些基于注释的实现,例如 https://github.com/foo4u/spring-mvc-cache-control ,但我更喜欢基于 XML 的配置,因为我必须根据测试/生产环境更改 HTTP 标头(例如,如果页面返回,Chrome 会发送另一个“查看页面源”请求与Cache-Control: private, no-store, no-cache, must-revalidate,并使反CSRF令牌不匹配)。

问题:

这些设置自 Spring 4.2 起已弃用。 此外,无法从这些设置中设置Cache-control: private。因为当且仅当 http 标头包含 Cache-Control: private 时,某些 CDN 提供程序才不会存储内容,因此对此 HTTP 标头的支持对于使用 CDN 的系统至关重要。例如http://tech.mercari.com/entry/2017/06/22/204500https://community.fastly.com/t/fastly-ttl/882

所以为了安全起见,我正在寻找设置 Cache-Control: private HTTP header from applicationContext.xml 的方法。

【问题讨论】:

    标签: java xml spring spring-mvc caching


    【解决方案1】:

    Spring 4.2+ 中似乎没有开箱即用的 XML 支持。如您所见herecacheControlMappingsWebContentInterceptor 没有set 方法,因此没有机会将XML 配置中的值写入其中;此映射旨在存储 url-cache-control 映射。但是,CacheControl 类有公共的cachePrivate 方法,可以用于注册自定义配置(我认为这可以针对 dev 或 prod 配置文件完成);例如:

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        CacheControl cacheControl = CacheControl.empty().cachePrivate();
        registry.addResourceHandler("/**")
                    .setCacheControl(cacheControl);
    }
    

    或直接在您的控制器中(也可能取决于活动配置文件):

    @RequestMapping(value = "/test")
    public ResponseEntity<?> doHandleRequest () {
        CacheControl cacheControl = CacheControl.empty().cachePrivate();
        return ResponseEntity.ok()
                             .cacheControl(cacheControl);
    }
    

    如果您确实需要使用 XML 配置,没有人会阻止您使用适当的方法和逻辑编写 WebContentInterceptor 的自定义子类,幸运的是,WebContentInterceptoraddCacheMapping 方法。

    【讨论】:

    • 感谢您的建议。 CacheControl.cachePrivate() 似乎将 private 设置为 Cache-control: 标头。但我发现了另一个问题。我想在 Struts 中设置所有 no-cache、no-store 和 max-age=0,如 nocache="true"。另一方面,CacheControl.noCache()、noStore() 和 maxAge() 都是静态方法,不返回 this。所以我无法通过 CacheControl 设置所有这些标头...
    • 感谢您的信息。回顾一下: - Spring 4.2+ 中没有开箱即用的 XML Cache-Control: private 支持。 - 您可以使用setCacheControl 设置Cache-Control 标头。 - Spring 中的CacheControl 类有一些设计问题。
    【解决方案2】:

    如果你必须使用 XML 配置(就像我必须的那样),你可以按如下方式实现它 -

    首先调用为您创建 bean 的工厂方法,以 XML 格式创建 CacheControl bean。在您的情况下,您需要一个空的 CacheControl 开头 -

    <bean id="cacheControlFactory" class="org.springframework.http.CacheControl" factory-method="empty" />
    

    现在在org.springframework.beans.factory.config.MethodInvokingFactoryBean的帮助下调用CacheControl实例的cachePrivate方法-

    <bean id="myCacheControl" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject">
            <ref bean="cacheControlFactory"/>
        </property>
        <property name="targetMethod">
            <value>cachePrivate</value>
        </property>
    </bean>
    

    现在使用保存配置的最终bean,并调用webContentInterceptoraddCacheMapping 方法,您就完成了。此配置将应用于您作为 varargs 参数中的列表发送的 url -

    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject">
            <ref bean="webContentInterceptor"/>
        </property>
        <property name="targetMethod">
            <value>addCacheMapping</value>
            </property>
        <property name="arguments">
            <list>
                <ref bean="myCacheControl" />
                <list>
                    <value>/home</value>
                    <value>/dp/**</value>
                    <value>/**/b/*</value>
                </list>
            </list>
        </property>
    </bean>
    

    可以在这个 SO 线程中找到有效的 xml 配置 - How to set cacheControlMappings in WebContentInterceptor in Spring 5 Xml

    【讨论】:

      猜你喜欢
      • 2021-03-15
      • 2019-01-20
      • 2020-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-11
      • 1970-01-01
      相关资源
      最近更新 更多