如何实现考虑请求头的OkHttp自定义缓存?
OkHttp自定义缓存:同时考虑请求头的解决方案
OkHttp默认缓存只依据URL生成缓存Key,导致同一接口不同请求头的响应会被错误复用,要解决这个问题,核心是让缓存Key包含你关心的请求头字段,具体可以通过自定义Cache类来实现:
1. 自定义Header感知的Cache类
继承OkHttp自带的Cache,重写cacheKey()方法,把需要区分的请求头(比如language)加入缓存Key的计算逻辑:
public class HeaderAwareCache extends Cache { public HeaderAwareCache(File directory, long maxSize) { super(directory, maxSize); } @Override protected String cacheKey(Request request) { // 先拿到默认的URL基础缓存Key String baseKey = super.cacheKey(request); // 获取需要纳入缓存区分的请求头,这里以language为例 String language = request.header("language"); if (language != null) { // 统一小写避免大小写差异导致的Key不一致 language = language.trim().toLowerCase(); // 拼接基础Key和语言参数,生成唯一缓存Key return baseKey + "_lang_" + language; } return baseKey; } }
2. 替换OkHttpClient的默认Cache
创建OkHttpClient实例时,使用你自定义的HeaderAwareCache替代默认缓存:
// 指定缓存目录和大小(示例为10MB) File cacheDir = new File(context.getCacheDir(), "api_response_cache"); long cacheMaxSize = 10 * 1024 * 1024; HeaderAwareCache customCache = new HeaderAwareCache(cacheDir, cacheMaxSize); OkHttpClient client = new OkHttpClient.Builder() .cache(customCache) .addInterceptor(new HeaderInterceptor()) // 你的请求头拦截器 .build();
3. 注意事项
- 确保服务器返回的响应允许缓存:响应头需要包含
Cache-Control(比如public, max-age=3600)或Expires字段,否则OkHttp不会缓存该响应。 - 多请求头扩展:如果需要同时考虑多个请求头(比如
language+region),可以在cacheKey()方法中拼接多个字段,例如:String region = request.header("region"); StringBuilder keyBuilder = new StringBuilder(baseKey); if (language != null) { keyBuilder.append("_lang_").append(language.trim().toLowerCase()); } if (region != null) { keyBuilder.append("_region_").append(region.trim().toLowerCase()); } return keyBuilder.toString(); - 请求头的准确性:确保你的
HeaderInterceptor确实正确添加了请求头,避免因头字段缺失导致缓存Key重复。
这样处理后,同一URL但不同language头的请求会生成不同的缓存Key,各自缓存对应的响应,切换语言后就能获取到对应语言的新数据,不会复用之前的缓存。
内容的提问来源于stack exchange,提问作者Biscuit
相关产品推荐
相关产品推荐

