Spring4.x官方参考文档中文版——第21章 Web MVC框架(29)

21.14.2 支持静态资源的HTTP缓存

    静态资源需要对’Cache-Control’和一些可选报头进行配置,以发挥其最佳性能。配置一个ResourceHttpRequestHandler来处理静态资源,不仅可以在本地就通过读取某个文件的metadata来写入’Last-Modified’报头,而且可以在属性被配置的情况下写入’Cache-Control’报头。

    你可以在一个ResourceHttpRequestHandler中设置cachePeriod属性,或者使用一个CacheControl的实例,它可以支持更多特定的指令:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**")
                .addResourceLocations("/public-resources/")
                .setCacheControl(CacheControl.maxAge(1, TimeUnit.HOURS).cachePublic());
    }
}

或者在XML中这样配置:

<mvc:resources mapping="/resources/**" location="/public-resources/">
	<mvc:cache-control max-age="3600" cache-public="true"/>
</mvc:resources>

21.14.3 在Controller中支持Cache-Control,Etag和Last-Modified响应报头

        Controller控制器可支持’Cache-Control’,’ETag’与/或’If-Modified-Since’的HTTP请求。在响应里设置’Cache-Control’报头是强烈推荐的。这涉及到为指定的请求计算lastModified参数的long型值,和/或一个Etag的值,然后与请求中的’If-Modified-Since’报头值进行对比,并有可能返回一个状态代码为304(未被修改)的响应。

        参考”Using HttpEntity”这一章节,Controller控制器可以使用HttpEntity类型来与请求/响应进行交互。Controller返回的ResponseEntity对象可以被包含到响应中的HTTP缓存中,如下所示:

@RequestMapping("/book/{id}")
publicResponseEntity<Book> showBook(@PathVariable Long id) {
 
   Book book = findBook(id);
   String version = book.getVersion();
 
    return ResponseEntity
                .ok()
               .cacheControl(CacheControl.maxAge(30,TimeUnit.DAYS))
                .eTag(version) // 也可以设置lastModified
                .body(book);
}

        上面的做法中,不仅可在响应里包含’ETag’和’Cache-Control’报头,而且如果在客户端发送的有条件的报头里,匹配到了Controller中设置的缓存信息时,会把响应转换成HTTP 304 Not Modified的空body响应。

        @RequestMapping的方法同样也支持类似操作,如下所示:

@RequestMapping
public StringmyHandleMethod(WebRequest webRequest, Model model) {
 
    long lastModified = // 1. 特定应用计算出来的值
 
    if(request.checkNotModified(lastModified)) {
       // 2. 退出的捷径 –不需要做更多处理
       return null;
   }
 
// 3.或者需要对请求做更多处理,比如准备响应内容等。
   model.addAttribute(...);
    return "myViewName";
}

       上面的例子有两个重点:调用request.checkNotModified(lastModified)和返回null。在这个方法返回true前,会先把响应设置为304状态。之后,基于此方法就会导致Spring MVC不对此请求做更多的处理。

这个方法里面有3个入参值请注意:

  • request.checkNotModified(lastModified)会用lastModifed与请求中的’If-Modified-Since’报头值进行比较
  • request.checkNotModified(eTag)会与请求中的’ETag’报头值进行比较
  • request.checkNotModified(eTag,lastModified)以上两个行为都会做,意味着两个条件都得满足,否则会返回HTTP 304 Not Modified的响应。

21.14.4 Shallow Etag的支持

        Etag是通过Servlet的过滤器ShallowEtagHeaderFilter来支持的。它是一个普通的Servlet过滤器,因此,他可以结合任何web框架来使用。ShallowEtagHeaderFilter过滤器正如其名,会创建一个shallow Etag(相对于deep ETag,有更深含义)。这个过滤器缓存渲染好的JSP的内容(或其他内容),并在其上生成一个MD5哈希值,并把它作为Etag报头,在响应中进行返回。当下次客户端请求同样的资源时,会使用这个哈希值作为If-None-Match的值。过滤器会检测到这个值,再次渲染此视图,并比较这两个哈希值,如果相同,会返回304。这个过滤器不会偷懒,还是会重新渲染视图,只是会省下一些带宽,渲染好的响应不会回传给客户端。

         请注意,这种策略会节省网络带宽而不是CPU,每个请求的整个响应还是会被处理出来。在controller级别的其他策略(如上所述)就能既节省网络带宽,又避免了再次处理。可以在mvc-config-static-resources中配置。

        在web.xml中配置ShallowEtagHeaderFilter:

<filter>
    <filter-name>etagFilter</filter-name>
    <filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class>
</filter>
 
<filter-mapping>
    <filter-name>etagFilter</filter-name>
    <servlet-name>petclinic</servlet-name>
</filter-mapping>

    或者在Servlet3.0+环境下:

public classMyWebAppInitializer extendsAbstractDispatcherServletInitializer {
 
    // ...
 
    @Override
    protected Filter[]getServletFilters() {
       return new Filter[] { newShallowEtagHeaderFilter() };
   }
 
}

详见”21.15 基于代码的Servlet容器初始化”。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值