dio_cache_interceptor缓存拦截器框架之CacheStore、CachePolicy、CacheOptions源码分析(二)

471 阅读9分钟

CacheStore(抽象类)

/// Definition of store
abstract class CacheStore {}

CacheStore 是一个抽象类的定义,用于表示缓存存储的接口。

exists

/// Checks if key exists in store
Future<bool> exists(String key);

exists 方法是 CacheStore 抽象类中的一个声明方法,用于检查指定的键(key)是否存在于缓存存储中。

get

/// Retrieves cached response from the given key.
Future<CacheResponse?> get(String key);

get 方法是 CacheStore 抽象类中的一个声明方法,用于根据指定的键(key)从缓存中检索缓存响应。

getFromPath

/// Retrieves cached responses from a path pattern.
///
/// [pathPattern] path pattern (e.g. RegExp('https://www.example.com/a/b') or
/// RegExp(r'https://www.example.com/a/\d+)).
///
/// [queryParams] filter is processed in the following way:
/// - null: all entries are collected,
/// - null value: all entries containing the key are collected,
/// - otherwise key/value match only.
///
/// You should be very restrictive when using this method as the underlying
/// store may parse and load all data from the store.
Future<List<CacheResponse>> getFromPath(
  RegExp pathPattern, {
  Map<String, String?>? queryParams,
});

getFromPath 方法是 CacheStore 抽象类中的一个声明方法,用于根据指定的路径模式从缓存中检索缓存响应列表。

参数说明:

  • pathPattern: 路径模式,可以使用正则表达式来匹配缓存中的路径。例如,RegExp('https://www.example.com/a/b')RegExp(r'https://www.example.com/a/\d+')

  • queryParams(可选): 查询参数过滤器,用于对缓存响应进行筛选。其具体处理方式如下:

    • null: 收集所有符合路径模式的缓存响应。
    • null 值:收集包含指定键的所有缓存响应。
    • 其他值:只匹配指定键值对的缓存响应。

注意事项:

  • 使用 getFromPath 方法时应该非常谨慎,因为底层存储可能会解析并加载所有与路径模式匹配的数据。
  • 如果数据量较大或缓存的路径模式较宽泛,可能导致性能问题。

返回值:

  • 返回一个 Future<List<CacheResponse>> 对象,表示缓存响应列表。列表中包含所有符合路径模式和查询参数过滤条件的缓存响应。

CacheResponse 对象通常包含缓存的响应数据以及相关的元数据,例如过期时间、缓存标记等。

示例用法:

dartCopy code
// 假设 cacheStore 是 CacheStore 的一个实例

// 获取所有符合路径模式的缓存响应
List<CacheResponse> cacheResponses = await cacheStore.getFromPath(
  RegExp(r'https://www.example.com/a/\d+'),
  queryParams: {
    'param1': 'value1',
    'param2': null,
  },
);

// 遍历缓存响应列表并处理数据
for (var cacheResponse in cacheResponses) {
  var responseData = cacheResponse.data; // 缓存响应数据
  var expirationTime = cacheResponse.expirationTime; // 缓存过期时间
  // ...
}

通过 getFromPath 方法,我们可以根据指定的路径模式和查询参数过滤条件获取符合条件的缓存响应列表,并对列表中的缓存响应进行相应的处理逻辑。请注意,该方法可能会涉及到数据的加载和解析,因此应谨慎使用,避免性能问题。

set

/// Pushes response in store
Future<void> set(CacheResponse response);

set 方法是 CacheStore 抽象类中的一个声明方法,用于将缓存响应保存到缓存存储中。

delete

/// Removes the given key from store.
/// [staleOnly] flag will remove it only if the key is expired
/// (from maxStale).
Future<void> delete(String key, {bool staleOnly = false});

delete 方法是 CacheStore 抽象类中的一个声明方法,用于从缓存存储中删除指定的缓存数据。

deleteFromPath

/// Removes keys from the given filters.
///
/// [pathPattern] path pattern (e.g. RegExp('https://www.example.com/a/b') or
/// RegExp(r'https://www.example.com/a/\d+)).
///
/// [queryParams] filter is processed in the following way:
/// - null: all entries are collected,
/// - null value: all entries containing the key are collected,
/// - otherwise key/value match only.
///
/// You should be very restrictive when using this method as the underlying
/// store may parse and load all data from the store.
Future<void> deleteFromPath(
  RegExp pathPattern, {
  Map<String, String?>? queryParams,
});

deleteFromPath 方法是 CacheStore 抽象类中的一个声明方法,用于从缓存存储中删除满足指定过滤条件的缓存数据。

参数说明:

  • pathPattern: 路径模式,通常为一个正则表达式,用于匹配要删除的缓存数据的路径。例如,RegExp('https://www.example.com/a/b') 可以用于匹配路径为 https://www.example.com/a/b 的缓存数据。

  • queryParams: 查询参数过滤器,是一个 Map 对象,用于根据查询参数来过滤要删除的缓存数据。具体规则如下:

    • 如果 queryParams 参数为 null,则删除所有满足路径模式的缓存数据。
    • 如果 queryParams 参数包含键名为 null 的项,则删除所有满足路径模式且包含指定查询参数键名的缓存数据。
    • 否则,只删除满足路径模式且查询参数与 queryParams 中的键值对完全匹配的缓存数据。

