HTTP 网络技术学习:缓存;为什么有时候出现问题要清除浏览器缓存?客户端缓存和服务端缓存是什么。

目录:

  1. 问题的背景
  2. Http的缓存是什么
  3. 客户端设置缓存,需要服务端允许?
  4. 缓存分类:为什么会有客户端缓存和服务器端缓存?
  5. 客户端缓存的参数设置,举例代码实现缓存

一、问题的背景

有时候网站出现问题,或者数据没有改变,通常客服或者售后会让我们刷新一下网页,或者关掉浏览器,或者清掉缓存再试试,然后就可以了,这是为什么呢?

今天我们就来看看http缓存是怎么样的。


二、Http的缓存是什么

HTTP缓存的主要目的是为了提高网页的加载速度和减少服务器的负载。当用户首次访问一个网页时,浏览器会下载网页上的所有资源(如HTML、CSS、JavaScript、图像等)。如果这些资源被缓存在本地,那么当用户再次访问该网页时,浏览器就可以直接从缓存中加载这些资源,而无需再次从服务器下载。这样可以显著减少加载时间,提高用户体验。


三、客户端设置缓存,需要服务端允许?

服务端是否设置这些头部字段并不影响客户端本身具有缓存功能的能力。即使服务端没有设置任何缓存相关的头部字段,客户端仍然可以缓存资源(尽管这种缓存可能是基于默认策略或客户端自定义策略的)。但是,为了确保客户端能够按照预期的缓存策略进行缓存,并避免潜在的缓存一致性问题,建议服务端明确设置这些头部字段。


四、缓存分类:为什么会有客户端缓存和服务器端缓存?

4.1 服务器端缓存

服务器端缓存是指将经常访问的数据或资源存储在服务器或服务器的边缘位置(如CDN节点),以便在后续请求中快速响应。

好处:

■ 减轻服务器压力:通过缓存常用响应来减少对源服务器的直接请求。

■ 内容分发:在跨地域的内容分发中,使用CDN缓存可以使用户更快地接收到数据。

■ 高流量网站:对于用户量大的网站,服务器缓存可以显著减少对源站的请求压力。

4.2 客户端缓存

客户端缓存是指将网页资源存储在用户的设备上(如浏览器),以便在后续访问时能够快速加载。

好处:

■ 减少网络流量:由于资源可以直接从本地获取,减少了数据从服务器到客户端的传输。

■ 加快请求速度:使用浏览器缓存可以避免网络延迟,提高页面加载速度。

■ 离线浏览:即使在网络不稳定或无网络时,用户仍然可以访问已经缓存的网页内容。

所以, 服务器端缓存的目的是减轻服务器压力、提高内容分发速度和减少高流量网站的请求压力,而客户端缓存则是为了加快页面加载速度、减少网络流量和支持离线浏览。


五、客户端缓存的参数设置,举例代码实现缓存

5.1 在HTTP客户端中添加缓存通常涉及以下参数:

  1. Cache-Control:
    ○ max-age:指定资源在客户端缓存的最大有效时间(秒)。例如,Cache-Control: max-age=3600表示资源在客户端缓存1小时。
    ○ public:资源可以被任何缓存存储(如浏览器、代理服务器)。
    ○ private:资源仅能被客户端缓存。
    ○ no-cache:需要重新验证资源有效性。
    ○ no-store:禁止缓存。
  2. Expires:表示资源的过期时间,是一个绝对时间。例如,Expires: Wed, 21 Oct 2023 07:28:00 GMT。需要注意的是,如果同时存在Cache-Control和Expires字段,Cache-Control的优先级更高。
  3. ETag:服务器返回的资源的唯一标识。客户端在后续请求中可以携带此标识(通过If-None-Match请求头),以便服务器验证资源是否发生变化。
  4. Last-Modified:标识响应资源的最后修改时间。客户端在后续请求中可以携带此时间(通过If-Modified-Since请求头),以便服务器验证资源是否已更新。

5.2 举例代码实现缓存

接下来做个例子, 我们在Android应用中使用Retrofit添加HTTP缓存时,你可以通过配置OkHttp客户端来实现。 比如我们要查询订单数据。

  1. 创建缓存目录和缓存实例
    在Android应用中,指定一个目录来存储缓存文件。通常,这个目录可以是应用的内部缓存目录。
