目录:
- 问题的背景
- Http的缓存是什么
- 客户端设置缓存,需要服务端允许?
- 缓存分类:为什么会有客户端缓存和服务器端缓存?
- 客户端缓存的参数设置,举例代码实现缓存
一、问题的背景
有时候网站出现问题,或者数据没有改变,通常客服或者售后会让我们刷新一下网页,或者关掉浏览器,或者清掉缓存再试试,然后就可以了,这是为什么呢?
今天我们就来看看http缓存是怎么样的。
二、Http的缓存是什么
HTTP缓存的主要目的是为了提高网页的加载速度和减少服务器的负载。当用户首次访问一个网页时,浏览器会下载网页上的所有资源(如HTML、CSS、JavaScript、图像等)。如果这些资源被缓存在本地,那么当用户再次访问该网页时,浏览器就可以直接从缓存中加载这些资源,而无需再次从服务器下载。这样可以显著减少加载时间,提高用户体验。
三、客户端设置缓存,需要服务端允许?
服务端是否设置这些头部字段并不影响客户端本身具有缓存功能的能力。即使服务端没有设置任何缓存相关的头部字段,客户端仍然可以缓存资源(尽管这种缓存可能是基于默认策略或客户端自定义策略的)。但是,为了确保客户端能够按照预期的缓存策略进行缓存,并避免潜在的缓存一致性问题,建议服务端明确设置这些头部字段。
四、缓存分类:为什么会有客户端缓存和服务器端缓存?
4.1 服务器端缓存
服务器端缓存是指将经常访问的数据或资源存储在服务器或服务器的边缘位置(如CDN节点),以便在后续请求中快速响应。
好处:
■ 减轻服务器压力:通过缓存常用响应来减少对源服务器的直接请求。
■ 内容分发:在跨地域的内容分发中,使用CDN缓存可以使用户更快地接收到数据。
■ 高流量网站:对于用户量大的网站,服务器缓存可以显著减少对源站的请求压力。
4.2 客户端缓存
客户端缓存是指将网页资源存储在用户的设备上(如浏览器),以便在后续访问时能够快速加载。
好处:
■ 减少网络流量:由于资源可以直接从本地获取,减少了数据从服务器到客户端的传输。
■ 加快请求速度:使用浏览器缓存可以避免网络延迟,提高页面加载速度。
■ 离线浏览:即使在网络不稳定或无网络时,用户仍然可以访问已经缓存的网页内容。
所以, 服务器端缓存的目的是减轻服务器压力、提高内容分发速度和减少高流量网站的请求压力,而客户端缓存则是为了加快页面加载速度、减少网络流量和支持离线浏览。
五、客户端缓存的参数设置,举例代码实现缓存
5.1 在HTTP客户端中添加缓存通常涉及以下参数:
- Cache-Control:
○ max-age:指定资源在客户端缓存的最大有效时间(秒)。例如,Cache-Control: max-age=3600表示资源在客户端缓存1小时。
○ public:资源可以被任何缓存存储(如浏览器、代理服务器)。
○ private:资源仅能被客户端缓存。
○ no-cache:需要重新验证资源有效性。
○ no-store:禁止缓存。 - Expires:表示资源的过期时间,是一个绝对时间。例如,Expires: Wed, 21 Oct 2023 07:28:00 GMT。需要注意的是,如果同时存在Cache-Control和Expires字段,Cache-Control的优先级更高。
- ETag:服务器返回的资源的唯一标识。客户端在后续请求中可以携带此标识(通过If-None-Match请求头),以便服务器验证资源是否发生变化。
- Last-Modified:标识响应资源的最后修改时间。客户端在后续请求中可以携带此时间(通过If-Modified-Since请求头),以便服务器验证资源是否已更新。
5.2 举例代码实现缓存
接下来做个例子, 我们在Android应用中使用Retrofit添加HTTP缓存时,你可以通过配置OkHttp客户端来实现。 比如我们要查询订单数据。
- 创建缓存目录和缓存实例
在Android应用中,指定一个目录来存储缓存文件。通常,这个目录可以是应用的内部缓存目录。
java
File httpCacheDirectory = new File(getApplicationContext().getCacheDir(), "http-cache");
int cacheSize = 10 * 1024 * 1024; // 10 MB
Cache cache = new Cache(httpCacheDirectory, cacheSize);
- 配置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();
- 创建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();
}
- 使用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头部来配合客户端的缓存策略。
回到我们最开始的问题,为什么有时候遇到问题需要清除缓存呢?有时候是因为数据错误了,或者是旧的了,然后服务器进行了处理,如果我们想要获得最新的数据,那么就需要清除缓存,获取新的数据。
好了,内容就介绍到这里,我是前期后期,如果大家有内容想要讨论,可以在评论区分享,我们下一篇文章见。