返回值:

  • Future<void> 对象,表示删除缓存数据的异步操作。

clean

/// Removes all keys from store.
/// [priorityOrBelow] flag will remove keys only for the priority or below.
/// [staleOnly] flag will remove keys only if expired
/// (from maxStale).
///
/// By default, all keys will be removed.
Future<void> clean({
  CachePriority priorityOrBelow = CachePriority.high,
  bool staleOnly = false,
});

clean 方法是 CacheStore 抽象类中的一个声明方法,用于从缓存存储中删除所有缓存数据或指定优先级以下的缓存数据。

clean 方法是 CacheStore 抽象类中的一个声明方法,用于从缓存存储中删除所有缓存数据或指定优先级以下的缓存数据。

方法签名为:

dartCopy code
Future<void> clean({
  CachePriority priorityOrBelow = CachePriority.high,
  bool staleOnly = false,
});

参数说明:

  • priorityOrBelow:可选参数,缓存数据的优先级过滤条件。缓存数据有不同的优先级,可以根据该参数来指定要删除的缓存数据的优先级范围。默认值为 CachePriority.high,表示删除高优先级及以下的缓存数据。可选值包括:

    • CachePriority.low: 缓存定义为低优先级。
    • CachePriority.normal: 缓存定义为普通优先级。
    • CachePriority.high: 缓存定义为高优先级。
  • staleOnly:可选参数,用于指定是否只删除已过期的缓存数据。默认值为 false,表示删除所有缓存数据,无论是否过期。如果设置为 true,则只删除已过期的缓存数据。

返回值:

  • Future<void> 对象,表示删除缓存数据的异步操作。

close

/// Releases underlying resources (if any)
Future<void> close();

close 方法是 CacheStore 抽象类中的一个声明方法,用于释放底层资源(如果有的话)。

pathExists

/// Checks if the given url matches with the given filters.
/// [url] must conform to uri parsing.
bool pathExists(
  String url,
  RegExp pathPattern, {
  Map<String, String?>? queryParams,
}) {
  if (!pathPattern.hasMatch(url)) return false;

  var hasMatch = true;

  final uri = Uri.parse(url);
  if (queryParams != null) {
    for (final entry in queryParams.entries) {
      hasMatch &= uri.queryParameters.containsKey(entry.key);
      if (entry.value != null) {
        hasMatch &= uri.queryParameters[entry.key] == entry.value;
      }
      if (!hasMatch) break;
    }
  }

  return hasMatch;
}

pathExists 方法用于检查给定的 URL 是否与给定的过滤条件匹配。

参数:

  • url:要检查的 URL 字符串,必须符合 URI 解析规则。
  • pathPattern:用于匹配 URL 的正则表达式。
  • queryParams:查询参数过滤器,一个可选的 Map,表示查询参数的键值对,用于进一步过滤匹配的 URL。

返回值:

  • bool 类型,表示给定的 URL 是否匹配过滤条件。如果匹配,则返回 true;否则返回 false

CachePolicy

/// Policy to handle request behaviour.
enum CachePolicy {
  /// Same as [CachePolicy.request] when origin server has no cache config.
  ///
  /// In short, you'll save every successful GET requests.
  forceCache,

  /// Same as [CachePolicy.refresh] when origin server has no cache config.
  refreshForceCache,

  /// Requests and skips cache save even if
  /// response has cache directives.
  noCache,

  /// Requests regardless cache availability.
  /// Caches if response has cache directives.
  refresh,

  /// Returns the cached value if available (and un-expired).
  ///
  /// Checks against origin server otherwise and updates cache freshness
  /// with returned headers when validation is needed.
  ///
  /// Requests otherwise and caches if response has directives.
  request,
}

CachePolicy 是一个枚举类型,用于定义缓存策略,即控制请求行为的方式。

枚举成员:

  • forceCache:如果源服务器没有缓存配置,则与 CachePolicy.request 相同。简而言之,将保存每个成功的 GET 请求的缓存。
  • refreshForceCache:如果源服务器没有缓存配置,则与 CachePolicy.refresh 相同。简而言之,强制刷新并保存缓存,即使响应具有缓存指令。
  • noCache:请求并跳过缓存保存,即使响应具有缓存指令。
  • refresh:无论缓存是否可用,都会发起请求。如果响应具有缓存指令,则缓存响应。
  • request:如果可用(且未过期),则返回缓存值。否则,根据需要检查源服务器,并根据返回的标头更新缓存的新鲜度。否则,请求并缓存响应。

CacheOptions

/// Options to apply to handle request and cache behaviour.
class CacheOptions {
  /// Handles behaviour to request backend.
  final CachePolicy policy;

