[iOS] iOS中URLRequest的缓存策略

在这里插入图片描述

Example 项目地址: https://github.com/zColdWater/URLRequestCacheExample 下载Demo,结合Demo一起实践更容易理解。

一,准备工作

在开始之前,我们需要清楚下面的一些问题,才方便我们后面的讲解。

1. URLRequest 涉及的范围

我们一提到URLRequest,我相信很多国内的开发者,首先就会联想到,HTTP请求,然后木有别的了。 但是其实 URLRequest是一个很大的概念,它不只服务于HTTP协议,它还服务于 其他应用协议,比如File协议,Data协议,自定义协议等等。 要么苹果公司为什么不叫它HTTPURLRequest呢? 问题就在于我们平时最常接触的就是HTTP协议,用来请求服务端的数据用来展示。

2. URLRequest.CachePolicy 涉及的范围

通过上面的文章我们清楚了 URLRequest 服务很多协议,那么URLRequest.CachePolicy的范围是什么呢,很明显,和URLRequest一样,这个缓存策略也包含上面这些协议,当然 我也不清楚其他协议的缓存策略是什么样子的,比如File协议,或则别的。 但是我很清楚,我们常用的HTTP协议的缓存协议,这个后面再讲,这里清楚的是,这个缓存策略支持很多协议,我们的HTTP协议有着自己的缓存策略。

3. HTTP协议的缓存策略

我之前转了一篇台湾作者关于HTTP协议的缓存策略的文章,文章地址是: http://47.99.237.180:8080/articles/2019/11/18/1574050998351.html
那么HTTP协议的缓存策略是什么呢?

Note: 首先我们需要清楚的是,HTTP协议的策略是需要客户端服务端配合完成的。也就是如果这个策略想要完成,需要双方都有动作,并且客户端需要完全配合才行。

我用最直白的话来概述这个原理:

  • 首先客户端第一次访问服务器某一个资源,并且服务器客户端协商好,我们都用标准的HTTP缓存协议。

  • 因为是第一次,客户端通过URL来查找,发现本地没有缓存,直接向服务器发起一个HTTP协议的网络请求。 客户端的请求头,例如:

    GET /EC6/poster-share-invite.png HTTP/1.1
    Host: fep-sit.nioint.com:5418
    Accept: */*
    User-Agent: SessionDownload/1 CFNetwork/1107.1 Darwin/19.0.0
    Accept-Language: en-us
    Accept-Encoding: gzip, deflate
    Connection: keep-alive
    

    这其实就是一个普通的网络请求,请求头也是客户端默认的,没有特殊设置。

  • 服务器接到了某一个客户端的发来的请求,然后做的直接就看一下这个请求头有没有提供HTTP协议缓存的相关字段,然后根据HTTP协议缓存规则,来判断是否返回状态码304让客户端用缓存,还是返回状态码200,让客户端使用服务器返回的新资源,服务器检查请求头的相关字段如下

    • If-None-Match: W/“20f9a-16f5c76370d” 这个字段你可以理解为这个资源的唯一Hash值,有点像MD5或者SHA1等,反正就是一个唯一标识啦,资源如果有变动,它一定就会有变动,并且这个值是从上一次服务器返回的响应头里面的Etag字段取来的。因为我们客户端是第一次请求,所以没有从之前的服务器响应里面拿到这个值,所以请求头就没有这个字段。
    • If-Modified-Since:Tue, 31 Dec 2019 14:57:28 GMT,这个字段表示的是最后一次资源更改的时间,同If-None-Match也是从上一次的服务器响应头中拿到,从Last-Modified字段取的。因为第一次请求,所以没有获取到上一次响应头的字段,也就没有带上。
  • 服务器开始根据HTTP协议规则进行检查,来决定是让客户端使用缓存还是使用服务器下发的资源。

    • 服务器的两种响应头:
      1. 状态码200(告诉客户端,不要使用缓存,用我给你的新资源)
         HTTP/1.1 200 OK  
         X-Powered-By: Express  
         Accept-Ranges: bytes  
         Cache-Control: public, max-age=0  
         Last-Modified: Tue, 31 Dec 2019 14:57:28 GMT  
         ETag: W/"20f9a-16f5c76370d"  
         Content-Type: image/gif  
         Content-Length: 135066  
         Date: Wed, 01 Jan 2020 01:56:35 GMT  
         Proxy-Connection: keep-alive
        
      2. 状态码304(告诉客户端你用自己的缓存即可)

        这里注意的是,在iOS当中,你不需要亲自处理304的情况,如果你使用了默认的缓存策略,也就是使用HTTP协议本身的缓存策略,系统的网络框架比如URLSession或者URLConnection会自动的将这个304处理成200,这样方便了开发者逻辑处理,开发者只需要知道 资源获取成功,就可以了。

        HTTP/1.1 304 Not Modified
        X-Powered-By: Express
        Accept-Ranges: bytes
        Cache-Control: public, max-age=0
        Last-Modified: Tue, 31 Dec 2019 14:57:28 GMT
        ETag: W/"20f9a-16f5c76370d"
        Date: Wed, 01 Jan 2020 01:59:25 GMT
        Proxy-Connection: keep-alive
        
    • 服务器响应头里与HTTP协议缓存策略相关的字段:
      1. Cache-Control: max-age = X (max-age=x 是告诉客户端x秒之内不要再发起请求了,就用你的缓存就OK了,换句话说,如果服务器告诉客户端max-age=100,客户端在100s之内再去请求,是不会发起真正的网络请求的,客户端的网络层框架会自动返回状态码200,上一次的缓存数据)
      2. Last-Modified: Tue, 31 Dec 2019 14:57:28 GMT(这个字段是告诉客户端,这个资源最后一次更新的时间,让客户端保存好,下一次请求的时候,在请求头里面带上这个值,请求头的那个字段就是If-Modified-Since,这里的规则是这样的,如果请求头里的If-Modified-Since时间点早于服务器的Last-Modified时间点,服务器会返回200,让客户端需要更新最新资源,如果反过来,或者相同,服务器会下发304,让客户端使用缓存。)
      3. ETag: W/“20f9a-16f5c76370d”(这个字段告诉客户端,这个值是这个资源的唯一id,如果服务器上面有新资源,我们会更新这个值,客户端要保存好,下次请求的时候带上,下次请求头里面这个If-None-Match字段就是保存的上次响应头里面的Etag字段。它的规则是,如果客户端请求头中的If-None-Match值不与服务器里面的Etag一致,就返回200,让客户端使用新资源,只有当相等的情况,会返回304,让客户端使用缓存。)
  • 服务器检查完请求头发现这个客户端没有带上资源缓存信息,那么服务器就认为客户端不想使用HTTP协议缓存策略,返回200,把资源也一同返回。

    HTTP/1.1 200 OK
    X-Powered-By: Express
    Accept-Ranges: bytes
    Cache-Control: public, max-age=0
    Last-Modified: Tue, 31 Dec 2019 14:57:28 GMT
    ETag: W/"20f9a-16f5c76370d"
    Content-Type: image/gif
    Content-Length: 135066
    Date: Wed, 01 Jan 2020 01:56:35 GMT
    Proxy-Connection: keep-alive
    
  • 客户端第一次拿到资源后,先将服务器告诉自己的缓存信息,保存起来,Cache-Control: public, max-age=0 读取一下max-age,发现值等于0,这是告诉我应该每次都发真正的请求,然后再存一下Last-Modified上次更新的时间,再存一下ETag,这个告诉我们资源的唯一id。

  • <
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值