3. 使用本地文件系统作为缓存仓库:配置 repositories.localCache、目录创建与权限

在离线环境下,Gradle 必须通过预先填充的本地缓存来提供所有依赖。使用 repositories.localCache 配置可以将一个预先准备好的本地文件夹注册为唯一的依赖仓库,完全绕过远程仓库调用。本章从原理到实施详细讲解如何设置、调试并加固该缓存仓库。

3.1 原理:本地文件系统缓存的工作方式

Gradle 的依赖解析生命周期中,仓库列表的优先级由声明顺序决定。当使用 repositories.localCache 时,Gradle 会以与 Maven 仓库相同的目录结构 <groupId>/<artifactId>/<version>/<artifact>-<version>.pom 扫描本地路径。离线模式下,若该仓库中找不到依赖,则整个构建立即失败,不会回退到任何远程仓库。

核心行为:

  • 仓库类型:ivy 或 maven 风格的本地目录
  • 元数据要求:必须包含 .pom 或 ivy.xml 文件(视仓库类型而定)
  • 离线开关:--offline 标志阻止任何远程访问,但不影响本地仓库的读取
本地缓存仓库解析流程 本地文件系统缓存仓库解析流程 项目构建开始 读取 repositories.localCache 检查本地目录是否存在 目录可用? 扫描依赖元数据 报错:目录不可用 缓存命中? 直接使用本地文件 构建失败(离线) 是 否 是 否

3.2 配置 repositories.localCache

repositories.localCache 是 Gradle 提供的一个便捷方法,用于添加基于本地文件系统的 Maven 或 Ivy 仓库。常用配置位置在 settings.gradle 中,可以确保该仓库对项目中的所有子项目生效。

最佳实践: 在 settings.gradle 中使用 pluginManagement.repositories 和 dependencyResolutionManagement.repositories 同时配置本地缓存,以覆盖插件和依赖两部分。

配置示例(settings.gradle):

dependencyResolutionManagement {
    repositories {
        localCache {
            // 指定本地缓存目录的路径
            directory = file("/opt/gradle-offline-cache")
            // 可选:设置仓库类型,默认自动检测
            // type = "maven"
        }
    }
}

pluginManagement {
    repositories {
        localCache {
            directory = file("/opt/gradle-offline-cache")
        }
    }
}

配置参数说明:

属性描述必需
directory本地文件系统缓存目录的路径是
type仓库格式("maven" 或 "ivy"),默认自动从目录结构推断否
name仓库逻辑名称,用于日志输出区分否

3.3 目录创建与权限设置

缓存目录必须在构建开始前存在且可读写。需要特别注意 Linux 环境下由 Jenkins、CI 或容器执行的构建,运行用户通常不是 root。

创建目录(Linux / macOS):

mkdir -p /opt/gradle-offline-cache
chown -R gradle:gradle /opt/gradle-offline-cache
chmod 755 /opt/gradle-offline-cache

创建目录(Windows):

mkdir C:\gradle-offline-cache
icacls C:\gradle-offline-cache /grant "gradle:(OI)(CI)F"

权限验证命令:

# Linux
ls -ld /opt/gradle-offline-cache
# 输出类似:
# drwxr-xr-x 2 gradle gradle 4096 Apr  1 10:00 /opt/gradle-offline-cache

# Windows
icacls C:\gradle-offline-cache

3.4 调试与验证

配置完成后,可以通过 Gradle 的依赖报告或详细日志确认是否使用了本地缓存。

方法一:查看依赖报告

gradle dependencies --offline

方法二:打开仓库解析日志

gradle build --offline --info | grep "localCache"

预期日志输出示例:

2025-04-01T10:00:00.000+0000 [INFO] [org.gradle.api.internal.artifacts.repositories.resolver.ExternalResourceResolver] 
  Using localCache repository at /opt/gradle-offline-cache for artifact com.example:my-lib:1.0.0

如果看到 Could not find artifact ... in localCache,则说明缓存目录中缺少该依赖的 POM 和 JAR 文件。

3.5 常见错误与解决方案

错误信息可能原因解决方案
Directory /path/to/cache does not exist目录未创建或路径错误确认目录存在且 settings.gradle 中路径为路径
Permission denied运行 Gradle 的用户没有读写权限执行 chmod 755 并修改目录所有者
No cached version of ... available for offline mode本地缓存中缺少该依赖在在线环境中使用 gradle build --no-daemon --build-cache 预填充缓存后重新打包
Cannot change strategy of configuration ... after it has been resolved在多项目构建中仓库配置顺序错误确保 dependencyResolutionManagement.repositories 在所有 build.gradle 之前定义

3.6 性能与稳定性优化

  • 使用固态硬盘(SSD): 缓存目录放在 SSD 上可显著减少依赖解析时的 I/O 延迟。
  • 避免符号链接: 缓存目录应使用真实物理路径,符号链接可能导致 Gradle 解析器误判仓库可达性。
  • 定期清理过期缓存: 使用 cron job 或构建后脚本删除超过 N 天的缓存文件,防止磁盘空间爆炸。
  • 副本保护: 在分布式 CI 环境中,将缓存目录挂载为只读共享卷(NFS 或 SAN),确保所有节点使用一致快照。

重要: 如果多个构建并发访问同一个本地缓存目录,务必使用文件锁或只读挂载以避免文件损坏。Gradle 本身对同目录并发读取是安全的,但写入(例如并行预填充)可能导致元数据不一致。