  /// Ability to return cache excepted on given status codes.
  /// Giving an empty list will hit cache on any status codes.
  ///
  /// Other errors, such as socket exceptions (connect, send TO, receive TO,
  /// ...),
  /// will trigger the cache.
  final List<int>? hitCacheOnErrorExcept;

  /// Builds the unique key used for indexing a request in cache.
  /// Default to [CacheOptions.defaultCacheKeyBuilder]
  final CacheKeyBuilder keyBuilder;

  /// The priority of a cached value.
  /// Ease the clean up if needed.
  final CachePriority priority;

  /// Store used for caching data.
  ///
  /// Required when setting interceptor.
  /// Optional when setting new options on dedicated requests.
  final CacheStore? store;

  /// Optional method to decrypt/encrypt cache content
  final CacheCipher? cipher;

  /// allow POST method request to be cached.
  final bool allowPostMethod;

  // Key to retrieve options from request
  static const _extraKey = '@cache_options@';

  // UUID helper to mark requests
  static final _uuid = Uuid();

  const CacheOptions({
    this.policy = CachePolicy.request,
    this.hitCacheOnErrorExcept,
    this.keyBuilder = defaultCacheKeyBuilder,
    this.maxStale,
    this.priority = CachePriority.normal,
    this.cipher,
    this.allowPostMethod = false,
    required this.store,
  });

  static CacheOptions? fromExtra(RequestOptions request) {
    return request.extra[_extraKey];
  }

  /// 缓存键
  static String defaultCacheKeyBuilder(RequestOptions request) {
    return _uuid.v5(Uuid.NAMESPACE_URL, request.uri.toString());
  }

  Map<String, dynamic> toExtra() {
    return {_extraKey: this};
  }

  Options toOptions() {
    return Options(extra: toExtra());
  }

  CacheOptions copyWith({
    CachePolicy? policy,
    Nullable<List<int>>? hitCacheOnErrorExcept,
    CacheKeyBuilder? keyBuilder,
    Nullable<Duration>? maxStale,
    CachePriority? priority,
    CacheStore? store,
    Nullable<CacheCipher>? cipher,
    bool? allowPostMethod,
  }) {
    return CacheOptions(
      policy: policy ?? this.policy,
      hitCacheOnErrorExcept: hitCacheOnErrorExcept != null
          ? hitCacheOnErrorExcept.value
          : this.hitCacheOnErrorExcept,
      keyBuilder: keyBuilder ?? this.keyBuilder,
      maxStale: maxStale != null ? maxStale.value : this.maxStale,
      priority: priority ?? this.priority,
      store: store ?? this.store,
      cipher: cipher != null ? cipher.value : this.cipher,
      allowPostMethod: allowPostMethod ?? this.allowPostMethod,
    );
  }
}

CacheOptions 是一个用于处理请求和缓存行为的选项类。

  • policy:处理向后端请求的行为,类型为 CachePolicy 枚举。
  • hitCacheOnErrorExcept:一个整数列表,用于指定在给定状态码上返回缓存,除非在指定的状态码上返回缓存。如果列表为空,则会在任何状态码上返回缓存。其他错误,如套接字异常(连接、发送超时、接收超时等),也会触发缓存。
  • keyBuilder:用于构建用于索引缓存请求的唯一键的方法,默认为 CacheOptions.defaultCacheKeyBuilder 方法。
  • priority:缓存值的优先级,用于在需要时简化清理。
  • store:用于缓存数据的存储。在设置拦截器时必需,在设置专用请求的新选项时可选。
  • cipher:可选的方法,用于解密/加密缓存内容。
  • allowPostMethod:是否允许 POST 方法请求进行缓存。

maxStale

 /// Overrides any HTTP directive to delete entry past this duration.
  ///
  /// Giving this value to a later request will update the previously
  /// cached response with this directive.
  ///
  /// This allows to postpone the deletion.
  final Duration? maxStale;
  • maxStale:用于覆盖任何 HTTP 指令以在此持续时间后删除条目的持续时间。如果在后续请求中给定此值,将使用此指令更新先前缓存的响应。这允许推迟删除。

fromExtra、toExtra、toOptions

  • fromExtra(RequestOptions request):从请求的额外信息中获取 CacheOptions 对象。
  • toExtra():将 CacheOptions 对象转换为额外信息的映射。
  • toOptions():将 CacheOptions 对象转换为 Options 对象,用于在 Dio 请求中使用。
  • copyWith(...):创建一个新的 CacheOptions 对象,并可选地修改其中的成员变量。

CacheKeyBuilder

/// Key builder to customize your keys.
typedef CacheKeyBuilder = String Function(RequestOptions request);

CacheKeyBuilder 是一个用于自定义缓存键的回调函数类型。它接受一个 RequestOptions 对象作为参数,并返回一个字符串作为缓存键。

在 Dio 缓存拦截器中,缓存键用于标识一个请求的唯一性,以便能够在缓存存储中索引和检索对应的缓存数据。不同的请求可能具有不同的缓存需求,例如基于请求的 URL、请求参数、请求头等信息来生成缓存键。