Skip to content

CAS Gradle 9.x 与 JDK 21 构建体系升级:从 Toolchains 到 CycloneDX SBOM 的全链路实践

作者: 必码 | bima.cc


前言

Apereo CAS(Central Authentication Service)作为全球最广泛采用的开源单点登录(SSO)解决方案之一,其构建体系在 7.3 版本中经历了自项目创立以来最为深刻的变革。CAS 7.3 基于 Spring Boot 3.5.6 和 Java 21 构建,这意味着它不仅要求运行时环境升级到 JDK 21,更在构建工具链层面全面拥抱了 Gradle 9.x 的新特性。从 Gradle Toolchains 的自动 JDK 下载机制,到 CycloneDX SBOM 的软件物料清单生成,再到 Jib 3.5.3 的多平台容器镜像构建,整个构建体系发生了质的变化。

本文基于 cas-overlay 项目 7.3 版本的 Gradle 9.1.0 构建配置,从源码分析的角度出发,系统性地梳理 CAS 构建体系从 5.3 到 7.3 的演进路径,深入解析每一个关键配置变更背后的技术动因。我们不仅会看到"改了什么",更要理解"为什么改"以及"怎么改"。

本文的读者受众包括:

  • 负责将 CAS 从 6.x 或 5.x 升级到 7.3 的架构师和运维工程师
  • 需要理解 Gradle 9.x 新特性对现有构建脚本影响的构建工程师
  • 关注软件供应链安全(SBOM)的技术管理者
  • 希望了解 Java 21 对 CAS 容器化部署影响的 DevOps 工程师
  • 对 CAS 依赖管理策略感兴趣的后端开发者

本文将从七个维度展开论述:构建体系跨版本演进全景、Gradle 9.x 核心特性与 CAS 适配、Foojay Toolchains 插件深度解析、CycloneDX SBOM 生成、Jib 多平台 Docker 镜像构建、Docker 多阶段构建 JDK 21 适配,以及依赖管理与版本控制。每个章节都包含可落地的配置示例和版本对比分析,力求为读者提供一份完整的升级参考手册。


第一章 CAS 构建体系跨版本演进全景

1.1 CAS 5.3:Gradle 7.5 + Java 8

CAS 5.3 是一个具有里程碑意义的版本,它标志着 CAS 项目从 Gradle 4.x 向 Gradle 7.5 的重大跨越。在 CAS 5.3 时代,Java 8 仍然是企业级应用的主流运行时环境,整个构建体系围绕 Java 8 的生态展开。

核心构建配置特征:

groovy
// CAS 5.3 典型构建配置(简化版)
plugins {
    id 'java'
    id 'org.springframework.boot' version '2.7.x'
    id 'io.spring.dependency-management' version '1.1.x'
}

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

dependencies {
    // MyBatis 数据层
    implementation 'org.mybatis:mybatis:3.5.6'
    implementation 'org.mybatis:mybatis-spring:1.3.1'

    // 数据库连接池
    implementation 'commons-dbcp:commons-dbcp:1.4'

    // 前端资源
    implementation 'org.webjars:bootstrap:3.4.1'
    implementation 'org.webjars:jquery:3.6.0'
}

CAS 5.3 的构建体系具有以下显著特征:

  1. Java 版本硬编码:通过 sourceCompatibilitytargetCompatibility 直接指定 Java 8,构建时要求 JAVA_HOME 指向 JDK 8 安装目录。这意味着开发团队的每个成员都必须手动安装并配置正确版本的 JDK。

  2. 依赖管理简单直接:使用 io.spring.dependency-management 插件配合 BOM(Bill of Materials)进行版本控制,依赖声明方式以 implementation 为主,版本号在大多数情况下由 BOM 隐式管理。

  3. MyBatis 生态的"保守选择":MyBatis 3.5.6 配合 mybatis-spring 1.3.1,这是一个经过大量生产验证的组合。mybatis-spring 1.3.1 对 Spring Framework 5.x 提供了良好的支持,但缺少对 Spring Boot 2.x 自动配置的原生集成。

  4. 连接池的"经典方案":使用 Apache Commons DBCP 1.4 作为数据库连接池。DBCP 1.4 虽然稳定,但缺乏连接池监控、异步获取连接等现代特性。

  5. 前端资源管理:WebJars 版本相对保守,Bootstrap 3.4.1 和 jQuery 3.6.0 是当时的主流选择。

CAS 5.3 构建体系架构图:

┌─────────────────────────────────────────────────────────────┐
│                    CAS 5.3 构建体系                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────┐    ┌──────────────┐    ┌───────────────┐  │
│  │  Gradle 7.5 │───▶│  Java 8 JDK  │───▶│  CAS WAR 包   │  │
│  │  (构建工具)  │    │ (手动安装)    │    │  (Servlet 3.1)│  │
│  └─────────────┘    └──────────────┘    └───────────────┘  │
│         │                                       │          │
│         ▼                                       ▼          │
│  ┌─────────────┐                        ┌───────────────┐  │
│  │ Spring Boot │                        │  Docker 镜像   │  │
│  │   2.7.x     │                        │  (手动构建)    │  │
│  └─────────────┘                        └───────────────┘  │
│         │                                                   │
│         ▼                                                   │
│  ┌─────────────────────────────────────────────────────┐   │
│  │              依赖管理 (dependency-management)         │   │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐            │   │
│  │  │MyBatis   │ │DBCP 1.4  │ │WebJars   │            │   │
│  │  │3.5.6     │ │          │ │Bootstrap │            │   │
│  │  │mybatis-  │ │          │ │3.4.1     │            │   │
│  │  │spring    │ │          │ │jQuery    │            │   │
│  │  │1.3.1     │ │          │ │3.6.0     │            │   │
│  │  └──────────┘ └──────────┘ └──────────┘            │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

1.2 CAS 6.6:Gradle 7.5 + Java 11

CAS 6.6 是连接旧时代与新时代的桥梁版本。它保持了 Gradle 7.5 的构建工具版本,但将 Java 运行时从 8 升级到了 11。Java 11 是 LTS(长期支持)版本,带来了模块化系统(Jigsaw)、HTTP Client API、局部变量类型推断(var)等重要特性。

核心构建配置特征:

groovy
// CAS 6.6 典型构建配置(简化版)
plugins {
    id 'java'
    id 'org.springframework.boot' version '3.0.x'
    id 'io.spring.dependency-management' version '1.1.x'
}

java {
    sourceCompatibility = JavaVersion.VERSION_11
    targetCompatibility = JavaVersion.VERSION_11
}

dependencies {
    // MyBatis 数据层 - 版本未变
    implementation 'org.mybatis:mybatis:3.5.6'
    implementation 'org.mybatis:mybatis-spring:1.3.1'

    // 数据库连接池 - 仍未升级
    implementation 'commons-dbcp:commons-dbcp:1.4'

    // 前端资源 - 版本小幅升级
    implementation 'org.webjars:bootstrap:5.2.3'
    implementation 'org.webjars:jquery:3.6.4'
}

CAS 6.6 的 Docker 构建配置:

dockerfile
# CAS 6.6 典型 Dockerfile
FROM eclipse-temurin:11-jdk AS builder
WORKDIR /app
COPY . .
RUN ./gradlew build -x test --no-daemon