java 复制代码
File httpCacheDirectory = new File(getApplicationContext().getCacheDir(), "http-cache");
int cacheSize = 10 * 1024 * 1024; // 10 MB
Cache cache = new Cache(httpCacheDirectory, cacheSize);
  1. 配置OkHttp客户端
    创建一个OkHttp客户端实例,并配置缓存和拦截器来处理HTTP头部。
java 复制代码
OkHttpClient client = new OkHttpClient.Builder()
    .cache(cache)
    .addInterceptor(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            // 添加自定义的Cache-Control头部,设置缓存时间为5分钟
            Request request = chain.request().newBuilder()
                .header("Cache-Control", "public, max-age=300") // 5 minutes in seconds
                .build();

            Response response = chain.proceed(request);

            // 你可以在这里添加额外的逻辑来处理响应,比如根据ETag或Last-Modified验证缓存

            // 示例:如果服务器返回了304 Not Modified,你可以从缓存中获取数据(这通常是由OkHttp自动处理的)
            // 但如果你想手动处理,可以检查response.code()是否为304,并从缓存中检索原始响应

            return response;
        }
    })
    .build();
  1. 创建Retrofit实例
    使用配置好的OkHttp客户端来创建Retrofit实例。
java 复制代码
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://your.api.endpoint/")
    .client(client)
    .build();
4. 定义API接口
定义你的API接口,就像平常一样。
public interface ApiService {
    @GET("your/endpoint")
    Call<YourResponseModel> getYourData();

}
  1. 使用Retrofit进行网络请求
    现在,你可以使用Retrofit进行网络请求,并且请求的结果会根据你设置的缓存策略(以及服务器响应中的缓存头部)进行缓存。
java 复制代码
ApiService apiService = retrofit.create(ApiService.class);
Call<YourResponseModel> call = apiService.getYourData();
 
call.enqueue(new Callback<YourResponseModel>() {
    @Override
    public void onResponse(Call<YourResponseModel> call, Response<YourResponseModel> response) {
        if (response.isSuccessful()) {
            // Handle the response data
            YourResponseModel data = response.body();
            // ...
        } else {
            // Handle the error
        }
    }
 
    @Override
    public void onFailure(Call<YourResponseModel> call, Throwable t) {
        // Handle the failure
    }
});

通过上述步骤,你可以在Android应用中使用Retrofit和OkHttp实现HTTP缓存。这样,当网络请求的数据在缓存有效期内时,客户端将直接从缓存中读取数据,而不是每次都向服务器发送请求。这可以显著提高应用的性能和用户体验。同时,服务端也应该设置适当的HTTP头部来配合客户端的缓存策略。

回到我们最开始的问题,为什么有时候遇到问题需要清除缓存呢?有时候是因为数据错误了,或者是旧的了,然后服务器进行了处理,如果我们想要获得最新的数据,那么就需要清除缓存,获取新的数据。

好了,内容就介绍到这里,我是前期后期,如果大家有内容想要讨论,可以在评论区分享,我们下一篇文章见。

相关推荐
乐闻x12 分钟前
优化 HTTP 接口请求:缓存策略与实现方法
网络协议·http·缓存
牛哄哄的柯南24 分钟前
有监督学习 vs 无监督学习:机器学习的两大支柱
人工智能·学习·机器学习
Hello.Reader32 分钟前
大批量URL去重的架构设计(redis-bitmap+redisson)
数据库·redis·缓存
等什么君!34 分钟前
学习反射(反射的使用,反射的应用场景)
java·开发语言·学习
逸琅37 分钟前
五十个网络安全学习项目——(九)无线网络安全分析
网络·学习·web安全
想一个不重名的名字43 分钟前
web端http请求响应头集合
前端·网络协议·http
右恩1 小时前
【二维码美化】
服务器·前端·python·学习
小仙有礼了1 小时前
Arcgis for javascript 开发学习经验
javascript·学习·arcgis
澄澈i1 小时前
设计模式学习[13]---抽象工厂模式+简单工厂+工厂方法模式回顾
学习·设计模式·抽象工厂模式
南宫生2 小时前
力扣-图论-18【算法学习day.68】
java·学习·算法·leetcode·图论