
作为Apache Grails从Apache软件基金会(ASF)的顶级项目(TLP)毕业后的首个主要版本,Grails 8标志着该框架全面转型为基于Java 21/25和Spring Boot 4的现代化技术栈。然而,企业在享受这些强大新功能带来的好处的同时,也面临着现实工程中的挑战:在大规模代码库中,应用程序重新加载速度变慢,开发效率下降。
作为 JRebel 官方授权合作伙伴,龙智为您带来Apache Grails 副总裁兼主席 James Fredley 对Grails 8 的前沿特性解读,以及平稳升级指南,更针对中大型项目的研发痛点,提供行业级热部署能效优化方案,助力 Java 团队扫清升级路上的效率障碍。
Grails 8标志着Grails框架演进的又一重要里程碑。该版本重点聚焦于长期稳定性、生态系统兼容性,以及对 Grails 应用在生产环境中所依赖的基础架构进行现代化改造。
作为 Apache Grails 的副总裁兼主席,我一直带领团队进行 Grails 8 的研发工作。继续阅读,深入了解 Grails 近期转型为 Apache 软件基金会(ASF)项目的幕后故事,看看 Grails 8 带来了哪些新特性,为何做出这些改变,以及 Java 开发团队在准备采用 Grails 8 时应做哪些考量。
此外,我还将介绍发布时间线、主要平台变更、废弃特性,以及将现有 Grails 应用升级到 Grails 8 的实用指南。
新篇章:Grails 正式入驻 Apache 软件基金会
2025 年 9 月,历经 18 个月的迁移努力,Apache Grails正式从孵化项目毕业,晋升为 Apache 软件基金会(ASF)顶级项目(Top-Level Project, TLP)。对于一个自 2005 年起持续迭代至今的框架而言,这是其发展史上最具里程碑意义的治理变革,这重新奠定了未来所有Grails版本(包括Grails 8)开发的基础。
在 Apache 软件基金会框架下治理、开发与发布 Grails
入驻 ASF 改变了 Grails 的治理、开发与发布方式。所有权从单一组织主导模式(Grails 曾先后由 G2One、SpringSource、Object Computing 以及 Grails 基金会/Unity 基金会轮流托管)转变为志愿者驱动、厂商中立的项目管理委员会,并在强调共识与透明的"Apache 之道"指导下运作。
如今的决策均在公开邮件列表中讨论,代码审查完全开放,发布流程严格遵循 ASF 关于许可合规、来源追溯与构建可重复性的政策要求。对于企业团队而言,这意味着更清晰的文档记录、可预测的治理机制以及不存在单一的企业故障点。
此次转型背后的技术工作量相当庞大。
变更内容包括:
-
GitHub 仓库整合:Grails 团队将 24 个以上的独立 GitHub 代码库整合为一个 grails-core 单体代码库(mono-repo)。该仓库现包含 109 个 Gradle 项目,并生成超过 325 个已发布的 JAR 文件。
-
构建时间大幅缩短:Grails 版本的构建时间从原来的三周缩短至约 30 分钟。
-
统一的 Maven 坐标:Maven 坐标已统一为org.apache.grails;每个发布的构件均经过许可证合规性审查,并为每个 JAR 文件自动生成软件物料清单(SBOM)。构建系统本身已实现端到端可重复性,任何第三方均可独立验证发布内容。这一能力不仅惠及框架本身,也为下游 Grails 应用带来益处。
重焕活力的 Grails 社区
同样重要的是,入驻 ASF 显著激发了社区活力。Grails 7是首个在 ASF 框架下发布的稳定版本,其开发团队成员构成远比以往版本更为广泛------其中不乏对Apache Groovy本身做出重要贡献的开发者。随之而来的是新提交者的不断加入、全新邮件列表的启用、焕然一新的 Slack 工作区,以及更加活跃的问题跟踪系统。
这一转变对框架的长期采用具有直接影响:仅依赖单一维护者的框架是脆弱的,而依托成熟基金会、拥有数十位活跃贡献者的框架则具备韧性。因此,在审视 Grails 8 发布时,必须将其置于这一重焕动能的社区背景之下来考量。
Grails 重焕发展新动能
Grails 8 是首个完全在 ASF 管理下规划并执行的主要版本,体现了项目对其新运营模式的信心。其发展路线图不再受限于单一组织所能提供的资金支持,而是由更广泛的 JVM 生态系统的发展趋势,以及志愿者团队所具备的引领能力来共同决定的。
回顾 Grails 7:承前启后的关键一步
理解 Grails 8 的演进方向,首先需要回顾 Grails 7 已交付的成果。Grails 7.0.0 于 2025 年 10 月 18 日发布,是 ASF 接管后首个稳定版本,它为 Grails 8 的所有上层构建奠定了技术基础。
通过 Grails 7 实现 Java 现代化
Grails 7 实现了整个技术栈的现代化升级。它全面迁移至 Apache Groovy 4.0.x、Spring Boot 3.5.x、Spring Framework 6.2.x 以及 Jakarta EE 10(即期待已久的`javax.* 到 jakarta.* 的命名空间迁移),并将最低运行环境要求提升至 Java 17。Maven 坐标统一调整为 org.apache.grails;grails-i18n 插件被迁移至独立的坐标空间,并默认设置为可传递;整个构建过程实现了逐字节级别的完全可重复,且为每个 JAR 文件生成了 SBOM(软件物料清单)。Grails Forge 应用程序生成器(start.grails.org)以及轻量级的 Grails Wrapper(grailsw,约 25KB)作为核心命令行工具(CLI),与传统的 Shell 脚本一同发布。功能测试方面迎来了全面焕新,引入了 Geb 8 及容器化浏览器支持,同时,cloud.wondrify.asset-pipeline 5.x 取代了旧版的 Asset Pipeline 坐标。
Grails 7 还完成了那些不引人注目但不可或缺的代码精简工作。它为模块化应用添加了多项目重载支持,并且将一长串来自 Grails 5 和 6 时代的已废弃 API 要么直接移除,要么安排在 Grails 8 中移除。换句话说,Grails 7 在其整个发布周期内,致力于使框架与现代 JVM 接轨,推动项目满足 ASF 的政策合规要求,并清理好跑道。而 Grails 8,正是团队在跑道清理完毕、畅通无阻的情况下所构建的成果。
Grails 8 发布计划与演进策略
Grails 8 的开发始终围绕一个清晰目标:使框架与现代 JVM 生态系统对齐,同时为企业级 Grails 应用提供稳定且面向未来的基石。其发布节奏也体现了这一优先级,在必要的平台升级与可预期的迁移路径之间取得平衡。
Grails 8 发布窗口
Grails 8 的开发工作于 2025 年 11 月下旬正式启动,紧随 Spring Boot 4.0.0 正式版(GA )发布之后。首个公开里程碑版本Grails 8.0.0-M1 于 2026 年 5 月 6 日发布,后续里程碑版本、候选发布版(RC)及最终的 8.0.0 正式版(GA)的发布节奏,将紧密跟随底层平台栈(如 Spring Boot、Groovy 等)的成熟度。在 8.0.0 正式版(GA )正式发布之前,建议团队将 8.0.x 里程碑版本视为预览构建,仅用于技术评估与迁移规划,而非用于生产环境部署。
平台对齐驱动 Grails 8 的发布节奏
Grails 8 有意与 Spring Boot 4.0 和 Spring Framework 7.0 紧密绑定。这正是 M1 版本未能更早发布的原因:框架不会基于尚未正式发布的 Spring 技术栈推出主要版本。一旦 8.0.0 正式版(GA)正式发布,该项目计划按照Spring Boot自身的月度更新周期,保持每月发布一次8.0.x版本补丁的频率,并针对安全问题和紧急修复提供非正式版本更新。
Grails 7 与 Grails 8 的生命周期重叠
7.0.x 版本线将持续获得全面的更新与维护,直至 Spring Boot 3.5.x 于 2026 年 6 月 30 日终止生命周期。这为团队提供了一条清晰的过渡路径:在 Spring Boot 3.5 获得官方支持期间,团队可以继续安心使用 Grails 7,并利用这段窗口期规划向 Grails 8 的迁移,从而避免陷入在不再受支持的底层平台上运行的困境。Grails 6.2.3(于 2025 年 1 月 3 日发布)是 6.2.x 系列的最终版本,也是迁入 ASF 前的最后一个版本;目前仍在使用 Grails 6 的团队应规划先迁移至 7.0.x,再升级至 8.0.x,而非尝试一步跨级跃升。
Grails 8 背后的设计目标
每个主要的 Grails 版本都由少数几个核心目标驱动。对于 Grails 8 而言,这些目标聚焦于长期生命力、代码清晰性以及互操作性。
● 长期生命力
Grails 8 使框架与具备多年支持周期的平台保持对齐,包括 Java 21 LTS、Spring Boot 4.0.x、Jakarta EE 10 以及 Hibernate 7。通过紧跟核心依赖的长期支持分支(并移除那些将框架绑定在这些依赖旧版本上的类与 API),Grails 8 能够顺畅地接收安全与功能更新,而无需进行破坏性的代码重写。在入驻 ASF 期间引入的单体代码库(mono-repo)、可重复构建以及 SBOM(软件物料清单),进一步减轻了维护负担,从而确保项目能够维持这一发布节奏。
● 代码清晰性
Grails 8 删除了大量遗留代码------包括初代 JSONBuilder、Mixin AST 转换、已废弃的 EnumMarshaller 类、旧版命名查询基础设施(NamedCriteriaProxy,NamedQueriesBuilder),AetherGrapeEngine,已废弃的插件过滤器,以及多个早已废弃的 MongoEntity 和标签库方法。其结果是,公共接口更小、更专注,且推荐的做法也是唯一的方式。这一改变使得 Grails 框架更易于学习,也更易于维护和支持。
● 互操作性
Spring Boot 4 已将其自动配置拆分为领域专用模块(如 spring-boot-webmvc,spring-boot-servlet,
spring-boot-mongodb 等),Spring Framework7 移除了自身的org.springframework.orm.hibernate
5 包,并采用了 JSpecify 可空性注解,同时 Jackson 3 取代 Jackson 2 成为默认的 JSON 映射器。Grails 8 全面吸收了这些上游变更,从而确保在 Grails 应用中直接调用 Spring 或 Jakarta API 的团队,能够无缝使用这些现代且受支持的版本,而无需与Grails进行技术对抗。
Grails 8 与现代 JVM 及 Jakarta 标准的对齐
Grails 8 明确与当前一代 JVM 生态及 Jakarta 标准保持同步。
| 组件 | Grails 7 | Grails 8 |
|---|---|---|
| Java 基线版本 | 17 | 21 |
| Spring Boot(Spring 启动器) | 3.5.x | 4.0.x(M1 版本中为 4.0.5) |
| Spring Framework(Spring 核心框架) | 6.2.x | 7.0.x(M1 版本中为 7.0.6) |
| Jakarta EE(企业版 Java 规范) | 10 | 10 |
| Jakarta Servlet API(Servlet 接口规范) | 6.0.x | 6.1.0 |
| Hibernate ORM(对象关系映射框架) | 5.6.x | M1 版本中为 5.6.x,后续里程碑版本将升级至 7.x |
| Apache Groovy(动态语言运行时) | 4.0.x | M1 版本中为 4.0.x |
| Gradle(构建自动化工具) | 8.14.x | 9.4.1 |
| Jackson(JSON 数据处理库) | 2.x | 3.x(包名变更为 tools.jackson.*) |
| Spock(测试与规范框架) | 2.3-groovy-4.0 | 2.3-groovy-4.0(Micronaut 配置文件中已支持 2.4-groovy-5.0) |
Hibernate 7 的升级正在通过 PR #15568 推进合并,这是一项基于 8.0.x-hibernate7 分支的大量工作,取代了之前在 PR #15530 中的尝试。预计它将在 8.0.0 GA 发布前完成合并,这也是为什么应将 M1 视为平台转型的预览,而非最终形态。
这种对齐是必要的,因为 Spring Framework 7 和 Spring Boot 4 都是围绕 Java 17+、Jakarta Servlet 6.1 以及全新的模块化自动配置布局而设计的。如果停留在旧的技术栈上,将迫使 Grails 无限期地向后移植(backport)安全修复;相反,该框架与其底层基础同步演进。
通过 Grails 8 减少历史遗留负担
Grails 8 的开发工作中,有相当大一部分是做减法。通过 PR #15565,以下内容已被正式移除:
-
旧版 JSON/XML EnumMarshaller
-
JSONBuilder(已被StreamingJsonBuilder取代)
-
旧的 Mixin/ MixinTargetAware/MixinTransfor
mation机制
-
已弃用的 ConstraintsEvaluator
-
CompatibilityPluginFilter 及整个 PluginFilter 层级结构
-
BinaryGrailsPluginDescriptor
-
CorePluginFinder(核心插件查找器)
-
AetherGrapeEngine 与 AetherGrapeEngineFactory
-
原始的 gson-views JSON 生成器类
-
GORM AutoTimestamp 注解以及 NamedCriteriaProxy/NamedQueriesBuilder 命名查询基础设施(仅其测试类就超过 1,000 行代码)
-
grails-events-compat 兼容适配层(shim)
-
GrailsApplication,GrailsPluginManager,MongoEntityFormTagLib和ApplicationTagLib中已弃用的方法
到 2026 年,这些 API 早已不再是主流选择,但每一项都伴随着对应的测试基础设施、文档以及不可忽视的兼容性成本。将它们彻底移除,不仅缩减了 Grails 为应对未来 Spring、Groovy 和 Hibernate 变更所需维护的公共接口边界,也让剩余的 API 更易于学习、编写文档和提供支持。
Grails 8 面向生产环境的重心
Grails 8 的设计围绕生产环境的实际运行需求:
-
开箱即用的可观测性默认配置:Spring Boot 4 的存活探针(Liveness Probe)与就绪探针(Readiness Probe)默认通过 Health 端点暴露。这意味着 Kubernetes 部署无需为每个应用额外编写样板代码,即可获得正确的探针行为。
-
可重复且可证明的构建:每个发布的 JAR 文件均附带软件物料清单(SBOM),且构建过程实现端到端可复现,便于安全团队验证构件来源。
-
日志默认配置契合现代基础设施:Logback 现在默认使用 UTF-8 编码写入日志文件,与 Log4j2 及主流容器日志采集工具保持一致。
-
可预测的插件兼容性提示信号:Grails Gradle 插件在配置阶段一旦检测到不兼容设置(例如在 BOM 中使用未启用 enforcedPlatform 的 grails-micronaut),便会立即报错,而非让构建过程在运行时以难以察觉的方式失败。
Grails 8 新特性一览
Grails 8 引入了一系列影响应用程序构建、配置和运行方式的变更。其中部分变更较为渐进,而另一些则反映了平台层面的根本性变革。
核心框架与依赖更新
Grails 8.0.0-M1 的主要变更包括:
-
Spring Boot 4.0.5 与 Spring Framework 7.0.6(PR #15541)。
-
Spring Boot 自动配置模块化:原先单体式的 spring-boot-autoconfigure JAR 已被移除;自动配置类现已拆分至领域专用模块中,如 spring-boot-webmvc、spring-boot-servlet 和 spring-boot-mongodb。Grails 8 通过拆分的 BOM(依赖物料清单)无缝适配了这一新布局(PR #15608)。
-
Jackson 3(tools.jackson.*)成为默认 JSON 映射器:Jackson 注解仍保留在 com.fasterxml.jackson.annotation.* 命名空间下,并明确允许与 Jackson 3 配合使用,因此现有的 DTO 和领域类无需修改。Spring Boot 的部分辅助类已重命名(例如 Jackson2ObjectMapperBuilderCustomizer 改为 JsonMapperBuilderCustomizer,@JsonComponent 改为 @JacksonComponent 等)。
-
Hibernate 7 升级正在推进中:通过 8.0.x-hibernate7 分支的 PR #15568 进行。Grails 8.0.0-M1 目前仍默认附带 Hibernate 5.6.15.Final。
-
Hibernate 兼容包内嵌处理:Spring Framework 7 已彻底移除 org.springframewor k.orm.hibernate5 包。Grails 8 将该包直接内嵌(vendor)至全新的 grails-data-hibernate5 -spring-orm 模块(位于org.grails.orm.hibern ate.support.hibernate5 路径下),确保 Grails 托管的 Hibernate 集成继续无缝工作。若应用在代码中直接导入了这些 Spring 类,则需手动更新包名。
-
Spring Security 更新(PR #15609):grails-spring-security 插件已同步刷新,并将遵循独立的发布节奏持续跟进。
-
Gradle 9.4.1 工具链:Grails Forge 项目生成器与 grails-micronaut 集成已全面升级至 Micronaut 4 / Micronaut Platform 5(PR #15365)。
-
CLI 交互依赖升级:Grails Shell 命令行界面现已采用 JLine 3.30.6 与 Jansi 2.4.2(PR #15367)。
-
测试框架更新:基于浏览器的功能测试现使用 Geb 8.0.1,同时集成 JUnit 6.0.3 与 Spock 2.3-groovy-4.0。
-
资源管线更新:位于 cloud.wondrify 坐标下的 Asset Pipeline 已升级至 5.1.0-M4(该坐标变更始于 Grails 7)。
Grails 8 的 Java 版本基线
Grails 8 要求使用 Java 21 来构建和运行应用程序,相较于 Grails 7 的 Java 17 要求有所提升。Java 21 是一个拥有广泛生态系统支持的长期支持(LTS)版本。Grails 团队选择 Java 21 而非更激进的基线版本(例如同样是 LTS 的 Java 25),主要基于以下两个实际原因:
1. 与现有工具生态系统的LTS 周期对齐:Java 21 在各大 OpenJDK 发行版(如 Temurin、Corretto、Liberica、Microsoft Build of OpenJDK、Oracle、Semeru)中均提供多年的供应商支持,这与大多数企业团队规划的技术支持周期相匹配。Java 25 虽然同样是 LTS 版本且更新,但工具生态系统(如构建代理、容器镜像、IDE 集成、第三方插件兼容性矩阵)通常需要 6 至 12 个月才能完全适配新的 LTS 版本。
2. 为插件提供可预期性:Grails 拥有规模庞大的第三方插件生态系统。将基线设定为 Java 21,可使这些插件针对稳定的字节码版本和标准库 API进行开发,而无需追逐后续版本中的预览特性或已敲定的 JEP(JDK 增强提案)。
但存在一个重要的例外:使用 grails-micronaut 集成的应用程序必须在 JDK 25 或更高版本上运行。**这并非 Grails 的决策,而是 Micronaut 的要求:Micronaut Core 的 io.micronaut.core.propagation.ScopedValues 引用了 java.lang.ScopedValue.CallableOp,而该类型仅在 JDK 25 中才存在(当 JEP 506 正式确定 ScopedValue 规范时,内部类型从 Callable 重命名为 CallableOp)。若在 JDK 21 至 JDK 24 上运行 Micronaut,会在运行时因找不到该类而失败,并抛出 NoClassDefFoundError:java/lang/ScopedValue$CallableOp 异常。Grails Forge 生成器会在项目生成阶段强制执行此要求,若 JDK 版本过低,Grails Gradle 插件也会给出明确的错误提示。不使用任何 Micronaut 集成的应用程序则不受此影响,可继续在 JDK 21 上运行。
配置与约定更新
部分 Spring Boot 4 的变更已延伸至 Grails 的配置体系中:
-
MongoDB 属性命名空间:在Spring Boot 自身自动配置中,spring.data.mongodb.* 现已变更为 spring.mongodb.*。Grails GORM for MongoDB 插件使用的是其专属的 mongodb.* 命名空间,不受此次变更影响。
-
Jackson 属性结构调整 :原有的 spring.jackson.read.* 和 spring.jackson.writ
e.*配置项已迁移至 spring.jackson.json.read.* 与 spring.jackson.json.write.* 路径下。对于大多数此类变更,spring-boot-properties-migrator 依赖项会在应用启动时发出警告。
-
枚举序列化默认行为 :正如 Grails 7.0.2 弃用公告中所宣布的,SimpleEnumMarshaller 现已正式成为 JSON 与 XML 枚举序列化的默认选项。枚举将被序列化为纯字符串值(例如 "SUBMIT"),而不再是带有类型元数据的冗长旧格式。此前通过配置 grails.converters.json.
enum.format: simple 显式启用的应用,现已可直接移除该配置。
-
Spring Boot Starter重命名:spring-boot-starter-web 现已更名为 spring-boot-starter-webmvc;spring-boot-starter-aop 更名为 spring-boot-starter-aspectj;OAuth2 相关 Starter 也已统一添加 security- 前缀(例如 spring-boot-starter-security-oauth2-client 等)。为降低迁移阻力,Spring Boot 4 提供了一个过渡性的 spring-boot-starter-classic,它会引入完整的模块集合,但新代码应直接面向这些模块化的 Starter 进行开发。
-
WAR 包部署:面向外部容器(External-container)的 WAR 包,现已改用 spring-boot-starter-tomcat-runtime,取代了原先providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat' 的惯用写法。内嵌 Tomcat(即 ./gradlew bootRun 命令及可执行 WAR 包的默认配置)则继续不变地使用 spring-boot-starter-tomcat。
构建、工具链与开发者体验
Gradle 版本覆盖管理:PR #15467 采用 Gradle 平台机制结合轻量级的 BOM 属性覆盖方案,取代了原有的 Spring 依赖管理插件。应用现在无需引入 Spring DM 插件,即可通过标准 Gradle 语法直接覆盖 BOM 托管的依赖版本。
-
基于方法的 TagLib 语法:PR #15465 为 Grails 标签库引入了基于方法的语法,在完全兼容传统闭包写法的同时,还提供了配套的性能基准测试与更新文档。
-
Shell CLI中的Apache Maven 解析器:grails-shell-cli 现已内嵌 Apache Maven 3.9.9 与 Maven Resolver 1.9.22,用于在传统交互式 Shell 中解析插件与依赖元数据。终端用户的 Grails 项目仍继续使用 Gradle 进行构建------此项变更仅影响 Shell CLI 自身的内部解析机制。
-
Grails Forge :位于 start.grails.org 的应用生成器是创建新 Grails 8 的推荐方式;它能够自动应用正确的 BOM (物料清单)、enforcedPlatform 语义以及 JDK 版本强制规则。
-
发布前就绪性验证:新增的 verify-branch.sh 脚本(PR #15621)为提交者提供了一键式预检能力,可在打发布标签前快速确认构建是否具备可复现性、签名完整性与可发布性。
-
可复现、字节级一致的构件:PR #15625 实现了每个模块的 SBOM 与 Groovydoc 输出的字节级可复现,确保重复执行发布流程时生成的构件内容完全一致。
Grails 8 的性能与运行时行为
对于大多数应用而言,Grails 8 在运行时行为上应表现为平稳、渐进式的演进,因为 Spring Boot 4 本身并非以性能优化为核心目标的发布版本。在进行容量规划时,有几个具体细节值得注意:
-
启动时间:对于标准的 Grails MVC 应用,启动时间与 Grails 7 基本持平。Spring Boot 4带来了渐进式的启动优化,但并未实现数量级上的飞跃。
-
内存与资源占用:内存占用与资源开销与 Spring Boot 4 的默认配置保持一致。内嵌 Tomcat 仍是默认选项;而 Undertow 在 Grails 8 中暂时不受支持,原因是其尚未发布兼容 Servlet 6.1 的版本(因此 Grails Forge 项目生成器已不再将 Undertow 列为可选配置)。
Grails 8 中的弃用项与破坏性变更
与任何主要版本发布一样,Grails 8 移除了在先前版本中已被标记为弃用的功能。这些移除是经过深思熟虑的,旨在确保框架具备长期可维护性。官方升级参考文档为Grails 8 升级指南,其中详细罗列了每一项变更。
已移除的长期弃用功能
大部分删除操作已通过 PR #15565 合并。其中影响最为关键的几项移除包括:
-
Grails.web.JSONBuilder:已被 groovy.json.
-
StreamingJsonBuilder 取代。使用旧版构建器手动构建 JSON 的代码,必须迁移至流式构建器。
-
旧版枚举序列化器:JSON 与 XML 中冗长的 EnumMarshaller 已被移除;SimpleEnumMarshaller 现已作为默认实现注册。通过 render(MyEnum.VALUE as JSON) 直接渲染单个枚举值的操作,现在会抛出 ConverterException 异常(详见 PR #15212)。
-
@Mixin 注解与 AST 转换机制:包括MixinTargetAware 与 MixinTransformation均被移除。官方建议改用 Groovy特征(Traits) 或扩展模块(Extension Modules) 作为替代方案。
-
GORM 旧版命名查询:NamedCriteriaProxy、NamedQueriesBuilder 以及 GORM 的 @AutoTimestamp 注解已被移除。建议改用 GORM 的 where 查询、查找器(finders),或兼容 @CompileStatic 编译的查询 DSL。
-
插件过滤层级结构: CompatibilityPluginFilter,PluginFilter,BasePluginFilter,IncludingPluginFilter,ExcludingPluginFilter,IdentityPluginFilter,PluginFilterRetriever 以及 BinaryGrailsPluginDescriptor 已全部移除。插件发现机制现已统一合并至现代化的插件管理器中。
-
AetherGrapeEngine / AetherGrapeEngine Factory:grails-shell-cli 中内嵌的 Grape 解析器已被移除。Shell 环境中的 Maven 依赖解析现直接通过 Apache Maven Resolver 进行。
-
grails-events-compat:Reactor 2 兼容层已被移除。仍在使用 reactor.bus.* 兼容类的应用,必须迁移至现代化的 grails-events API。
-
已弃用的标签库方法:FormTagLib 与 ApplicationTagLib 移除了约十几个长期标记为弃用的方法。完整移除清单请参阅官方升级指南。
Grails 8 中需要注意的行为变更
即使部分 API 依然保留,多个运行时默认行为也已发生调整:
-
@SpringBootTest 不再自动配置 MockMvc、WebClient 或 TestRestTemplate。原先依赖隐式注入的测试代码,现在必须显式添加 @AutoConfigureMockMvc、@AutoConfigureWebClient 或 @AutoConfigureTestRestTemplate 。
-
@MockBean 和 @SpyBean 已被移除,取而代之的是位于 org.springframework.test.context.bean.override.mockito 的 @MockitoBean 与 @MockitoSpyBean。新注解仅支持在测试类字段上声明,无法再用于 @Configuration 类中。
-
TestRestTemplate已迁移至 org.springframework.boot.resttestclient包下。
-
HttpStatus.MOVED_TEMPORARILY 已被移除。请改用 HttpStatus.FOUND------两者均表示 HTTP 302 状态码,运行时行为完全一致。
-
Spring Framework 7 已移除主题相关功能。ThemeResolver、ThemeSource、Theme、SimpleTheme 及 SessionThemeResolver 等类均已不复存在。原先依赖 Spring 主题动态切换样式表的应用,需改用配置属性或会话(Session)属性来实现等效功能。
-
Spring Retry 不再由 Spring Boot 4 托管。若应用直接使用 @Retryable、@EnableRetry 或 @Recover ,则需在 build.gradle 中显式声明该依赖。
-
Logback 日志文件默认编码已改为 UTF-8。原先基于过去使用平台默认字符集的日志采集管道(log scraping pipelines)必须切换为 UTF-8。
-
存活探针(Liveness)与就绪探针(Readiness)现已默认在 Health 端点启用;如需关闭,可通过配置项 management.endpoint.health.probes.enabled: false 进行禁用。
Grails 8 升级与迁移注意事项
对于一直跟进代码弃用(deprecation)情况并及时处理的团队而言,升级至 Grails 8 相对直接,但仍需审慎规划、稳步推进。此次升级本质上是从 Spring Boot 3 向 Spring Boot 4 的迁移,并在此基础上叠加了 Grails 专属的兼容性防护机制;大部分破坏性变更实际上源于上游平台的演进,而非 Grails 框架自身。
升级至 Grails 8 的实用迁移步骤
请遵循以下步骤,以简化从 Grails 7 到 Grails 8 的迁移过程:
1.升级至最新的 Grails 7.x 版本
Grails 7 已完成 javax.* 到 jakarta.* 的迁移,并将 Maven 坐标统一归集至 org.apache.grails。在升级至 Grails 8 之前,先在最新的 7.x 版本上完成这些基础迁移,可确保每个问题都独立暴露出来并逐一解决,避免在跨版本升级时集中爆发。
2.在升级至 Grails 8 前,彻底清理 Grails 7 中的所有弃用警告
所有在 Grails 7 中被标记为弃用的任何内容,在 Grails 8 中均已被正式移除。此处最有效的工具是 Spring Boot 的 spring-boot-properties-migrator 依赖:将其以 runtimeOnly 作用域引入项目,启动应用,逐一修复它输出的所有配置警告,确认无误后再将该依赖移除。
3.审查项目中直接引用的 Spring 导入
请在代码库中全局搜索以下路径或标识符:org.springframework.orm.hibernate5.*、com.
fasterxml.jackson.databind.*、org.springframe
work.boot.web.embedded.*、HttpStatus.MOVED
_TEMPORARILY,以及与 Spring Theme(主题)相关的类。《Grails 8 升级指南》已为上述每项内容提供了明确的替代方案与迁移示例,可按指引逐一替换。
4. 验证插件与自定义框架扩展
确认 build.gradle 中的每个 Grails 插件均已升级至兼容 Grails 8 的版本。对于使用 grails-micronaut 的项目,务必确保 BOM(物料清单) 已通过 enforcedPlatform 引入(若未正确配置,Grails Gradle 插件将在构建配置阶段直接导致构建失败)。
5.更新测试
在相关位置添加 @AutoConfigureMockMvc 或 @AutoConfigureTestRestTemplate;将 @Mock
Bean 替换为 @MockitoBean;同步更新 TestRest
Template 的导入路径。
6.规划 JDK 版本策略
JDK 21 为最低基线要求。若项目中任何位置使用了 Micronaut,则必须在 CI 环境与生产环境中就绪 JDK 25。采用混合部署模式的团队应在迁移前统一 JDK 版本标准。
7.使用类似生产环境的工作负载进行测试
Spring Boot 4 的默认配置变更(如 UTF-8 日志编码、探针默认启用、开发工具实时重载默认关闭)单看影响细微,但叠加后在预发环境中会变得明显。建议在升级后完整执行一次预生产测试。
8.密切关注启动时间与重载表现
Spring Boot 4 调整了多项开发工作流的默认配置(详见下一节)。对于中大型应用而言,代码重载速度将直接成为影响迁移期间开发效率的关键指标,需纳入实测评估。
Grails 8 开发中的代码重载选项
随着 Grails 应用规模的不断扩大,热重载速度往往是开发者反馈循环中显著变慢的一环。Grails 8 的发布正是做出明确选型决策、而非继续依赖默认配置的最佳时机。
Apache Grails 官方开发重载文档列出了 Grails 8 所支持的所有重载方案。对大多数团队而言,实际开发中最关键的三个选项是:
1.Spring Boot Developer Tools(开发者工具)
这是新生成 Grails 应用的默认配置,也是理想的起步方案。它采用双类加载器机制,能够在代码变更时自动重启应用上下文,并支持静态资源的实时重载。官方 Grails 文档对其扩展性有明确提示:"在应用规模较小时表现良好,但当应用变得非常庞大时,重启可能会变慢甚至失败。"对于中大型 Grails 应用,DevTools 重启通常需要数秒到数分钟,因为每次类路径变更都会触发全量应用上下文重建、清除内存状态、使 JIT 编译优化失效,并重新执行 @PostConstruct 初始化与应用引导逻辑。
2.IntelliJ IDEA 增强版热替换(调试模式)
在调试会话期间,该功能可直接重载已修改的类,而无需重启应用上下文。它虽能避免 DevTools 的全量重启,但受限于 JVM 热替换对"结构性变更"的硬性约束------除非您同时使用 JetBrains Runtime(JBR)并启用 -XX:+AllowEnhancedClassRedefinition 参数。在实际开发中,面对中大型应用,其重载时间感知上仍需数十秒,与 DevTools 相差无几。原因在于,绝大多数实质性代码变更(如新增方法、调整 Spring Bean 定义、修改 GORM 映射)恰恰属于 IDE 无法直接热替换的结构性变更。
3. JRebel
这是一款商业级JVM 代理工具,通过字节码插桩(bytecode instrumentation)实现真正的热替换。它能够在不重启 JVM、不丢失应用状态的前提下,实时重载类、配置与资源。其重载过程几乎是瞬时的------即使在大型应用中,通常也远低于一秒,因为整个过程中没有任何组件被销毁或重建。JRebel 是 Grails 官方明确推荐用于高级重载需求的方案,提供了一流的 Grails / Spring Boot 集成支持,并配有专属的 IntelliJ IDEA 插件。
Grails 文档中也列出了 Hotswap Agent 与 原生 JVM 调试模式热替换。目前 Hotswap Agent 在 Grails 中仍被归类为实验性方案,且官方文档已明确记录其局限性;而原生 JVM 调试模式热替换仅支持非结构性变更。对于企业级 Grails 8 应用而言,两者均不适合作为核心重载方案,但在特定狭窄场景下仍具可用性。
此外,Spring Boot 4 自身调整了一项影响上述所有方案的默认配置:spring.devtools.livereload.
enabled 现已默认设为 false。Grails Forge 项目生成器会通过 application-development.yml 主动将其重新启用;但若您现有的 Grails 7 应用依赖于 devtools 的实时重载功能,升级至 Grails 8 后需手动添加此配置。
为什么为中大型 Grails 8 应用选择 JRebel?
给 Grails 8 团队的实际建议非常明确:对于小型应用,DevTools 完全够用。但随着应用规模的增长(事实上,任何值得迁移至 Grails 8 的项目通常都已具备相当体量),每次代码变更的重载耗时都会从几秒攀升至几十秒,在超大型企业级应用中甚至可能长达数分钟。
若将这一单次耗时乘以开发者每天产生的代码变更次数,答案便一目了然:几十秒的重载等待与 JRebel不到一秒的即时重载之间的差距,直接决定了开发者是度过高效专注的一天,还是陷入频繁上下文切换的低效循环。
JRebel 的价值在 Grails 8 迁移影响最显著的场景中体现得尤为突出:
-
承载大量内存状态的应用:如缓存、定时任务、Spring Security 会话、GORM 连接池、消息队列及 WebSocket 连接等。DevTools 每次重载都会清空这些状态,而 JRebel 则能完整保留。
-
模块化与多项目 Grails 应用:在共享模块中仅修改一行代码,往往会触发所有下游依赖项目的级联重建。
-
使用 grails-micronaut 集成的应用:此类应用类路径更长、JDK 版本要求更高(JDK 25+),启动引导过程也更为繁重。
-
迁移工作本身:在迁移期间,您需要快速迭代处理 Spring Boot 4 的弃用警告、插件兼容性修复,以及 GSP/Groovy/Java 代码的连续变更。在整个迁移周期中,每次重载节省的每一秒,都会在整个迁移周期中不断累积放大。
对于正在对真实生产应用进行现代化升级的 Grails 8 团队而言,免费方案与 JRebel 在重载速度上的差距已足够显著------它不仅会实质性拉长整个迁移周期,更会直接影响团队在最终交付上线时的信心。
关于 Grails 8 的最终思考
Grails 8 的核心目标在于确保 Grails 继续作为一流框架,在现代化环境中高效构建与运行 JVM 应用。本次发布的各项变革,凝聚了团队多年来在生产环境中运行 Grails 的实战经验,标志着项目在 Apache 软件基金会治理下完成的首个完整开发周期,并清晰锚定生态系统的未来技术栈:Java 21、Spring Boot 4、Spring Framework 7、Hibernate 7 与 Jakarta EE 10。
对于已使用 Grails 7.x 的团队而言,只要日常已及时清理废弃警告,此次升级将是平稳渐进的,而非破坏性的重构。对于仍停留在 Grails 6.x 的团队,官方推荐的升级路径是:先迁移至最新的 Grails 7 版本,再逐步升级至 Grails 8。此项迁移工作建议在 Spring Boot 3.5.x 于 2026 年 6 月 30 日正式终止支持(EOL)之前完成。
只要团队制定周密的升级规划,Grails 8 必将成为下一代 Grails 应用稳定且功能强大的基础平台。更重要的是,它也是首个明确为开源社区长期治理与持续演进而设计的 Grails 版本。