FROM eclipse-temurin:11-jre
COPY --from=builder /app/build/libs/*.war /app/cas.war
EXPOSE 8443 8080
ENTRYPOINT ["java", "-jar", "/app/cas.war"]

CAS 6.6 的构建体系相比 5.3 有以下变化:

  1. Java 版本升级到 11:这是最大的变化。Java 11 移除了 Java EE 模块(如 javax.xml.bindjavax.annotation 等),CAS 需要手动添加这些依赖或迁移到 Jakarta 命名空间。不过 CAS 6.6 仍然基于 Spring Boot 2.x,尚未完全迁移到 Jakarta EE。

  2. Docker 基础镜像切换:从通用的 JDK 镜像切换到 eclipse-temurin:11-jdk,这是一个由 Eclipse Adoptium 项目维护的高质量 OpenJDK 发行版。Temurin 通过了 TCK(Technology Compatibility Kit)认证,保证了与 Java 规范的完全兼容。

  3. 前端资源升级:Bootstrap 从 3.4.1 升级到 5.2.3,这是一个跨越式升级。Bootstrap 5 移除了 jQuery 依赖,但 CAS 仍然保留了 jQuery 用于其他前端功能。

  4. MyBatis 和 DBCP 未升级:值得注意的是,CAS 6.6 保持了 MyBatis 3.5.6 + mybatis-spring 1.3.1 和 commons-dbcp 1.4 的组合。这反映了 CAS 项目在 6.x 时代的保守策略——优先保证稳定性,而非追求依赖的最新版本。

  5. Spring Boot 3.0.x 的引入:CAS 6.6 后期版本开始引入 Spring Boot 3.0.x,这意味着最低 Java 版本要求变成了 17。但 CAS 6.6 的主流配置仍然是 Java 11 + Spring Boot 2.7.x。

CAS 6.6 构建体系的关键痛点:

  • JDK 管理仍然手动:开发人员需要手动安装 JDK 11 并设置 JAVA_HOME
  • 没有 SBOM 生成:不满足日益严格的软件供应链安全合规要求
  • 容器镜像构建效率低:每次构建都需要下载全部依赖,缺乏有效的层缓存策略
  • 依赖版本管理分散:BOM 和直接版本声明混用,缺乏统一的版本控制策略

1.3 CAS 7.3:Gradle 9.1.0 + Java 21

CAS 7.3 代表了 CAS 构建体系的全面现代化。它不仅升级了 Java 版本,更在构建工具链、依赖管理、容器化、安全合规等多个维度进行了根本性的重构。

核心构建配置:

groovy
// CAS 7.3 核心构建配置(教学简化版)
plugins {
    id 'java'
    id 'org.springframework.boot' version '3.5.6'
    id 'io.spring.dependency-management' version '1.1.7'

    // Foojay Toolchains 插件 - 自动 JDK 下载
    id 'org.gradle.toolchains.foojay-resolver-convention' version '0.9.0'

    // CycloneDX SBOM 插件 - 软件物料清单生成
    id 'org.cyclonedx.bom' version '1.10.0'

    // Jib 插件 - 多平台容器镜像构建
    id 'com.google.cloud.tools.jib' version '3.5.3'
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
        vendor = JvmVendorSpec.AMAZON  // Amazon Corretto
    }
}

dependencies {
    // 使用 enforcedPlatform 进行严格版本控制
    enforcedPlatform("org.apereo.cas:cas-server-support-bom:${casServerVersion}")

    // MyBatis 数据层 - 大幅升级
    implementation 'org.mybatis:mybatis:3.5.16'
    implementation 'org.mybatis:mybatis-spring:3.0.3'

    // 数据库连接池 - 迁移到 DBCP2
    implementation 'org.apache.commons:commons-dbcp2:2.10.0'

    // 前端资源 - 全面升级
    implementation 'org.webjars:bootstrap:5.3.3'
    implementation 'org.webjars:jquery:3.7.1'
    implementation 'org.webjars.npm:material-components-web:14.0.0'
}

jib {
    from {
        image = 'azul/zulu-openjdk:21'
    }
    to {
        image = "your-registry/cas:${project.version}"
        tags = ['latest', 'jdk21']
    }
    platforms {
        platform {
            architecture = 'amd64'
            os = 'linux'
        }
        platform {
            architecture = 'arm64'
            os = 'linux'
        }
    }
}

cyclonedxBom {
    includeConfigs = ['runtimeClasspath', 'compileClasspath']
    schemaVersion = '1.5'
    destination = file("build/reports/cyclonedx")
}

CAS 7.3 构建体系架构图:

┌──────────────────────────────────────────────────────────────────────┐
│                       CAS 7.3 构建体系                                │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌──────────────┐   ┌──────────────────┐   ┌────────────────────┐   │
│  │  Gradle 9.1  │──▶│  Foojay          │──▶│  Amazon Corretto   │   │
│  │  (构建引擎)   │   │  Toolchains      │   │  JDK 21 (自动下载)  │   │
│  │              │   │  (自动JDK管理)    │   │                    │   │
│  └──────┬───────┘   └──────────────────┘   └────────┬───────────┘   │
│         │                                            │               │
│         ▼                                            ▼               │
│  ┌──────────────┐                          ┌────────────────────┐   │
│  │ Spring Boot  │                          │  CAS WAR 包         │   │
│  │   3.5.6      │                          │  (Servlet 6.0)     │   │
│  │              │                          │  (Jakarta EE 10)   │   │
│  └──────┬───────┘                          └────────┬───────────┘   │
│         │                                            │               │
│         ▼                                            ▼               │
│  ┌─────────────────────────────────────────────────────────────┐    │
│  │                    依赖管理 (enforcedPlatform)                │    │
│  │  ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐  │    │
│  │  │MyBatis    │ │DBCP2      │ │WebJars    │ │Material   │  │    │
│  │  │3.5.16     │ │2.10.0     │ │Bootstrap  │ │Components │  │    │
│  │  │mybatis-   │ │           │ │5.3.3      │ │Web 14.0.0 │  │    │
│  │  │spring     │ │           │ │jQuery     │ │           │  │    │
│  │  │3.0.3      │ │           │ │3.7.1      │ │           │  │    │
│  │  └───────────┘ └───────────┘ └───────────┘ └───────────┘  │    │
│  └─────────────────────────────────────────────────────────────┘    │
│                                                                      │
│  ┌──────────────────┐    ┌──────────────────┐                       │
│  │  Jib 3.5.3       │    │  CycloneDX       │                       │
│  │  (多平台镜像构建)  │    │  (SBOM 生成)     │                       │
│  │  amd64 + arm64   │    │  schema 1.5      │                       │
│  └──────────────────┘    └──────────────────┘                       │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘

CAS 7.3 构建体系的核心变革包括:

  1. Toolchains 自动 JDK 管理:通过 Foojay 插件,Gradle 会自动下载并使用指定版本的 JDK,开发人员无需手动安装。这是一个革命性的变化——团队成员只需安装任意版本的 Gradle Wrapper,构建系统会自动处理 JDK 版本问题。

  2. enforcedPlatform 严格版本控制:从 platform 升级到 enforcedPlatform,这意味着 BOM 中声明的版本具有强制约束力,任何传递依赖都无法覆盖 BOM 中指定的版本。这对于 CAS 这样的大型项目至关重要,可以有效防止依赖版本冲突。

  3. CycloneDX SBOM 生成:引入了软件物料清单(Software Bill of Materials)生成能力,满足 Executive Order 14028、EU Cyber Resilience Act 等法规对软件供应链透明度的要求。

  4. Jib 多平台镜像构建:使用 Jib 3.5.3 替代传统的 Dockerfile 构建,支持同时生成 amd64 和 arm64 架构的容器镜像,且无需 Docker daemon。

  5. MyBatis 跨代升级:从 mybatis-spring 1.3.1 升级到 3.0.3,这是一个跨越了 2.x 大版本的重大升级,带来了对 Spring Boot 3.x 的原生自动配置支持。

  6. 连接池现代化:从 commons-dbcp 1.4 迁移到 commons-dbcp2 2.10.0,获得了连接池监控、异步获取连接、连接泄漏检测等现代特性。

1.4 构建体系演进对比表

下表汇总了 CAS 三个主要版本在构建体系方面的关键差异:

维度CAS 5.3CAS 6.6CAS 7.3
Gradle 版本7.57.59.1.0
Java 版本8 (1.8)1121
Java 版本指定方式sourceCompatibility / targetCompatibilitysourceCompatibility / targetCompatibilityjava.toolchain
JDK 管理手动安装手动安装Foojay Toolchains 自动下载
JVM Vendor任意Eclipse TemurinAmazon Corretto
Spring Boot2.7.x2.7.x / 3.0.x3.5.6
Servlet 规范Servlet 3.1Servlet 4.0Servlet 6.0 (Jakarta)
依赖管理platform + dependency-managementplatform + dependency-managementenforcedPlatform
MyBatis3.5.6 + mybatis-spring 1.3.13.5.6 + mybatis-spring 1.3.13.5.16 + mybatis-spring 3.0.3
连接池commons-dbcp 1.4commons-dbcp 1.4commons-dbcp2 2.10.0
Bootstrap3.4.15.2.35.3.3
jQuery3.6.03.6.43.7.1
Material Components14.0.0
Docker 基础镜像通用 JDK 8 镜像eclipse-temurin:11-jdkazul/zulu-openjdk:21
容器构建方式DockerfileDockerfileJib 3.5.3
多平台支持amd64 + arm64
SBOM 生成CycloneDX 1.5
Configuration Cache不支持实验性生产就绪
Groovy/Kotlin DSLGroovyGroovyGroovy(Kotlin 可选)

版本演进关键里程碑图:

时间线 ─────────────────────────────────────────────────────────────▶

CAS 5.3          CAS 6.6              CAS 7.3
  │                │                    │
  │ Gradle 7.5     │ Gradle 7.5         │ Gradle 9.1.0
  │ Java 8         │ Java 11            │ Java 21
  │                │                    │
  │ ───────────────│────────────────────│──────────────
  │                │                    │
  │                │ Spring Boot 3.0    │ Spring Boot 3.5.6
  │                │ (部分版本)          │ Jakarta EE 10
  │                │                    │
  │                │                    │ ───────────────
  │                │                    │
  │                │                    │ Foojay Toolchains
  │                │                    │ CycloneDX SBOM
  │                │                    │ Jib 多平台
  │                │                    │ enforcedPlatform
  │                │                    │ MyBatis 3.0.3
  │                │                    │ DBCP2 2.10.0
  │                │                    │
  ▼                ▼                    ▼
┌──────┐      ┌──────┐            ┌──────────┐
│ 2019 │      │ 2022 │            │  2025    │
└──────┘      └──────┘            └──────────┘

第二章 Gradle 9.x 核心特性与 CAS 适配

2.1 Gradle 9.x 的重大变更

Gradle 9.x 是 Gradle 构建工具的一次重大版本升级,它引入了许多破坏性变更(breaking changes),对 CAS 项目的构建脚本产生了深远影响。理解这些变更对于成功迁移到 CAS 7.3 至关重要。

Gradle 版本演进路线:

Gradle 版本演进
═══════════════════════════════════════════════════════════

  Gradle 7.x          Gradle 8.x          Gradle 9.x
  ┌─────────┐        ┌─────────┐        ┌─────────┐
  │ 7.0     │───────▶│ 8.0     │───────▶│ 9.0     │
  │ 2021    │        │ 2023    │        │ 2025    │
  │         │        │         │        │         │
  │ • 配置  │        │ • 配置  │        │ • 配置  │
  │   避免API│        │   缓存  │        │   缓存  │
  │ • Groovy│        │   稳定  │        │   默认  │
  │   3.x   │        │ • Kotlin│        │   启用  │
  │ • JVM   │        │   DSL   │        │ • API   │
  │   Tool  │        │   增强  │        │   清理  │
  │   Chain │        │ • Isolated│       │ • Groovy│
  │   实验性│        │   Projects│       │   4.x   │
  │         │        │   实验性│        │ • Java  │
  └─────────┘        └─────────┘        │   24 基线│
                                        └─────────┘

Gradle 9.x 的核心变更清单:

  1. Configuration Cache 默认启用:这是对构建脚本影响最大的变更。Configuration Cache 要求所有构建逻辑必须是"无状态"的——不能在配置阶段访问项目状态、不能使用 afterEvaluate 回调、不能在配置阶段解析配置文件等。

  2. API 清理:大量在 Gradle 7.x/8.x 中被标记为 @Deprecated 的 API 被彻底移除。例如,Project.afterEvaluate() 的某些用法、旧的 DependencyHandler 方法签名等。

  3. Groovy 4.x 升级:Gradle 9.x 内置的 Groovy 版本从 3.x 升级到 4.x。这意味着构建脚本中使用的 Groovy 语法需要兼容 Groovy 4.x,特别是 GString 插值和闭包委托策略的变化。

  4. Isolated Projects 正式发布:项目隔离机制从实验性功能变为正式功能。每个子项目在配置阶段只能访问自己的项目对象,不能跨项目访问依赖关系。

  5. Java 24 作为基线:Gradle 9.x 本身需要 Java 17+ 才能运行,但推荐使用 Java 21 或更高版本。Gradle 9.x 的 API 设计时以 Java 24 作为目标基线。

CAS 7.3 对 Gradle 9.x 变更的适配策略:

groovy
// CAS 7.3 的 Gradle Wrapper 配置
// gradle/wrapper/gradle-wrapper.properties
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

CAS 7.3 在适配 Gradle 9.x 时采取了以下策略:

  • 保守的插件版本选择:所有插件都选择了与 Gradle 9.x 兼容的版本,避免使用实验性功能
  • 构建脚本简化:移除了所有在 Configuration Cache 下不兼容的构建逻辑
  • Toolchains 替代手动 JDK 管理:利用 Toolchains API 替代 sourceCompatibility/targetCompatibility

2.2 Configuration Cache 兼容处理

Configuration Cache 是 Gradle 在 8.x 中引入、9.x 中默认启用的性能优化特性。它的核心思想是:将构建的"配置阶段"结果缓存起来,后续构建如果配置没有变化,则直接使用缓存结果,跳过整个配置阶段。

Configuration Cache 工作原理:

传统构建流程(无 Configuration Cache):
═══════════════════════════════════════════════════════════

  初始化 ──▶ 配置阶段 ──▶ 执行阶段

              ├── 解析 settings.gradle
              ├── 解析 build.gradle
              ├── 评估所有插件
              ├── 解析依赖声明
              ├── 配置所有 Task
              └── 构建依赖图
              
  [每次构建都要完整执行配置阶段]

启用 Configuration Cache 后的构建流程:
═══════════════════════════════════════════════════════════

  首次构建:
  初始化 ──▶ 配置阶段 ──▶ 执行阶段 ──▶ 缓存配置结果
              │                        │
              │                        └──▶ ~/.gradle/configuration-cache/

  后续构建(配置未变化):
  初始化 ──▶ [读取缓存] ──▶ 执行阶段

              └── 直接加载缓存的配置结果
              
  [配置阶段被完全跳过,构建速度提升 30-50%]

Configuration Cache 的限制条件:

Configuration Cache 要求构建逻辑满足以下条件:

  1. 无状态配置:配置阶段的代码不能依赖于外部可变状态
  2. 无副作用:配置阶段不能执行 I/O 操作(如读取文件、网络请求)
  3. afterEvaluate:不能使用 project.afterEvaluate {} 回调
  4. gradle.projectsLoaded:不能在 settings.gradle 中使用此回调
  5. Provider API:所有属性访问必须通过 Provider API 进行懒加载

CAS 7.3 中的 Configuration Cache 兼容处理:

groovy
// ❌ 不兼容 Configuration Cache 的写法(CAS 5.3/6.6 风格)
project.afterEvaluate {
    // 在 afterEvaluate 中读取项目属性
    def casVersion = project.casServerVersion
    println "CAS version: ${casVersion}"
    
    // 动态添加依赖
    dependencies {
        implementation "org.apereo.cas:cas-server-support-xxx:${casVersion}"
    }
}

// ✅ 兼容 Configuration Cache 的写法(CAS 7.3 风格)
// 使用 Provider API 进行懒加载
def casVersion = project.providers.gradleProperty('casServerVersion')

dependencies {
    // 使用字符串插值,Gradle 会在执行阶段解析
    implementation "org.apereo.cas:cas-server-support-xxx:${casVersion.get()}"
}

// ✅ 使用 lazy configuration
configurations {
    integrationTestImplementation {
        extendsFrom implementation
    }
}

CAS 7.3 中 Configuration Cache 的配置:

groovy
// CAS 7.3 的 Configuration Cache 配置
// build.gradle

// 显式启用 Configuration Cache(Gradle 9.x 中默认启用)
configurationCache {
    // 允许在控制台输出 Configuration Cache 相关的警告
    problems {
        warnOnProblems()
    }
}

// 或者通过命令行参数控制
// ./gradlew build --configuration-cache
// ./gradlew build --no-configuration-cache  // 禁用

Configuration Cache 迁移常见问题与解决方案:

问题原因解决方案
Cannot call Project.afterEvaluateafterEvaluate 在 Configuration Cache 下不可用使用 Provider API 或 lazy configuration
Cannot access Project at configuration time配置阶段访问了项目状态将访问延迟到执行阶段
Build logic should not read files at configuration time配置阶段执行了文件 I/O使用 Provider.of()regularFile 属性
Provider is not compatible with Configuration Cache使用了不兼容的 Provider 实现使用 providers.factory 创建 Provider
Task properties are not correctly wiredTask 输入输出未正确声明使用 @InputFile@OutputDirectory 等注解

2.3 API 废弃与替代方案

Gradle 9.x 移除了大量在 7.x/8.x 中已废弃的 API。以下是 CAS 构建脚本中常见的影响点:

1. JvmVendorSpec API 变更

groovy
// ❌ Gradle 7.x 风格(在 9.x 中可能不可用)
java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
        vendor = JvmVendorSpec.AMAZON
    }
}

// ✅ Gradle 9.x 兼容写法
java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
        // 使用 JvmVendorSpec.of() 更安全
        vendor = JvmVendorSpec.matching("AMAZON")
    }
}

// ✅ 更通用的写法,兼容 Gradle 7.x/8.x/9.x
java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
        vendor = JvmVendorSpec.AMAZON
    }
}

2. 依赖声明 API 变更

groovy
// ❌ 旧式依赖声明(已废弃)
dependencies {
    compile group: 'org.mybatis', name: 'mybatis', version: '3.5.16'
    runtime group: 'org.apache.commons', name: 'commons-dbcp2', version: '2.10.0'
}

// ✅ 新式依赖声明
dependencies {
    implementation 'org.mybatis:mybatis:3.5.16'
    runtimeOnly 'org.apache.commons:commons-dbcp2:2.10.0'
}

3. Task 配置 API 变更

groovy
// ❌ 旧式 Task 配置(Configuration Cache 不兼容)
task copyConfig(type: Copy) {
    from "src/main/resources"
    into "$buildDir/config"
    // 在配置阶段解析属性
    def env = System.getenv("CAS_ENV") ?: "dev"
    rename { filename -> 
        filename.replace(".template", ".${env}")
    }
}

// ✅ 新式 Task 配置(Configuration Cache 兼容)
tasks.register('copyConfig', Copy) {
    from layout.projectDirectory.dir("src/main/resources")
    into layout.buildDirectory.dir("config")
    
    // 使用 Provider 延迟解析
    def env = providers.environmentVariable("CAS_ENV")
        .orElse("dev")
    
    rename { filename ->
        filename.replace(".template", ".${env.get()}")
    }
}

4. platformenforcedPlatform 的升级

groovy
// CAS 5.3/6.6:使用 platform(推荐但不强制)
dependencies {
    platform("org.apereo.cas:cas-server-support-bom:${casServerVersion}")
    implementation 'org.apereo.cas:cas-server-support-xxx'
    // 如果传递依赖声明了不同版本,可能产生冲突
}

// CAS 7.3:使用 enforcedPlatform(强制版本)
dependencies {
    enforcedPlatform("org.apereo.cas:cas-server-support-bom:${casServerVersion}")
    implementation 'org.apereo.cas:cas-server-support-xxx'
    // BOM 中的版本具有最高优先级,传递依赖无法覆盖
}

2.4 Groovy DSL vs Kotlin DSL 选择

CAS 7.3 默认使用 Groovy DSL 编写构建脚本,但 Gradle 9.x 对 Kotlin DSL 的支持已经非常成熟。两种 DSL 各有优劣:

Groovy DSL vs Kotlin DSL 对比:

维度Groovy DSLKotlin DSL
学习曲线低(Groovy 语法简单)中(需要 Kotlin 基础)
类型安全弱(运行时才发现类型错误)强(编译时类型检查)
IDE 支持优秀(自动补全更准确)
Configuration Cache需要额外注意天然友好
脚本后缀build.gradlebuild.gradle.kts
CAS 官方支持主要支持可选支持
社区资源丰富增长中
构建性能略慢(动态类型)略快(静态编译)

CAS 7.3 选择 Groovy DSL 的原因:

  1. 向后兼容:CAS 5.3 和 6.6 都使用 Groovy DSL,保持一致性可以降低迁移成本
  2. 社区资源丰富:Groovy DSL 的教程、示例和社区讨论远多于 Kotlin DSL
  3. 构建脚本复杂度适中:CAS overlay 项目的构建脚本不需要复杂的类型安全保证
  4. Gradle 插件兼容性:部分 Gradle 插件对 Groovy DSL 的支持更完善

Kotlin DSL 示例(供参考):

kotlin
// build.gradle.kts - CAS 7.3 的 Kotlin DSL 版本
plugins {
    java
    id("org.springframework.boot") version "3.5.6"
    id("io.spring.dependency-management") version "1.1.7"
    id("org.gradle.toolchains.foojay-resolver-convention") version "0.9.0"
    id("org.cyclonedx.bom") version "1.10.0"
    id("com.google.cloud.tools.jib") version "3.5.3"
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
        vendor = JvmVendorSpec.AMAZON
    }
}

dependencies {
    enforcedPlatform("org.apereo.cas:cas-server-support-bom:${casServerVersion}")
    
    implementation("org.mybatis:mybatis:3.5.16")
    implementation("org.mybatis:mybatis-spring:3.0.3")
    implementation("org.apache.commons:commons-dbcp2:2.10.0")
    implementation("org.webjars:bootstrap:5.3.3")
    implementation("org.webjars:jquery:3.7.1")
}

jib {
    from {
        image = "azul/zulu-openjdk:21"
    }
    to {
        image = "your-registry/cas:${project.version}"
    }
}

第三章 Foojay Toolchains 插件深度解析

3.1 Toolchains 概念与价值

Java Toolchains 是 JDK 9 中引入、在 Gradle 6.7 中获得支持的一个重要概念。它将"构建所需的 JDK 版本"与"运行 Gradle 的 JDK 版本"解耦,使得同一个 Gradle 安装可以构建需要不同 JDK 版本的项目。

传统 JDK 管理的痛点:

在没有 Toolchains 的时代,Java 项目的 JDK 管理面临以下问题:

传统 JDK 管理模式
═══════════════════════════════════════════════════════════

开发者 A 的机器:
  JAVA_HOME=/usr/lib/jvm/java-8     ← 项目 A 需要
  JAVA_HOME=/usr/lib/jvm/java-11    ← 项目 B 需要
  JAVA_HOME=/usr/lib/jvm/java-21    ← 项目 C 需要
  ❌ 只能设置一个 JAVA_HOME

解决方案(传统):
  1. 手动切换 JAVA_HOME(容易出错)
  2. 使用 SDKMAN(需要额外安装)
  3. 使用 jenv(macOS 专用)
  4. 在 IDE 中配置(不同 IDE 配置不同)

  ❌ 团队成员的 JDK 版本不一致
  ❌ CI/CD 需要安装多个 JDK
  ❌ 新成员入职配置成本高

Toolchains 的解决方案:

Toolchains 模式
═══════════════════════════════════════════════════════════

开发者 A 的机器:
  Gradle Wrapper(任意版本)


  Foojay Toolchains 插件

       ├── 检测 build.gradle 中的 toolchain 声明
       ├── 发现需要 JDK 21 (Amazon Corretto)
       ├── 检查本地缓存 (~/.gradle/jdks/)
       │     ├── 有 → 直接使用
       │     └── 没有 → 自动从 Foojay API 下载


  使用下载的 JDK 21 进行编译和测试

  ✅ 无需手动安装 JDK
  ✅ 团队成员自动使用相同版本
  ✅ CI/CD 无需预装 JDK
  ✅ 新成员零配置即可构建

Toolchains 的核心价值:

  1. 构建可重复性:所有团队成员和 CI/CD 环境使用完全相同的 JDK 版本和发行版
  2. 降低入门门槛:新成员只需克隆仓库并运行 ./gradlew build,无需任何额外配置
  3. 多版本共存:同一台机器可以同时构建需要不同 JDK 版本的项目
  4. CI/CD 简化:CI 环境不需要预装特定版本的 JDK,Foojay 插件会自动处理
  5. 安全性:通过 Foojay API 下载的 JDK 来自经过验证的发行版源

3.2 Foojay 插件配置详解

Foojay Toolchains 插件(org.gradle.toolchains.foojay-resolver-convention)是 Gradle 官方推荐的 Toolchains JDK 下载解决方案。它通过 Foojay Disco API(https://api.foojay.io)自动下载所需的 JDK 发行版。

插件声明:

groovy
// settings.gradle(推荐位置)
plugins {
    id 'org.gradle.toolchains.foojay-resolver-convention' version '0.9.0'
}

// 或者 build.gradle(也可以)
plugins {
    id 'org.gradle.toolchains.foojay-resolver-convention' version '0.9.0'
}

为什么推荐在 settings.gradle 中声明?

settings.gradle 中声明 Foojay 插件有一个重要优势:它可以在 Gradle 解析 build.gradle 之前就准备好 JDK。这意味着即使 build.gradle 中使用了特定 JDK 版本的 API,Gradle 也能正确处理。

插件声明位置的影响
═══════════════════════════════════════════════════════════

settings.gradle 中声明(推荐):
  settings.gradle 解析 → Foojay 插件激活 → JDK 下载 → build.gradle 解析
  ✅ build.gradle 可以安全使用新版本 JDK 的 API

build.gradle 中声明:
  settings.gradle 解析 → build.gradle 解析 → Foojay 插件激活 → JDK 下载
  ⚠️ build.gradle 解析时可能还没有正确的 JDK

Toolchains 声明:

groovy
// build.gradle
java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
        vendor = JvmVendorSpec.AMAZON
    }
}

Foojay 插件的工作流程:

Foojay Toolchains 工作流程
═══════════════════════════════════════════════════════════

  1. Gradle 读取 toolchain 声明

     ├── languageVersion = 21
     ├── vendor = AMAZON


  2. Foojay 插件查询本地 JDK 目录

     ├── ~/.gradle/jdks/
     ├── 操作系统检测 (Linux/macOS/Windows)
     ├── 架构检测 (x86_64/aarch64)


  3. 本地查找结果

     ├── 找到匹配的 JDK → 直接使用 ✅

     └── 未找到匹配的 JDK


  4. 调用 Foojay Disco API

     ├── GET https://api.foojay.io/disco/v3.0/distributions?
     │     package_type=jdk&version=21&distro=amazon_corretto&
     │     architecture=x64&operating_system=linux

     ├── 解析响应 JSON
     ├── 获取下载链接


  5. 下载并安装 JDK

     ├── 下载到 ~/.gradle/jdks/
     ├── 解压并验证
     ├── 注册到 Gradle Toolchain 服务


  6. 使用 JDK 进行构建

Foojay 插件的高级配置:

groovy
// settings.gradle - Foojay 插件高级配置
settingsEvaluated {
    // 可以通过系统属性控制 Foojay 行为
    if (System.getProperty('foojay.disable') == 'true') {
        // 禁用自动下载,仅使用本地已安装的 JDK
        gradle.settingsEvaluated {
            // 不做任何操作
        }
    }
}

// 通过 gradle.properties 控制行为
// gradle.properties
org.gradle.java.installations.auto-detect=true    // 自动检测已安装的 JDK
org.gradle.java.installations.paths=/path/to/jdks  // 指定 JDK 搜索路径

3.3 JVM Vendor 选择机制

CAS 7.3 选择了 Amazon Corretto 作为 JVM Vendor,这是一个经过深思熟虑的选择。不同的 JDK 发行版在性能、安全更新频率、LTS 支持策略等方面存在差异。

主流 JDK 发行版对比:

发行版维护者TCK 认证LTS 更新特点适用场景
Amazon CorrettoAmazon长期AWS 优化,免费AWS 环境、企业生产
Eclipse TemurinEclipse Foundation长期社区驱动,广泛使用通用场景
Azul ZuluAzul Systems长期性能优化高性能需求
Oracle JDKOracle付费 LTS官方发行版Oracle 生态
OpenJDK社区部分社区支持原始发行版开发测试
GraalVM CEOracle Labs社区支持AOT 编译云原生、微服务

CAS 7.3 选择 Amazon Corretto 的原因:

  1. AWS 生态兼容性:许多 CAS 部署在 AWS 上,Corretto 对 AWS 基础设施有针对性优化
  2. 免费 LTS 支持:Corretto 提供免费的长期支持更新,无需付费订阅
  3. 安全补丁及时:Amazon 承诺在关键安全漏洞发布后快速提供补丁
  4. 生产验证:Corretto 在 Amazon 内部大规模使用,经过了充分的生产验证
  5. 跨平台一致性:在 Linux、Windows、macOS 上提供一致的体验

JVM Vendor 配置方式:

groovy
// 方式一:使用 JvmVendorSpec 枚举(推荐)
java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
        vendor = JvmVendorSpec.AMAZON
    }
}

// 方式二:使用字符串匹配
java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
        vendor = JvmVendorSpec.matching("amazon")
    }
}

// 方式三:不指定 vendor(让 Gradle 自动选择)
java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
        // vendor 未指定,Gradle 会选择第一个可用的 JDK 21
    }
}

3.4 JvmVendorSpec 枚举兼容处理

JvmVendorSpec 是 Gradle 提供的 JVM 发行版枚举类,它在不同 Gradle 版本中的 API 存在差异。CAS 7.3 需要处理这种兼容性问题。

Gradle 版本间的 JvmVendorSpec 差异:

Gradle 7.x:
  JvmVendorSpec 是枚举类
  使用方式:JvmVendorSpec.AMAZON
  可用值:ADOPTIUM, AMAZON, APPLE, AZUL, GRAAL_VM, 
          MICROSOFT, ORACLE, SAP, ...

Gradle 8.x:
  JvmVendorSpec 仍然是枚举类
  新增:of(String) 工厂方法
  使用方式:JvmVendorSpec.AMAZON 或 JvmVendorSpec.of("AMAZON")

Gradle 9.x:
  JvmVendorSpec API 进一步优化
  推荐使用 matching(String) 方法
  使用方式:JvmVendorSpec.matching("AMAZON")

CAS 7.3 的兼容性处理:

groovy
// CAS 7.3 的兼容性写法 - 同时兼容 Gradle 7.x/8.x/9.x
java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
        
        // 方式一:直接使用枚举(最简单,兼容性最好)
        vendor = JvmVendorSpec.AMAZON
        
        // 方式二:使用 matching 方法(Gradle 8.3+)
        // vendor = JvmVendorSpec.matching("AMAZON")
    }
}

为什么 CAS 7.3 选择 JvmVendorSpec.AMAZON 而不是 JvmVendorSpec.of("AMAZON")

  1. 向后兼容JvmVendorSpec.AMAZON 在 Gradle 7.x 中就已经存在,确保了最大程度的兼容性
  2. 编译时安全:枚举值在编译时就会被验证,拼写错误会被立即发现
  3. IDE 支持:枚举值可以获得 IDE 的自动补全和文档提示
  4. 性能:枚举比较比字符串比较更高效

自定义 Vendor 匹配策略:

groovy
// 如果需要更灵活的 vendor 匹配
java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
        
        // 匹配所有基于 OpenJDK 的发行版
        vendor = JvmVendorSpec.matching(".*")
        
        // 或者匹配特定前缀
        // vendor = JvmVendorSpec.matching("AMAZON|ADOPTIUM")
    }
}

3.5 多 JDK 版本共存策略

在大型企业中,不同的项目可能需要不同的 JDK 版本。Foojay Toolchains 插件支持多 JDK 版本共存,每个项目可以声明自己需要的 JDK 版本。

多项目多 JDK 场景:

企业多项目 JDK 管理场景
═══════════════════════════════════════════════════════════

  ~/.gradle/jdks/
  ├── amazon_corretto-21.0.2/
  │   └── (CAS 7.3 使用)
  ├── eclipse_temurin-17.0.9/
  │   └── (其他 Spring Boot 3.x 项目使用)
  ├── amazon_corretto-11.0.21/
  │   └── (遗留项目使用)
  └── azul_zulu-8.0.392/
      └── (老旧项目使用)

  项目 A (CAS 7.3):
    toolchain { languageVersion = 21; vendor = AMAZON }
    → 使用 amazon_corretto-21.0.2

  项目 B (Spring Boot 3.2):
    toolchain { languageVersion = 17; vendor = ADOPTIUM }
    → 使用 eclipse_temurin-17.0.9

  项目 C (遗留系统):
    toolchain { languageVersion = 11; vendor = AMAZON }
    → 使用 amazon_corretto-11.0.21

测试多 JDK 版本兼容性:

CAS 7.3 的构建脚本可以配置为在多个 JDK 版本下运行测试:

groovy
// build.gradle - 多 JDK 版本测试配置
testing {
    suites {
        // 主测试套件使用 JDK 21
        test {
            useJUnitPlatform()
            java {
                toolchain {
                    languageVersion = JavaLanguageVersion.of(21)
                    vendor = JvmVendorSpec.AMAZON
                }
            }
        }
        
        // 集成测试套件使用 JDK 21
        integrationTest(JvmTestSuite) {
            useJUnitPlatform()
            java {
                toolchain {
                    languageVersion = JavaLanguageVersion.of(21)
                    vendor = JvmVendorSpec.AMAZON
                }
            }
        }
    }
}

JDK 磁盘空间管理:

Foojay 下载的 JDK 会存储在 ~/.gradle/jdks/ 目录下。每个 JDK 大约 300-500MB,如果项目多,磁盘占用可能较大。可以通过以下方式管理:

bash
# 查看已下载的 JDK
ls -la ~/.gradle/jdks/

# 清理不再使用的 JDK
rm -rf ~/.gradle/jdks/amazon_corretto-11.0.21/

# 通过 Gradle 命令清理
./gradlew --stop
# 然后手动清理 ~/.gradle/jdks/ 中的旧版本

第四章 CycloneDX SBOM 生成

4.1 SBOM 概念与合规要求

SBOM(Software Bill of Materials,软件物料清单)是软件组件的详细清单,类似于食品包装上的成分表。它记录了软件中包含的所有第三方库、框架、工具及其版本信息。

SBOM 的核心价值:

SBOM 在软件供应链安全中的位置
═══════════════════════════════════════════════════════════

  软件供应链安全层次模型:

  ┌─────────────────────────────────────────┐
  │         合规与审计层                      │
  │  EO 14028 / EU CRA / NIST SP 800-218   │
  └────────────────┬────────────────────────┘
                   │ 要求

  ┌─────────────────────────────────────────┐
  │         SBOM 生成层                      │
  │  CycloneDX / SPDX / SWID               │
  └────────────────┬────────────────────────┘
                   │ 依赖

  ┌─────────────────────────────────────────┐
  │         构建工具层                        │
  │  Gradle / Maven / npm / pip            │
  └────────────────┬────────────────────────┘
                   │ 分析

  ┌─────────────────────────────────────────┐
  │         依赖解析层                        │
  │  依赖树 / 传递依赖 / 版本冲突            │
  └─────────────────────────────────────────┘

SBOM 相关法规要求:

法规/标准适用范围SBOM 要求生效时间
EO 14028美国联邦政府供应商必须提供 SBOM2022-2024 分阶段
EU Cyber Resilience Act欧盟市场所有联网产品强制 SBOM2027 年全面生效
NIST SP 800-218美国联邦机构SSDF 框架包含 SBOM已发布
SLSA Framework开源项目供应链完整性证明持续演进
Executive Order 14017美国关键基础设施供应链风险评估已签署

SBOM 标准对比:

标准维护者格式优势CAS 选择
CycloneDXOWASPJSON/XML轻量、专注安全、生态丰富✅ 采用
SPDXLinux FoundationJSON/XML/RDF许可证分析强未采用
SWIDISO/IECXML企业级标识未采用

CAS 7.3 选择 CycloneDX 的原因:

  1. OWASP 背书:CycloneDX 是 OWASP(开放 Web 应用安全项目)的旗舰项目
  2. Gradle 插件成熟org.cyclonedx.bom 插件功能完善,与 Gradle 9.x 兼容
  3. VEX 支持:支持 VEX(Vulnerability Exploitability eXchange),可以标记已知漏洞的处置状态
  4. 轻量高效:生成的 SBOM 文件体积小,解析速度快
  5. 工具链完整:有丰富的 SBOM 分析工具(如 Dependency-Track、Grype 等)

4.2 CycloneDX Gradle 插件配置

CAS 7.3 使用 org.cyclonedx.bom 插件生成 SBOM。以下是详细的配置说明。

插件声明:

groovy
// build.gradle
plugins {
    id 'org.cyclonedx.bom' version '1.10.0'
}

完整配置:

groovy
// CAS 7.3 CycloneDX 配置(教学简化版)
cyclonedxBom {
    // 包含的配置(即哪些依赖会被纳入 SBOM)
    includeConfigs = ['runtimeClasspath', 'compileClasspath']
    
    // 排除的配置
    excludeConfigs = ['testRuntimeClasspath', 'testCompileClasspath']
    
    // 排除的 Group ID
    excludeGroups = ['org.apereo.cas.test']
    
    // Schema 版本
    schemaVersion = '1.5'
    
    // 输出格式
    outputFormat = 'json'
    
    // 输出目录
    destination = file("build/reports/cyclonedx")
    
    // 输出文件名
    outputName = 'cas-sbom'
    
    // 包含项目信息
    includeProjectBuildFile = true
    
    // 包含 License 信息
    includeLicenseText = false
    
    // 跳过子项目(在多项目构建中)
    skipProjects = []
}

配置项详解:

  1. includeConfigs:指定哪些依赖配置会被纳入 SBOM 分析。CAS 7.3 只包含 runtimeClasspathcompileClasspath,排除了测试依赖。这是因为 SBOM 主要用于生产环境的安全审计,测试依赖不应纳入。

  2. schemaVersion:CycloneDX 规范版本。1.5 是目前最新的稳定版本,支持 VEX(漏洞可利用性交换)、服务组件、VCS 信息等高级特性。

  3. outputFormat:输出格式支持 jsonxmlall。JSON 格式更易于机器处理,XML 格式更易于人工阅读。

  4. destination:SBOM 文件的输出目录。CAS 7.3 将其放在 build/reports/cyclonedx/ 下,与测试报告等构建产物放在一起。

运行 SBOM 生成:

bash
# 生成 SBOM
./gradlew cyclonedxBom

# 输出文件
# build/reports/cyclonedx/cas-sbom.json

与构建流程集成:

groovy
// 将 SBOM 生成集成到构建流程中
tasks.named('build') {
    // build 任务依赖于 cyclonedxBom
    dependsOn 'cyclonedxBom'
}

// 或者创建专门的 CI 任务
tasks.register('ciBuild') {
    dependsOn 'build'
    dependsOn 'cyclonedxBom'
    // 可以添加更多 CI 相关的任务
}

4.3 SBOM 报告内容解析

CycloneDX 生成的 SBOM 是一个 JSON 文件,包含了项目的完整依赖信息。以下是 CAS 7.3 SBOM 的典型内容结构。

SBOM 文件结构:

json
{
  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
  "bomFormat": "CycloneDX",
  "specVersion": "1.5",
  "serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
  "version": 1,
  "metadata": {
    "timestamp": "2025-01-15T10:30:00Z",
    "tools": [
      {
        "vendor": "CycloneDX",
        "name": "cyclonedx-gradle-plugin",
        "version": "1.10.0"
      }
    ],
    "component": {
      "group": "org.apereo.cas",
      "name": "cas-overlay",
      "version": "7.3.0",
      "type": "application",
      "purl": "pkg:maven/org.apereo.cas/cas-overlay@7.3.0",
      "properties": [
        {
          "name": "cdx:gradle:project:version",
          "value": "7.3.0"
        }
      ]
    }
  },
  "components": [
    {
      "group": "org.apereo.cas",
      "name": "cas-server-core-api",
      "version": "7.3.0",
      "type": "library",
      "purl": "pkg:maven/org.apereo.cas/cas-server-core-api@7.3.0",
      "licenses": [
        {
          "id": "Apache-2.0"
        }
      ]
    },
    {
      "group": "org.mybatis",
      "name": "mybatis",
      "version": "3.5.16",
      "type": "library",
      "purl": "pkg:maven/org.mybatis/mybatis@3.5.16",
      "licenses": [
        {
          "id": "Apache-2.0"
        }
      ]
    },
    {
      "group": "org.apache.commons",
      "name": "commons-dbcp2",
      "version": "2.10.0",
      "type": "library",
      "purl": "pkg:maven/org.apache.commons/commons-dbcp2@2.10.0",
      "licenses": [
        {
          "id": "Apache-2.0"
        }
      ]
    }
  ],
  "dependencies": [
    {
      "ref": "pkg:maven/org.apereo.cas/cas-overlay@7.3.0",
      "dependsOn": [
        "pkg:maven/org.apereo.cas/cas-server-core-api@7.3.0",
        "pkg:maven/org.mybatis/mybatis@3.5.16",
        "pkg:maven/org.apache.commons/commons-dbcp2@2.10.0"
      ]
    }
  ]
}

SBOM 关键字段解析:

字段说明示例
bomFormatBOM 格式标识CycloneDX
specVersionCycloneDX 规范版本1.5
serialNumber唯一序列号urn:uuid:...
metadata.timestamp生成时间ISO 8601 格式
metadata.component主组件信息CAS overlay 项目
components[]依赖组件列表所有第三方库
components[].purl包 URL(Package URL)pkg:maven/...
components[].licenses许可证信息Apache-2.0
dependencies[]依赖关系图组件间的依赖关系

Package URL (purl) 格式说明:

purl 格式:pkg:<type>/<namespace>/<name>@<version>

CAS 7.3 中的 purl 示例:
  pkg:maven/org.apereo.cas/cas-server-core-api@7.3.0
  pkg:maven/org.mybatis/mybatis@3.5.16
  pkg:maven/org.apache.commons/commons-dbcp2@2.10.0
  pkg:maven/org.webjars/bootstrap@5.3.3
  pkg:maven/org.webjars.npm/material-components-web@14.0.0

4.4 生产环境 SBOM 管理

SBOM 生成只是软件供应链安全的第一步,更重要的是在生产环境中管理和使用 SBOM。

SBOM 生命周期管理:

SBOM 生命周期
═══════════════════════════════════════════════════════════

  1. 生成(Generate)

     ├── 构建时自动生成(CycloneDX Gradle 插件)
     ├── 包含在构建产物中
     └── 版本与构建产物绑定


  2. 存储(Store)

     ├── 与 Docker 镜像一起推送到仓库
     ├── 上传到 SBOM 管理平台(Dependency-Track)
     └── 归档到制品库(Nexus/Artifactory)


  3. 分析(Analyze)

     ├── 漏洞扫描(Grype/Trivy)
     ├── 许可证合规检查
     └── 依赖风险评估


  4. 响应(Respond)

     ├── 漏洞修复优先级排序
     ├── VEX(漏洞可利用性交换)发布
     └── 升级依赖版本


  5. 审计(Audit)

     ├── 定期 SBOM 合规审计
     ├── 供应链安全报告
     └── 监管合规证明

SBOM 与 Docker 镜像集成:

dockerfile
# CAS 7.3 Dockerfile - SBOM 集成
FROM azul/zulu-openjdk:21 AS builder
WORKDIR /app
COPY . .

# 生成 SBOM
RUN ./gradlew cyclonedxBom --no-daemon

# 构建应用
RUN ./gradlew build -x test --no-daemon

FROM azul/zulu-openjdk:21
WORKDIR /app

# 复制应用
COPY --from=builder /app/build/libs/*.war /app/cas.war

# 复制 SBOM(重要!)
COPY --from=builder /app/build/reports/cyclonedx/cas-sbom.json /app/sbom.json

# 添加 SBOM 标签(OCI 标准)
LABEL org.opencontainers.image.title="CAS 7.3"
LABEL org.opencontainers.image.version="7.3.0"
LABEL io.cyclonedx.version="1.5"

EXPOSE 8443 8080
ENTRYPOINT ["java", "-jar", "/app/cas.war"]

SBOM 漏洞扫描集成:

bash
# 使用 Grype 扫描 SBOM 中的漏洞
grype sbom:build/reports/cyclonedx/cas-sbom.json

# 使用 Trivy 扫描
trivy sbom build/reports/cyclonedx/cas-sbom.json

# 使用 Dependency-Track 进行持续监控
# 将 SBOM 上传到 Dependency-Track API
curl -X POST "https://dependency-track.example.com/api/v1/bom" \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: multipart/form-data" \
  -F "project=CAS-7.3" \
  -F "bom=@build/reports/cyclonedx/cas-sbom.json"

CI/CD 中的 SBOM 流水线:

yaml
# GitLab CI/CD 示例 - SBOM 集成
stages:
  - build
  - sbom-scan
  - deploy

build:
  stage: build
  script:
    - ./gradlew build cyclonedxBom
  artifacts:
    paths:
      - build/reports/cyclonedx/
      - build/libs/

sbom-scan:
  stage: sbom-scan
  needs: [build]
  script:
    - grype sbom:build/reports/cyclonedx/cas-sbom.json --fail-on critical
  allow_failure: false

deploy:
  stage: deploy
  needs: [sbom-scan]
  script:
    - docker build -t cas:7.3 .
    - docker push your-registry/cas:7.3

第五章 Jib 多平台 Docker 镜像构建

5.1 Jib 插件核心概念

Jib 是 Google 开源的 Java 容器化工具,它可以将 Java 应用直接构建为 OCI 兼容的 Docker 镜像,无需 Docker daemon、无需编写 Dockerfile、无需了解 Docker 最佳实践。

传统 Docker 构建的问题:

传统 Docker 构建流程
═══════════════════════════════════════════════════════════

  开发者机器 / CI Runner
  ┌─────────────────────────────────────────┐
  │                                         │
  │  1. 编译 Java 代码                       │
  │  2. 运行测试                             │
  │  3. 编写 Dockerfile                      │
  │  4. 安装 Docker daemon                   │
  │  5. docker build .                       │
  │     ├── 启动 Docker daemon               │
  │     ├── 复制源代码到 Docker context       │
  │     ├── 在容器内编译(或复制编译结果)     │
  │     ├── 安装依赖                         │
  │     └── 生成镜像层                       │
  │  6. docker push                          │
  │                                         │
  │  问题:                                  │
  │  ❌ 需要 Docker daemon(安全风险)        │
  │  ❌ 需要 Dockerfile(维护成本)           │
  │  ❌ 需要了解 Docker 最佳实践              │
  │  ❌ 多平台构建复杂                        │
  │  ❌ 层缓存策略需要手动优化                │
  │                                         │
  └─────────────────────────────────────────┘

Jib 的解决方案:

Jib 构建流程
═══════════════════════════════════════════════════════════

  开发者机器 / CI Runner
  ┌─────────────────────────────────────────┐
  │                                         │
  │  1. ./gradlew jib                       │
  │     ├── 分析 Java classpath              │
  │     ├── 分层打包依赖                     │
  │     │   ├── 层1: 基础镜像               │
  │     │   ├── 层2: 依赖 JAR               │
  │     │   ├── 层3: 应用资源               │
  │     │   └── 层4: 应用 classes           │
  │     ├── 直接推送到容器仓库               │
  │     └── 无需 Docker daemon               │
  │                                         │
  │  优势:                                  │
  │  ✅ 无需 Docker daemon                   │
  │  ✅ 无需 Dockerfile                      │
  │  ✅ 自动分层和缓存                       │
  │  ✅ 原生多平台支持                       │
  │  ✅ 可重现构建                           │
  │  ✅ 与 Gradle 深度集成                   │
  │                                         │
  └─────────────────────────────────────────┘

Jib 的镜像层结构:

Jib 自动生成的镜像层
═══════════════════════════════════════════════════════════

  ┌─────────────────────────────────┐
  │  层4: Application Classes       │  ← 变化最频繁
  │  (编译后的 .class 文件)          │     每次代码修改都会变化
  ├─────────────────────────────────┤
  │  层3: Application Resources     │  ← 变化较少
  │  (配置文件、静态资源)             │     配置修改时才变化
  ├─────────────────────────────────┤
  │  层2: Dependencies              │  ← 变化最少
  │  (第三方 JAR 包)                │     依赖版本变更时才变化
  │  (MyBatis, DBCP2, Spring...)   │     可跨项目共享缓存
  ├─────────────────────────────────┤
  │  层1: Base Image                │  ← 几乎不变
  │  (azul/zulu-openjdk:21)        │     只在基础镜像更新时变化
  └─────────────────────────────────┘

  缓存优势:
  - 修改代码 → 只重建层4(快速!)
  - 修改配置 → 重建层3+层4
  - 升级依赖 → 重建层2+层3+层4
  - 更换基础镜像 → 全部重建

5.2 多平台镜像构建配置

CAS 7.3 使用 Jib 3.5.3 构建多平台 Docker 镜像,同时支持 amd64(x86_64)和 arm64(AArch64)架构。

完整 Jib 配置:

groovy
// CAS 7.3 Jib 配置(教学简化版)
jib {
    from {
        // 基础镜像
        image = 'azul/zulu-openjdk:21'
        // 可以指定凭据(如果基础镜像是私有仓库)
        // credHelper = 'ecr-login'
    }
    
    to {
        // 目标镜像仓库
        image = "your-registry.example.com/cas:${project.version}"
        // 镜像标签
        tags = [
            "latest",
            "jdk21",
            project.version.toString()
        ]
        // 可以指定凭据
        credHelper = 'ecr-login'  // AWS ECR
        // 或者使用用户名密码
        // auth {
        //     username = project.findProperty('registryUser')
        //     password = project.findProperty('registryPassword')
        // }
    }
    
    // 多平台配置
    platforms {
        platform {
            architecture = 'amd64'
            os = 'linux'
        }
        platform {
            architecture = 'arm64'
            os = 'linux'
        }
    }
    
    // 容器配置
    container {
        // JVM 参数
        jvmFlags = [
            '-Xms512m',
            '-Xmx2048m',
            '-XX:+UseG1GC',
            '-Dcas.serviceRegistry.watcherEnabled=false',
            '-Djava.security.egd=file:/dev/./urandom'
        ]
        
        // 环境变量
        environment = [
            'CAS_SERVER_VERSION': project.version.toString(),
            'SPRING_PROFILES_ACTIVE': 'production'
        ]
        
        // 端口
        ports = ['8443', '8080']
        
        // 入口点
        mainClass = 'org.apereo.cas.web.CasWebApplication'
        
        // 创建时间(UTC)
        creationTime = 'USE_CURRENT_TIMESTAMP'
        
        // 用户
        user = '1001:1001'
        
        // 工作目录
        workingDirectory = '/app'
    }
    
    // 构建优化
    containerizingMode = 'packaged'  // 使用已打包的 WAR 文件
    
    // 输出到本地 Docker daemon(用于测试)
    // dockerClient {
    //     executable = '/usr/bin/docker'
    // }
}

多平台构建原理:

Jib 多平台构建流程
═══════════════════════════════════════════════════════════

  ./gradlew jib

  ┌──────────────────────────────────────────────────┐
  │                    Jib 构建引擎                    │
  │                                                    │
  │  1. 分析 Java classpath(与平台无关)               │
  │     ├── 解析依赖 JAR                               │
  │     ├── 收集应用 classes                           │
  │     └── 收集应用资源                               │
  │                                                    │
  │  2. 为每个平台构建镜像层                            │
  │     ├── amd64/linux                                │
  │     │   ├── 拉取 azul/zulu-openjdk:21 (amd64)     │
  │     │   ├── 添加依赖层                             │
  │     │   ├── 添加资源层                             │
  │     │   └── 添加应用层                             │
  │     │                                              │
  │     └── arm64/linux                                │
  │         ├── 拉取 azul/zulu-openjdk:21 (arm64)     │
  │         ├── 添加依赖层                             │
  │         ├── 添加资源层                             │
  │         └── 添加应用层                             │
  │                                                    │
  │  3. 推送到容器仓库                                  │
  │     ├── 推送 amd64 manifest                        │
  │     ├── 推送 arm64 manifest                        │
  │     └── 创建/更新多架构 manifest list               │
  │                                                    │
  └──────────────────────────────────────────────────┘

  容器仓库中的存储结构:
  your-registry/cas:7.3.0
  ├── manifest list (多架构索引)
  │   ├── amd64 manifest → 指向 amd64 层
  │   └── arm64 manifest → 指向 arm64 层
  ├── amd64 层
  │   ├── base layer (azul/zulu-openjdk:21 amd64)
  │   ├── dependencies layer
  │   ├── resources layer
  │   └── application layer
  └── arm64 层
      ├── base layer (azul/zulu-openjdk:21 arm64)
      ├── dependencies layer
      ├── resources layer
      └── application layer

常用 Jib 命令:

bash
# 构建并推送到远程仓库
./gradlew jib

# 构建到本地 Docker daemon
./gradlew jibDockerBuild

# 构建到本地 tar 文件
./gradlew jibBuildTar

# 跳过 Jib 构建
./gradlew build -x jib

# 指定目标镜像
./gradlew jib -Djib.to.image=your-registry/cas:7.3.0

# 指定额外的标签
./gradlew jib -Djib.to.tags=latest,jdk21,production

5.3 基础镜像选择策略

CAS 7.3 选择 azul/zulu-openjdk:21 作为基础镜像。基础镜像的选择对容器的安全性、性能和体积都有重要影响。

主流 JDK 21 Docker 镜像对比:

镜像维护者大小 (JRE)TCK 认证特点
azul/zulu-openjdk:21Azul Systems~200MB性能优化,多架构
eclipse-temurin:21-jreEclipse Foundation~190MB社区标准
amazoncorretto:21Amazon~195MBAWS 优化
graalvm/jdk:21Oracle Labs~350MBAOT 编译支持
openjdk:21-jdk-slimDocker Library~220MB部分官方社区版

CAS 7.3 选择 Azul Zulu 的原因:

  1. 多架构支持完善:Azul Zulu 提供了高质量的 amd64 和 arm64 镜像,与 Jib 的多平台构建完美配合
  2. 性能优化:Azul 在 JVM 性能优化方面有深厚积累,Zulu JDK 在多项基准测试中表现优异
  3. TCK 认证:通过完整的 TCK 认证,保证了与 Java 规范的完全兼容
  4. 安全更新及时:Azul 承诺在关键安全漏洞发布后快速提供更新
  5. 镜像体积合理:Zulu 的 JRE 镜像体积适中,不会过度膨胀容器

基础镜像版本固定策略:

groovy
// ❌ 不推荐:使用 latest 标签
jib {
    from {
        image = 'azul/zulu-openjdk:21'  // 可能指向不同版本
    }
}

// ✅ 推荐:使用具体版本
jib {
    from {
        image = 'azul/zulu-openjdk-alpine:21.0.2-21.0.2+13'
    }
}

// ✅ 更好:使用 digest(完全确定性)
jib {
    from {
        image = 'azul/zulu-openjdk-alpine@sha256:abc123...'
    }
}

5.4 镜像层优化与缓存

Jib 的分层策略是其核心优势之一。理解层优化原理可以帮助我们最大化构建缓存命中率。

依赖层分离策略:

groovy
// Jib 默认的分层策略
jib {
    container {
        // 默认分层:
        // 层1: 基础镜像
        // 层2: 所有依赖 JAR(snapshot 和 release 混在一起)
        // 层3: 应用资源
        // 层4: 应用 classes
        
        // 可以通过 extraDirectories 添加额外文件
        extraDirectories {
            paths = [
                file('src/main/docker')  // Docker 特定配置文件
            ]
            permissions = [
                '/app/entrypoint.sh': '755'
            ]
        }
    }
}

缓存命中率优化技巧:

缓存命中率优化策略
═══════════════════════════════════════════════════════════

  场景1:日常开发(只修改 Java 代码)
  ├── 层1 命中缓存 ✅
  ├── 层2 命中缓存 ✅
  ├── 层3 命中缓存 ✅
  └── 层4 重建 ⏳(只有这一层需要重建)
  → 构建时间:~10-20 秒

  场景2:修改配置文件
  ├── 层1 命中缓存 ✅
  ├── 层2 命中缓存 ✅
  ├── 层3 重建 ⏳
  └── 层4 重建 ⏳
  → 构建时间:~20-30 秒

  场景3:升级依赖版本
  ├── 层1 命中缓存 ✅
  ├── 层2 重建 ⏳
  ├── 层3 重建 ⏳
  └── 层4 重建 ⏳
  → 构建时间:~30-60 秒

  场景4:更换基础镜像
  ├── 层1 重建 ⏳
  ├── 层2 重建 ⏳
  ├── 层3 重建 ⏳
  └── 层4 重建 ⏳
  → 构建时间:~2-5 分钟

Jib 与传统 Dockerfile 构建的性能对比:

维度JibDockerfile
首次构建~2-3 分钟~3-5 分钟
代码修改重建~10-20 秒~30-60 秒
依赖升级重建~30-60 秒~1-3 分钟
多平台构建原生支持需要 buildx
Docker daemon不需要必需
构建可重现性高(确定性层内容)中(依赖构建上下文)

第六章 Docker 多阶段构建 JDK 21 适配

6.1 基础镜像选择:azul/zulu-openjdk:21

虽然 CAS 7.3 推荐使用 Jib 进行容器化构建,但在某些场景下(如需要自定义 entrypoint、集成非 Java 文件等),传统的 Dockerfile 多阶段构建仍然是必要的。

CAS 7.3 Docker 多阶段构建配置:

dockerfile
# CAS 7.3 Dockerfile(教学简化版)
# ============================================
# 阶段1:构建阶段
# ============================================
FROM azul/zulu-openjdk:21 AS builder

# 安装必要工具
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
    curl \
    unzip \
    && rm -rf /var/lib/apt/lists/*

# 设置工作目录
WORKDIR /app

# 复制 Gradle Wrapper 和配置
COPY gradle/ gradle/
COPY gradlew build.gradle settings.gradle ./

# 使用 Gradle Wrapper 构建(Foojay 会自动下载 JDK 21)
RUN chmod +x gradlew && \
    ./gradlew dependencies --no-daemon || true

# 复制源代码
COPY src/ src/

# 执行构建
RUN ./gradlew build -x test --no-daemon

# ============================================
# 阶段2:运行时阶段
# ============================================
FROM azul/zulu-openjdk-alpine:21

# 创建非 root 用户
RUN addgroup -S cas && adduser -S cas -G cas

# 设置工作目录
WORKDIR /app

# 复制构建产物
COPY --from=builder /app/build/libs/cas.war /app/cas.war

# 复制 entrypoint 脚本
COPY src/main/docker/entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh

# 复制 SBOM
COPY --from=builder /app/build/reports/cyclonedx/cas-sbom.json /app/sbom.json

# 设置环境变量
ENV JAVA_OPTS="-Xms512m -Xmx2048m -XX:+UseG1GC" \
    CAS_SERVER_VERSION="7.3.0" \
    TZ=Asia/Shanghai

# 切换到非 root 用户
USER cas

# 暴露端口
EXPOSE 8443 8080

# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
    CMD curl -f http://localhost:8080/cas/status || exit 1

# 入口点
ENTRYPOINT ["/app/entrypoint.sh"]

基础镜像选择对比:

JDK 21 Docker 基础镜像选择决策树
═══════════════════════════════════════════════════════════

  需要最小镜像体积?
  ├── 是 → 使用 Alpine 版本
  │   ├── azul/zulu-openjdk-alpine:21 (~170MB)
  │   └── 注意:Alpine 使用 musl libc,可能有兼容性问题

  └── 否 → 使用标准版本
      ├── azul/zulu-openjdk:21 (~220MB) ← CAS 7.3 选择
      ├── eclipse-temurin:21 (~215MB)
      └── amazoncorretto:21 (~210MB)

  需要完整 JDK(不只是 JRE)?
  ├── 是 → 使用 JDK 镜像
  │   └── 用于构建阶段或需要 JDK 工具的场景

  └── 否 → 使用 JRE 镜像(推荐用于生产)
      └── 减少攻击面,减小镜像体积

6.2 entrypoint.sh JDK 21 兼容修改

CAS 的 entrypoint.sh 脚本是容器启动的关键文件。从 JDK 11 升级到 JDK 21 后,需要对脚本进行多项兼容性修改。

CAS 5.3/6.6 的 entrypoint.sh(旧版):

bash
#!/bin/sh
# CAS 5.3/6.6 entrypoint.sh(简化版)

# 旧版 JVM 参数
JAVA_OPTS="${JAVA_OPTS} -noverify"           # ❌ JDK 21 中已废弃
JAVA_OPTS="${JAVA_OPTS} -Xdebug"             # ❌ JDK 21 中已废弃
JAVA_OPTS="${JAVA_OPTS} -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=*:5005"

# 启动 CAS
exec java ${JAVA_OPTS} \
    -jar /app/cas.war \
    --spring.profiles.active=${SPRING_PROFILES_ACTIVE:-default}

CAS 7.3 的 entrypoint.sh(新版):

bash
#!/bin/sh
# CAS 7.3 entrypoint.sh(教学简化版)
set -e

# ============================================
# JVM 参数配置
# ============================================

# 内存配置
JAVA_OPTS="${JAVA_OPTS:-} -Xms512m -Xmx2048m"

# GC 配置 - 使用 G1GC(Java 21 默认)
JAVA_OPTS="${JAVA_OPTS} -XX:+UseG1GC"
JAVA_OPTS="${JAVA_OPTS} -XX:MaxGCPauseMillis=200"
JAVA_OPTS="${JAVA_OPTS} -XX:G1HeapRegionSize=8m"

# ✅ 移除 -noverify(JDK 21 中已废弃,默认行为已改变)
# ❌ JAVA_OPTS="${JAVA_OPTS} -noverify"

# ✅ 使用 -agentlib:jdwp 替代 -Xdebug + -Xrunjdwp
if [ "${ENABLE_DEBUG}" = "true" ]; then
    JAVA_OPTS="${JAVA_OPTS} -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005"
fi

# ============================================
# CAS 特定配置
# ============================================

# 禁用 WatcherService(容器环境中不需要文件系统监听)
JAVA_OPTS="${JAVA_OPTS} -Dcas.serviceRegistry.watcherEnabled=false"

# 时区设置
JAVA_OPTS="${JAVA_OPTS} -Duser.timezone=${TZ:-Asia/Shanghai}"

# 随机数生成器优化(容器环境中 /dev/random 可能阻塞)
JAVA_OPTS="${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom"

# ============================================
# 健康检查与就绪探针
# ============================================

# 等待数据库就绪(如果配置了数据库)
# wait-for-it.sh ${DB_HOST}:${DB_PORT} --timeout=30 --strict

# ============================================
# 启动 CAS
# ============================================

echo "============================================"
echo "Starting CAS ${CAS_SERVER_VERSION:-7.3.0}"
echo "Java Version: $(java -version 2>&1 | head -1)"
echo "JVM Options: ${JAVA_OPTS}"
echo "Spring Profiles: ${SPRING_PROFILES_ACTIVE:-default}"
echo "============================================"

exec java ${JAVA_OPTS} \
    -jar /app/cas.war \
    --spring.profiles.active="${SPRING_PROFILES_ACTIVE:-default}" \
    --cas.server.prefix="${CAS_SERVER_PREFIX:-https://localhost:8443/cas}" \
    --cas.server.name="${CAS_SERVER_NAME:-https://localhost:8443}"

entrypoint.sh 关键变更详解:

旧参数新参数变更原因
-noverify移除JDK 13+ 中 -noverify 已被废弃,JDK 17+ 中默认不进行字节码验证优化
-Xdebug移除JDK 21 中 -Xdebug 已被废弃
-Xrunjdwp:...-agentlib:jdwp:...JDWP 调试参数格式更新
-Dcas.serviceRegistry.watcherEnabled=false容器环境中禁用文件系统监听
-Djava.security.egd=file:/dev/./urandom优化容器环境中的随机数生成

6.3 JVM 参数调整

JDK 21 对 JVM 参数进行了大量优化和调整。CAS 7.3 的 JVM 参数配置需要针对 JDK 21 的特性进行优化。

JDK 21 推荐的 JVM 参数:

bash
# CAS 7.3 生产环境推荐 JVM 参数
JAVA_OPTS="-Xms2g -Xmx2g \                    # 堆大小(建议初始和最大相同)
  -XX:+UseG1GC \                               # 使用 G1 垃圾收集器(JDK 21 默认)
  -XX:MaxGCPauseMillis=200 \                   # 最大 GC 停顿时间目标
  -XX:G1HeapRegionSize=8m \                    # G1 区域大小
  -XX:+UseStringDeduplication \                # 字符串去重(节省内存)
  -XX:+UseCompressedOops \                     # 压缩普通对象指针(64位系统)
  -XX:+UseCompressedClassPointers \            # 压缩类指针
  -XX:+OptimizeStringConcat \                  # 字符串连接优化
  -Djdk.httpclient.HttpClient.log=errors \     # HTTP Client 日志级别
  -Djava.security.egd=file:/dev/./urandom \    # 随机数生成器
  -Dcas.serviceRegistry.watcherEnabled=false \ # 禁用 WatcherService
  -Dfile.encoding=UTF-8 \                      # 文件编码
  -Duser.timezone=Asia/Shanghai"               # 时区

JDK 21 的 GC 选择指南:

JDK 21 垃圾收集器选择决策树
═══════════════════════════════════════════════════════════

  你的应用特征是什么?

  ├── 低延迟优先(SSO 认证场景)
  │   ├── 堆大小 < 4GB → ZGC(推荐)
  │   │   -XX:+UseZGC
  │   │   -XX:+ZGenerational  # JDK 21 的分代 ZGC
  │   │
  │   └── 堆大小 >= 4GB → ZGC 或 Shenandoah
  │       -XX:+UseZGC -XX:+ZGenerational

  ├── 吞吐量优先(后台处理场景)
  │   └── Parallel GC
  │       -XX:+UseParallelGC

  └── 平衡模式(CAS 推荐默认选择)
      └── G1GC(JDK 21 默认)
          -XX:+UseG1GC
          -XX:MaxGCPauseMillis=200

  CAS 7.3 推荐:G1GC
  原因:
  1. CAS 是 Web 应用,需要平衡延迟和吞吐量
  2. G1GC 是 JDK 21 的默认 GC,经过充分优化
  3. G1GC 的可预测停顿时间适合 SSO 认证场景
  4. 分代 ZGC 虽然在 JDK 21 中可用,但 G1GC 更成熟

JDK 21 新特性对 CAS 的影响:

JDK 21 特性对 CAS 的影响配置建议
Virtual Threads (JEP 444)Spring Boot 3.5.6 可以利用虚拟线程提升并发性能-Djdk.virtualThreadScheduler.parallelism=200
Generational ZGC (JEP 439)低延迟场景的备选 GC-XX:+UseZGC -XX:+ZGenerational
Record Patterns (JEP 440)CAS 内部代码可以使用模式匹配简化逻辑无需 JVM 参数
String Templates (JEP 430)预览特性,暂不建议在生产环境使用-XX:+EnablePreview(不推荐)
Sequenced Collections (JEP 431)CAS 内部代码可以使用新的集合接口无需 JVM 参数

6.4 WatcherService 禁用与服务注册

CAS 使用 WatcherService 来监听文件系统变化,实现服务注册表的动态更新。但在容器环境中,这种机制不仅没有必要,还可能导致问题。

WatcherService 的问题:

WatcherService 在容器环境中的问题
═══════════════════════════════════════════════════════════

  容器环境特点:
  ├── 文件系统是只读层(overlay2)
  ├── 配置文件通过环境变量或 ConfigMap 注入
  ├── 不需要监听文件系统变化
  └── WatcherService 可能消耗不必要的资源

  WatcherService 的潜在问题:
  ├── 1. inotify watch 限制
  │   Linux 默认限制每个用户最多 8192 个 inotify watch
  │   CAS 的 WatcherService 可能消耗大量 watch
  │   → 导致 "too many open files" 错误

  ├── 2. 性能影响
  │   WatcherService 会创建后台线程轮询文件变化
  │   在高负载场景下可能影响性能

  └── 3. 安全风险
      WatcherService 需要文件系统访问权限
      在安全加固的容器中可能被拒绝

  解决方案:
  -Dcas.serviceRegistry.watcherEnabled=false
  ✅ 禁用 WatcherService
  ✅ 减少资源消耗
  ✅ 避免潜在的文件系统问题

CAS 服务注册在容器环境中的替代方案:

yaml
# application.yml - CAS 7.3 容器环境服务注册配置
cas:
  service-registry:
    # 禁用 WatcherService
    watcher-enabled: false
    
    # 使用 JSON 文件服务注册(推荐用于容器环境)
    json:
      location: file:/app/services/*.json
      
    # 或者使用数据库服务注册
    # jdbc:
    #   driver-class: org.postgresql.Driver
    #   url: jdbc:postgresql://db:5432/cas_services
    #   user: cas
    #   password: ${DB_PASSWORD}
    #   ddl-auto: create-drop
    
    # 定时刷新服务注册表(替代 WatcherService)
    reload-interval: PT5M  # 每 5 分钟刷新一次

完整的容器环境 JVM 参数配置:

bash
# CAS 7.3 容器环境完整 JVM 参数
JAVA_OPTS="\
  # 内存配置
  -Xms2g -Xmx2g \
  -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m \
  -XX:ReservedCodeCacheSize=128m \
  
  # GC 配置
  -XX:+UseG1GC \
  -XX:MaxGCPauseMillis=200 \
  -XX:G1HeapRegionSize=8m \
  -XX:+UseStringDeduplication \
  
  # 容器环境适配
  -Dcas.serviceRegistry.watcherEnabled=false \
  -Djava.security.egd=file:/dev/./urandom \
  -Dfile.encoding=UTF-8 \
  -Duser.timezone=Asia/Shanghai \
  
  # 日志配置
  -Dlogging.config=file:/app/config/logback.xml \
  -Dlogback.configurationFile=file:/app/config/logback.xml \
  
  # 网络配置
  -Dserver.port=8443 \
  -Dserver.ssl.enabled=true \
  -Dcas.server.prefix=https://cas.example.com/cas \
  -Dcas.server.name=https://cas.example.com \
  
  # 健康检查
  -Dmanagement.endpoints.web.exposure.include=health,info,metrics \
  -Dmanagement.endpoint.health.show-details=always"

第七章 依赖管理与版本控制

7.1 enforcedPlatform 严格版本控制

CAS 7.3 从 platform 升级到 enforcedPlatform 进行依赖版本控制,这是一个重要的策略变化。

platform vs enforcedPlatform 对比:

platform vs enforcedPlatform 行为差异
═══════════════════════════════════════════════════════════

  场景:BOM 声明 commons-dbcp2 版本为 2.10.0
        但某个传递依赖声明 commons-dbcp2 版本为 2.9.0

  ┌─────────────────────────────────────────┐
  │  platform(Gradle 推荐模式)              │
  │                                          │
  │  BOM 版本: 2.10.0                        │
  │  传递依赖: 2.9.0                         │
  │  结果: 2.9.0(传递依赖优先)              │
  │  ⚠️ 可能使用不兼容的版本                  │
  └─────────────────────────────────────────┘

  ┌─────────────────────────────────────────┐
  │  enforcedPlatform(CAS 7.3 选择)         │
  │                                          │
  │  BOM 版本: 2.10.0                        │
  │  传递依赖: 2.9.0                         │
  │  结果: 2.10.0(BOM 强制覆盖)             │
  │  ✅ 确保使用经过验证的版本                 │
  └─────────────────────────────────────────┘

CAS 7.3 的 enforcedPlatform 配置:

groovy
// CAS 7.3 依赖管理配置(教学简化版)
ext {
    casServerVersion = '7.3.0'
}

dependencies {
    // 使用 enforcedPlatform 进行严格版本控制
    enforcedPlatform("org.apereo.cas:cas-server-support-bom:${casServerVersion}")
    
    // CAS 核心依赖
    implementation "org.apereo.cas:cas-server-support-rest:${casServerVersion}"
    implementation "org.apereo.cas:cas-server-support-oauth:${casServerVersion}"
    implementation "org.apereo.cas:cas-server-support-oidc:${casServerVersion}"
    implementation "org.apereo.cas:cas-server-support-mybatis:${casServerVersion}"
    
    // 数据库相关
    implementation 'org.mybatis:mybatis:3.5.16'
    implementation 'org.mybatis:mybatis-spring:3.0.3'
    implementation 'org.apache.commons:commons-dbcp2:2.10.0'
    
    // 前端资源
    implementation 'org.webjars:bootstrap:5.3.3'
    implementation 'org.webjars:jquery:3.7.1'
    implementation 'org.webjars.npm:material-components-web:14.0.0'
}

enforcedPlatform 的注意事项:

  1. 版本冲突处理:当 enforcedPlatform 与直接声明的版本冲突时,Gradle 会报错。这实际上是好事——它强制开发者显式处理版本冲突。

  2. 与 Spring Boot BOM 的配合:CAS 7.3 同时使用了 CAS BOM 和 Spring Boot BOM,需要注意两者的优先级。

groovy
// CAS 7.3 多 BOM 配置
dependencies {
    // Spring Boot BOM(优先级较低)
    platform("org.springframework.boot:spring-boot-dependencies:3.5.6")
    
    // CAS BOM(优先级较高,使用 enforcedPlatform)
    enforcedPlatform("org.apereo.cas:cas-server-support-bom:${casServerVersion}")
    
    // 当两者都声明了同一个依赖的版本时:
    // enforcedPlatform 的版本会胜出
}
  1. 排除特定依赖:如果需要覆盖 BOM 中的某个版本,可以使用 exclude
groovy
dependencies {
    enforcedPlatform("org.apereo.cas:cas-server-support-bom:${casServerVersion}")
    
    // 排除 BOM 中的某个依赖版本
    implementation("org.apereo.cas:cas-server-support-xxx:${casServerVersion}") {
        exclude group: 'com.example', module: 'unwanted-library'
    }
    
    // 显式指定版本(覆盖 BOM)
    implementation 'com.example:specific-library:2.0.0'
}

7.2 MyBatis 跨版本升级:1.3.1 到 3.0.3

MyBatis Spring 集成模块从 1.3.1 升级到 3.0.3 是 CAS 7.3 依赖升级中最具挑战性的部分。这是一个跨越了 2.x 大版本的重大升级。

MyBatis 版本演进路线:

MyBatis Spring 集成模块版本演进
═══════════════════════════════════════════════════════════

  mybatis-spring 1.x(CAS 5.3/6.6 使用)
  ┌─────────────────────────────────────────┐
  │  mybatis-spring 1.3.1                    │
  │  ├── 支持 Spring 3.x / 4.x / 5.x       │
  │  ├── 手动配置 SqlSessionFactory         │
  │  ├── 手动配置 MapperScannerConfigurer   │
  │  ├── 不支持 Spring Boot 自动配置         │
  │  └── Java 7+                            │
  └─────────────────────────────────────────┘


  mybatis-spring 2.x(过渡版本)
  ┌─────────────────────────────────────────┐
  │  mybatis-spring 2.x                      │
  │  ├── 支持 Spring 5.x / 6.x             │
  │  ├── 引入 Spring Boot 自动配置          │
  │  ├── 支持 Jakarta Persistence API       │
  │  └── Java 8+                            │
  └─────────────────────────────────────────┘


  mybatis-spring 3.x(CAS 7.3 使用)
  ┌─────────────────────────────────────────┐
  │  mybatis-spring 3.0.3                    │
  │  ├── 支持 Spring 6.x(Spring Boot 3.x) │
  │  ├── 完整的 Spring Boot 自动配置        │
  │  ├── 使用 Jakarta EE 命名空间           │
  │  ├── 支持 Spring Boot 3.x 配置属性      │
  │  └── Java 17+                           │
  └─────────────────────────────────────────┘

关键变更详解:

  1. 命名空间变更(javax → jakarta)
java
// ❌ mybatis-spring 1.3.1(CAS 5.3/6.6)
import javax.sql.DataSource;
import javax.transaction.Transactional;

// ✅ mybatis-spring 3.0.3(CAS 7.3)
import jakarta.sql.DataSource;
import jakarta.transaction.Transactional;
  1. 配置方式变更
java
// ❌ mybatis-spring 1.3.1 手动配置方式
@Configuration
public class MyBatisConfig {
    
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setTypeAliasesPackage("org.apereo.cas");
        bean.setMapperLocations(new PathMatchingResourcePatternResolver()
            .getResources("classpath:mapper/*.xml"));
        return bean.getObject();
    }
    
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer configurer = new MapperScannerConfigurer();
        configurer.setBasePackage("org.apereo.cas.mapper");
        configurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
        return configurer;
    }
}

// ✅ mybatis-spring 3.0.3 Spring Boot 自动配置
// application.yml
mybatis:
  type-aliases-package: org.apereo.cas
  mapper-locations: classpath:mapper/*.xml
  configuration:
    map-underscore-to-camel-case: true
    cache-enabled: true
    lazy-loading-enabled: false
    default-executor-type: REUSE
  1. Mapper 接口变更
java
// ❌ mybatis-spring 1.3.1 风格
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface UserMapper {
    @Select("SELECT * FROM users WHERE username = #{username}")
    User findByUsername(String username);
}

// ✅ mybatis-spring 3.0.3 风格(接口不变,但注解处理方式更新)
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Options;

@Mapper
public interface UserMapper {
    @Select("SELECT * FROM users WHERE username = #{username}")
    @Options(useCache = true, timeout = 10000)
    User findByUsername(String username);
}

MyBatis 3.5.16 的新特性:

特性版本说明
支持 Java 213.5.16完全兼容 Java 21
支持 Jakarta EE3.5.14+使用 Jakarta 命名空间
性能优化3.5.xSQL 解析和参数处理优化
类型处理器增强3.5.x支持更多 Java 类型的自动映射
缓存改进3.5.x二级缓存性能优化
日志改进3.5.x支持 SLF4J 2.x

7.3 commons-dbcp 到 commons-dbcp2 迁移

从 commons-dbcp 1.4 迁移到 commons-dbcp2 2.10.0 是 CAS 7.3 依赖升级的另一个重要部分。

DBCP 版本对比:

特性commons-dbcp 1.4commons-dbcp2 2.10.0
Java 版本Java 6+Java 8+
连接池实现BasicDataSourceBasicDataSource
异步获取连接不支持支持(maxTotal + maxIdle
连接泄漏检测不支持removeAbandonedOnBorrow
连接验证validationQueryvalidationQuery + 自动验证
JMX 监控有限完整的 JMX 支持
连接池预热不支持initialSize
线程安全synchronized并发优化
包名org.apache.commons.dbcporg.apache.commons.dbcp2

迁移配置对比:

java
// ❌ commons-dbcp 1.4 配置(CAS 5.3/6.6)
import org.apache.commons.dbcp.BasicDataSource;

@Bean
public DataSource dataSource() {
    BasicDataSource ds = new BasicDataSource();
    ds.setDriverClassName("com.mysql.jdbc.Driver");
    ds.setUrl("jdbc:mysql://localhost:3306/cas");
    ds.setUsername("cas");
    ds.setPassword("password");
    ds.setMaxActive(50);        // DBCP2 中改为 setMaxTotal()
    ds.setMaxIdle(30);
    ds.setMinIdle(10);
    ds.setInitialSize(10);
    ds.setMaxWait(10000);       // DBCP2 中改为 setMaxWaitMillis()
    ds.setValidationQuery("SELECT 1");
    ds.setTestOnBorrow(true);
    ds.setTestWhileIdle(true);
    ds.setTimeBetweenEvictionRunsMillis(30000);
    ds.setMinEvictableIdleTimeMillis(60000);
    return ds;
}

// ✅ commons-dbcp2 2.10.0 配置(CAS 7.3)
import org.apache.commons.dbcp2.BasicDataSource;

@Bean
public DataSource dataSource() {
    BasicDataSource ds = new BasicDataSource();
    ds.setDriverClassName("com.mysql.cj.jdbc.Driver");  // MySQL Connector/J 8.x
    ds.setUrl("jdbc:mysql://localhost:3306/cas?useSSL=false&serverTimezone=UTC");
    ds.setUsername("cas");
    ds.setPassword("password");
    ds.setMaxTotal(50);           // 原 maxActive
    ds.setMaxIdle(30);
    ds.setMinIdle(10);
    ds.setInitialSize(10);
    ds.setMaxWaitMillis(10000);   // 原 maxWait
    ds.setValidationQuery("SELECT 1");
    ds.setTestOnBorrow(true);
    ds.setTestWhileIdle(true);
    ds.setTimeBetweenEvictionRunsMillis(30000);
    ds.setMinEvictableIdleTimeMillis(60000);
    
    // DBCP2 新增特性
    ds.setRemoveAbandonedOnBorrow(true);     // 连接泄漏检测
    ds.setRemoveAbandonedTimeout(300);        // 300 秒未关闭视为泄漏
    ds.setLogAbandoned(true);                 // 记录泄漏连接的堆栈
    ds.setPoolPreparedStatements(true);       // 预编译语句缓存
    ds.setMaxOpenPreparedStatements(50);      // 最大缓存语句数
    
    return ds;
}

Spring Boot 自动配置方式(推荐):

yaml
# application.yml - CAS 7.3 数据源配置
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/${DB_NAME:cas}?useSSL=false&serverTimezone=UTC
    username: ${DB_USER:cas}
    password: ${DB_PASSWORD:password}
    type: org.apache.commons.dbcp2.BasicDataSource
    dbcp2:
      max-total: 50
      max-idle: 30
      min-idle: 10
      initial-size: 10
      max-wait-millis: 10000
      validation-query: SELECT 1
      test-on-borrow: true
      test-while-idle: true
      time-between-eviction-runs-millis: 30000
      min-evictable-idle-time-millis: 60000
      remove-abandoned-on-borrow: true
      remove-abandoned-timeout: 300
      log-abandoned: true
      pool-prepared-statements: true
      max-open-prepared-statements: 50

DBCP2 连接池监控配置:

java
// 启用 JMX 监控
@Bean
public DataSource dataSource() {
    BasicDataSource ds = new BasicDataSource();
    // ... 其他配置 ...
    
    // 启用 JMX
    ds.setJmxName("org.apache.commons.dbcp2:type=DataSource,name=CAS");
    
    return ds;
}

7.4 WebJars 前端依赖管理

CAS 7.3 的前端依赖管理经历了重大变化,引入了 Material Design Components,并升级了 Bootstrap 和 jQuery。

WebJars 版本升级对比:

依赖CAS 5.3CAS 6.6CAS 7.3变化说明
Bootstrap3.4.15.2.35.3.3跨代升级(3→5)
jQuery3.6.03.6.43.7.1小版本升级
Material Components14.0.0新引入
Popper.js2.11.62.11.8Bootstrap 5 依赖

CAS 7.3 WebJars 配置:

groovy
// CAS 7.3 前端依赖配置
dependencies {
    // Bootstrap 5.3.3 - 完全重写的 CSS 框架
    implementation 'org.webjars:bootstrap:5.3.3'
    
    // jQuery 3.7.1 - 虽然 Bootstrap 5 不再依赖 jQuery,但 CAS 仍需要
    implementation 'org.webjars:jquery:3.7.1'
    
    // Material Components Web 14.0.0 - Google Material Design 组件
    implementation 'org.webjars.npm:material-components-web:14.0.0'
    
    // Popper.js - Bootstrap 5 的依赖
    implementation 'org.webjars:popper.js:2.11.8'
}

Bootstrap 3 到 5 的迁移要点:

Bootstrap 3 → 5 迁移关键变化
═══════════════════════════════════════════════════════════

  CSS 类名变更:
  ├── .panel → .card
  ├── .well → .card-body
  ├── .thumbnail → .card + .img-fluid
  ├── .label → .badge
  ├── .form-group → .mb-3
  ├── .input-group-addon → .input-group-text
  ├── .hidden-xs/sm/md/lg → .d-none .d-sm-none ...
  ├── .pull-left/right → .float-start/end
  ├── .text-left/right/center → .text-start/end/center
  └── .col-xs-* → .col-*(无 xs 断点)

  JavaScript 变更:
  ├── 移除 jQuery 依赖(Bootstrap 5 原生 JS)
  ├── data-* 属性命名变更(camelCase → kebab-case)
  ├── 事件命名变更(如 shown.bs.modal 不变)
  └── 工具提示和弹出框需要 Popper.js

  CAS 的影响:
  ├── 登录页面 UI 需要重新设计
  ├── 自定义主题 CSS 需要全面更新
  ├── JavaScript 插件调用方式需要调整
  └── 响应式断点需要重新测试

Material Components Web 集成:

CAS 7.3 引入 Material Components Web (MDC-Web) 14.0.0,为 CAS 的管理界面提供 Material Design 风格的 UI 组件。

groovy
// Material Components Web 依赖
implementation 'org.webjars.npm:material-components-web:14.0.0'
html
<!-- CAS 7.3 中使用 Material Components -->
<!DOCTYPE html>
<html>
<head>
    <!-- Material Icons -->
    <link rel="stylesheet" href="/webjars/material-components-web/14.0.0/material-components-web.min.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
</head>
<body>
    <!-- Material Button -->
    <button class="mdc-button mdc-button--raised">
        <span class="mdc-button__ripple"></span>
        <span class="mdc-button__label">Login</span>
    </button>
    
    <!-- Material Text Field -->
    <label class="mdc-text-field mdc-text-field--outlined">
        <span class="mdc-notched-outline">
            <span class="mdc-notched-outline__leading"></span>
            <span class="mdc-notched-outline__notch">
                <span class="mdc-floating-label" id="my-label-id">Username</span>
            </span>
            <span class="mdc-notched-outline__trailing"></span>
        </span>
        <input type="text" class="mdc-text-field__input" aria-labelledby="my-label-id">
    </label>
    
    <script src="/webjars/material-components-web/14.0.0/material-components-web.min.js"></script>
    <script>
        // 初始化 Material Components
        mdc.textField.MDCTextField.attachTo(document.querySelector('.mdc-text-field'));
        mdc.ripple.MDCRipple.attachTo(document.querySelector('.mdc-button'));
    </script>
</body>
</html>

WebJars 版本管理最佳实践:

groovy
// 集中管理 WebJars 版本
ext {
    webjarsVersions = [
        bootstrap: '5.3.3',
        jquery: '3.7.1',
        materialComponentsWeb: '14.0.0',
        popperJs: '2.11.8'
    ]
}

dependencies {
    implementation "org.webjars:bootstrap:${webjarsVersions.bootstrap}"
    implementation "org.webjars:jquery:${webjarsVersions.jquery}"
    implementation "org.webjars.npm:material-components-web:${webjarsVersions.materialComponentsWeb}"
    implementation "org.webjars:popper.js:${webjarsVersions.popperJs}"
}

总结与展望

升级路径总结

本文从七个维度系统性地分析了 CAS 从 5.3/6.6 升级到 7.3 的构建体系变革。以下是核心升级路径的总结:

CAS 构建体系升级全景图
═══════════════════════════════════════════════════════════

  ┌──────────────────────────────────────────────────────────┐
  │                    CAS 7.3 升级全景                       │
  │                                                            │
  │  构建工具层                                                │
  │  ├── Gradle 7.5 → 9.1.0                                   │
  │  ├── sourceCompatibility → java.toolchain                  │
  │  ├── 手动 JDK → Foojay Toolchains 自动下载                 │
  │  └── Configuration Cache 默认启用                          │
  │                                                            │
  │  依赖管理层                                                │
  │  ├── platform → enforcedPlatform                           │
  │  ├── mybatis-spring 1.3.1 → 3.0.3                         │
  │  ├── commons-dbcp 1.4 → commons-dbcp2 2.10.0              │
  │  └── Bootstrap 3.4.1 → 5.3.3 + MDC 14.0.0                │
  │                                                            │
  │  容器化层                                                  │
  │  ├── Dockerfile → Jib 3.5.3                                │
  │  ├── 单平台 → 多平台 (amd64 + arm64)                       │
  │  ├── eclipse-temurin:11 → azul/zulu-openjdk:21             │
  │  └── entrypoint.sh JDK 21 兼容修改                         │
  │                                                            │
  │  安全合规层                                                │
  │  ├── 无 SBOM → CycloneDX 1.5                              │
  │  ├── 无漏洞扫描 → SBOM + Grype/Trivy                      │
  │  └── 无供应链透明度 → 完整依赖追踪                          │
  │                                                            │
  │  运行时层                                                  │
  │  ├── Java 8/11 → Java 21                                   │
  │  ├── Spring Boot 2.7 → 3.5.6                               │
  │  ├── javax → jakarta                                       │
  │  └── -noverify/-Xdebug → -agentlib:jdwp                    │
  │                                                            │
  └──────────────────────────────────────────────────────────┘

升级建议

对于计划将 CAS 从 6.x 升级到 7.3 的团队,我们建议以下升级路径:

  1. 第一阶段:构建工具升级

    • 升级 Gradle Wrapper 到 9.1.0
    • 引入 Foojay Toolchains 插件
    • sourceCompatibility 迁移到 java.toolchain
    • 修复 Configuration Cache 兼容性问题
  2. 第二阶段:依赖升级

    • platform 升级到 enforcedPlatform
    • 升级 MyBatis 到 3.5.16 + mybatis-spring 3.0.3
    • 迁移 commons-dbcp 到 commons-dbcp2
    • 更新前端 WebJars 版本
  3. 第三阶段:容器化升级

    • 引入 Jib 插件替代 Dockerfile
    • 配置多平台镜像构建
    • 更新 entrypoint.sh 兼容 JDK 21
    • 调整 JVM 参数
  4. 第四阶段:安全合规

    • 引入 CycloneDX SBOM 生成
    • 集成漏洞扫描工具
    • 建立 SBOM 管理流程
  5. 第五阶段:运行时适配

    • 处理 javax → jakarta 命名空间迁移
    • 更新自定义认证处理器
    • 测试所有自定义扩展的兼容性

未来展望

CAS 构建体系的演进仍在继续。以下几个方向值得关注:

  1. Gradle Kotlin DSL:随着 Kotlin DSL 的成熟,CAS 未来可能会提供官方的 Kotlin DSL 构建脚本
  2. GraalVM Native Image:CAS 已经开始探索 GraalVM 原生镜像编译,这将大幅缩短启动时间
  3. SBOM 自动化:SBOM 生成将更加自动化,与 CI/CD 流水线深度集成
  4. AI 辅助构建:AI 工具可能被用于自动检测依赖冲突、推荐版本升级等
  5. 云原生构建:构建过程将进一步向云端迁移,利用远程构建缓存和分布式构建

版权声明: 本文为必码(bima.cc)原创技术文章,仅供学习交流。

本文内容基于实际项目源码解析整理,代码示例均为教学简化版本,仅供学习参考。

如需获取完整项目代码或技术支持,请访问 bima.cc