Spring-webmvc

HTTP缓存

2019-07-12  本文已影响0人  xzz4632

1. 与HTTP缓存有关的header字段

1.1 Cache-Control

缓存控制
注:Cache-Control属于HTTP 1.1规范, 因此只对实现了HTTP 1.1规范的浏览器有效.

1.2 Expires

过期时间, 即指定具体的过期时间点, 这要求浏览器与服务器时间同步.
注:Expires属于HTTP 1.0规范, 如果同时存在Cache-Control, Cache-Control有较高的优先级.

1.3 Last-Modified

最后修改时间

1.4 Etag

服务器生成的验证标签.

2. Spring HTTP缓存配置

2.1 CacheControl

支持与Cache-Control有关的设置. 可以在以下对象的参数:

ResponseEntity.ok().cacheControl(cacheControl).body("");

注:ResponseEntity.ok()生成的BodyBuilder对象还可以添加其他header信息.

// Java配置
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @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>

注意:如果在响应头中只设置了Cache-Control, 而没有设置其他有关项, 测试时先请求一次, 然后打开一个新的窗口输入相同的URL, 此时其Status Code显示为`200 (from disk cache).

2.2 Expires

获取时间

ZonedDateTime expiresDate = ZonedDateTime.now().with(LocalTime.MAX);
String expires = expiresDate.format(DateTimeFormatter.RFC_1123_DATE_TIME);
2.3 Last-Modified

这是一个验证器, 当在响应头中添加了Last-Modified, 在下次请求这个URL时其请求头就会有If-Modified-Since字段, 在后台可用WebRequest对象对其进行验证.

// 注WebRequest可以直接注入到@RequestMapping方法中
if (webRequest.checkNotModified(expiresDate.toEpochSecond()*1000)) {
    return null;
}

这个有一定的限制, 它只能跟踪文档的修改时间, 不能对内容进行跟踪.

2.4 Etag

HTTP1.1 新增规范, 这也是一个验证器, 当响应返回Etag后, 再次请求时会携带If-None-Match字段, 其值为上次响应所返回的Etag字段值. 可以在服务器端通过WebRequest对象的checkNotModified(String etag)进行验证.

注:WebRequest的checkNotModified有三个重载方法:

// 验证last-modified
boolean checkNotModified(long lastModifiedTimestamp)
// 验证etag
boolean checkNotModified(String etag)
// 二者同时验证
boolean checkNotModified(@Nullable String etag, long lastModifiedTimestamp);

3. Etag过滤器

spring提供了一个Etag过滤器ShallowEtagHeaderFilter, 可以根据响应内容生成Etag值并添加到响应中. 从而节省带宽,但这并不节省CPU时间。




  1. 什么是HTTP缓存, 为什么要使用它?
    http缓存位于服务器与浏览器之间, 用来监视请求, 并保存这个请求的响应副本(如html页面, 图片, 文件等), 然后当有一个与之完全相同的请求时, 这个请求可以使用之前保存的响应副本而不用从服务器下载相同的响应内容.
    使用它的目的有两个: 一个是减少延迟, 另一个是减少网络流量.

  2. web缓存的种类?
    2.1 浏览器缓存
    缓存存储在电脑的硬盘上, 这对于点击后退按钮或查看已查看过的网页非常有用, 这会直接从缓存中获取. 另外, 如果在网站中用了同样的导航图片, 这些图片都将会从缓存中提供.
    2.2 代理缓存
    代理缓存的工作原理与浏览器缓存大致相同,但规模要大得多。由于代理缓存不是浏览器或服务器的一部分,而是在网络上,所以请求必须以某种方式路由到它们。一种方法是使用浏览器的代理设置手动告诉它使用什么代理; 另一个是使用拦截, 由底层网络将web请求重定向到代理,因此不需要为它们配置客户机。
    代理缓存是一种共享缓存;它们通常拥有大量用户,而不是只有一个人在使用它们。

  3. WEB缓存是怎样工作的?
    3.1 缓存规则

    • 如果响应的头信息表示不要缓存响应内容,缓存就不会保存它。
    • 如果请求是经过身份验证或是安全的(如HTTPS),它的响应内容将不会被共享缓存保存。
    • 缓存内容在如下条件下会被认为是有效的: 一是如果在响应头信息中设置了过期时间或有效期, 在有效期内它是有效的. 二是如果发起了请求, 但是这个请求的内容并没有被更改, 此时缓存内容也是有效的.
    • 如果缓存过期,则会要求服务器验证它,并告诉缓存它所缓存的内容是否仍然有效。
    • 在某些情况下(例如,当它与网络断开连接时),缓存也可以提供过期的缓存内容。

如果响应中既没有验证器(ETag或Last-Modified头),也没有有效期信息,那么响应将不会被缓存.
总之,有效期和验证是缓存处理内容的最重要方式。

  1. 怎样控制缓存?
    通过HTTP headers

4.1 Pragma: no-cache
该设置只对少部分有效.

4.2 Expries
都支持. 它指定了缓存的过期时间点. 超过了这个时间点, 会请求服务器并确认先前的缓存内容是否被更改.
这个过期时间通常被设置为一个基于客户端最后一次访问时间的时间,或者是服务器上文档的最后更改时间。

Expires头特别适合缓存静态资源(如导航栏和按钮, 图片等)。因为它们变化不大,所以你可以对它们设置非常长的过期时间。这对定期更改的页面也很有用。例如,如果你每天早上6点更新一个新闻页面,你可以将页面设置为此时过期,这样缓存就知道什么时候可以获得一个新的副本,而无需用户点击“reload”。
Expires头中的值是一个HTTP日期;请记住这个HTTP日期是格林尼治标准时间(GMT),而不是本地时间。
Expires: Fri, 30 Oct 1998 14:19:41 GMT

尽管Expires头很有用,但它有一些限制。首先,Web服务器上的时钟和客户端缓存必须同步;如果他们的时间不同,缓存可能错误地认为旧的内容是新的。Expires的另一个问题是,很容易忘记设置了一些内容在特定时间过期, 如果在过期之前不更新过期时间,那么过期后每个请求都会请求Web服务器,从而增加负载和延迟。

如果使用Expires头,确保Web服务器的时钟是准确的非常重要。一种方法是使用网络时间(NTP);

4.3 Cache-Control
HTTP 1.1引入了一个新的报头,Cache-Control,以使Web发布者对其内容有更多的控制,并解决Expires的限制。
用法如下:

示例:
Cache-Control: max-age=3600, must-revalidate

当同时存在Cache-Control和Expires时,Cache-Control优先.

4.4 验证
当缓存内容发生更改时,服务器和缓存使用验证进行通信。通过验证,缓存器可以避免在本地已经有一个相同的副本时下载整个与之相同的内容.

验证器非常重要;如果不存在,并且没有任何可用的有效期信息(Expires或Cache-Control),将不会缓存任何内容。

最常见的验证器是文档最后更改的时间,即last - modified。当缓存存储了包含last - modified头部的响应时,它可以使用if - modified - since请求来询问服务器该内容自上次被获取以来是否发生了更改。

HTTP 1.1引入了名为ETag的新验证器。ETags是由服务器生成的唯一标识符,每次更新内容时都会更改。因为服务器控制如何生成ETag,所以缓存可以确保当ETag发出if - none - match请求时,如果匹配,那么缓存内容与实际内容是相同的。

几乎所有缓存都使用Last-Modified时间作为验证器;ETag验证也变得越来越普遍。

大多数现代Web服务器都将生成ETag和Last-Modified头,以自动用作静态内容(文件)的验证器;而你什么都不用做。但是,他们对动态内容(如CGI、ASP或数据库站点)了解得不够,无法生成动态内容.

关于web缓存的用法:

常见问答:

https://www.mnot.net/cache_docs/#REF

上一篇 下一篇

猜你喜欢

热点阅读