ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Gretty 源码深度剖析:从 Gradle 插件到 Runner 的完整执行链路

Gretty 源码深度剖析:从 Gradle 插件到 Runner 的完整执行链路 Gretty 源码深度剖析从 Gradle 插件到 Runner 的完整执行链路【免费下载链接】grettyAdvanced gradle plugin for running web-apps on jetty and tomcat.项目地址: https://gitcode.com/gh_mirrors/gr/gretty当你在build.gradle里敲下apply plugin: org.akhikhl.gretty再执行一行gradle appRun一个 Jetty 或 Tomcat 容器便神奇地启动起来浏览器自动弹出你的 Web 应用。Gretty正是这样一个高级 Gradle 插件它把构建 Web 应用并在 Jetty/Tomcat 上运行这件事简化到了极致。但这一行命令背后到底发生了什么从Gradle 插件注册任务、到DefaultLauncher拉起独立 JVM、再到Runner进程里启动 Servlet 容器是一条设计精巧的完整执行链路。本文将从源码角度把这条链路从头到尾拆给你看帮助你真正理解 Gretty 的运行机制。一、Gretty 源码整体架构三个关键层次 ️在深入执行链路之前先认识 Gretty 的源码布局。克隆仓库后核心代码集中在libs/目录下可以分成三个层次层次模块职责Gradle 插件层libs/gretty/与 Gradle 深度耦合注册任务、扩展、配置、依赖桥接层libs/gretty-core/、libs/gretty-runner/进程启动、端口协商、服务协议、Runner 主类容器适配层gretty-runner-jetty7/8/9/93/94、gretty-runner-tomcat/7/8针对不同 Servlet 容器实现ServerManager这种分层设计非常巧妙Gradle 插件层libs/gretty只负责与构建系统交互容器适配层完全独立于 Gradle甚至可以直接复用。理解了这三个层次整条执行链路就清晰了一半。二、执行链路总览一次 appRun 的完整旅程 一次gradle appRun的完整执行大致经历以下五个阶段插件入口GrettyPlugin.apply()注册扩展与任务任务执行AppStartTask组装配置构造DefaultLauncher进程拉起LauncherBase协商端口通过javaexec启动 Runner 子进程服务循环Runner主进程监听命令调用ServerManager启动容器交互控制Gradle 侧监听按键向 Runner 发送 restart/stop 指令下面我们逐个阶段深入剖析。三、第一阶段插件入口 —— GrettyPlugin 干了什么 一切从GrettyPlugin开始它是整个插件的总开关源码位于 GrettyPlugin.groovy。它的apply()方法主要做了四件事1. 注册扩展DSLproject.extensions.create(gretty, GrettyExtension) project.extensions.create(farm, FarmExtension, project) project.extensions.create(product, ProductExtension)这就是你能在build.gradle里写gretty { ... }、farm { ... }配置块的来源。2. 批量注册任务在addTasks()方法中插件一口气注册了几十个任务appRun、appStart、appStop、appRestart、jettyRun、tomcatRun以及各自的 Debug 变体如appRunDebug还有集成测试配套的appBeforeIntegrationTest/appAfterIntegrationTest。3. 建立任务依赖在addTaskDependencies()中appRun会依赖prepareInplaceWebApp或prepareArchiveWebApp确保启动前 Web 应用资源已准备就绪。4. 注入依赖配置插件还会为 Spring Boot 项目自动排除内嵌 Tomcat/Jetty避免与 Gretty 管理的容器冲突这正是 Gretty 能优雅支持 Spring Boot 的关键细节。小知识GrettyStartTask类已标记Deprecated建议直接使用AppStartTask源码见 GrettyStartTask.groovy。四、第二阶段任务执行 —— StartBaseTask 的模板方法 运行appRun时实际执行的是AppStartTask继承自StartBaseTask。StartBaseTask是一个经典的模板方法模式实现源码见 StartBaseTask.groovy。它的核心是TaskAction action()方法LauncherConfig config getLauncherConfig() Launcher launcher new DefaultLauncher(project, config) launcher.scannerManager createScannerManager(config, ...) launcher.launch()而AppStartTask.getStartConfig()见 AppStartTask.groovy负责把 DSL 配置、项目默认值、命令行参数合并成最终的ServerConfig和WebAppConfig并调用doPrepareServerConfig()处理证书生成、Jacoco 参数注入、SpringLoaded 热加载 agent 等细节。五、第三阶段进程拉起 —— LauncherBase 与端口协商 DefaultLauncher继承了LauncherBase源码在 LauncherBase.groovy这里藏着两个重要机制1. 端口协商beforeLaunch()会先检查build/gretty_ports属性文件判断服务器是否已在运行如果未运行则通过findFreePorts()分配两个空闲端口servicePort服务端口用于接收命令和statusPort状态端口用于回报启动状态并写入属性文件。2. 启动子进程launchThread()中会构造JavaExecParams以org.akhikhl.gretty.Runner为主类通过javaexec在独立的 JVM 进程中启动服务器params.main org.akhikhl.gretty.Runner params.args [ --servicePort${servicePort}, --statusPort${statusPort}, --serverManagerFactory${getServerManagerFactory()} ]设计亮点服务器运行在独立进程中与 Gradle 守护进程隔离。即使 Gradle 任务结束服务器也能存活这也是appStart非交互模式能后台常驻的原因。六、第四阶段Runner 主进程 —— 命令驱动的服务循环 Runner是独立 JVM 的入口源码见 Runner.groovy它的main()解析三个命令行参数后进入一个死循环创建ServerSocket监听servicePort并向 Gradle 侧发送init信号循环读取 Gradle 侧发来的 JSON 命令首次收到配置后加载 logback 日志配置调用ServerManager.startServer()之后根据命令响应status返回启动状态、stop停止服务器并退出、restart重启容器、redeploy xxx热部署指定 Web 应用这个机制让Gradle 任务已退出、服务器仍在运行成为可能服务器启动后appRun的交互循环只是不停读取键盘输入并把按键翻译成restartWithEvent等命令发给 Runner。七、第五阶段ServerManager —— 容器适配层的抽象 ServerManager是容器适配层的核心接口ServerManager.groovy只定义四个方法setParams()—— 注入运行参数startServer()—— 启动容器stopServer()—— 停止容器redeploy()—— 热部署指定应用每个容器版本提供自己的实现gretty-runner-jetty9、gretty-runner-jetty94负责 Jetty 各版本gretty-runner-tomcat8等负责 Tomcat。Runner 通过Class.forName(params.serverManagerFactory)反射加载对应的工厂类从而与具体容器解耦。这种一个 Runner 多个 ServerManager 实现的架构让 Gretty 只需一份命令协议就能无缝支持 Jetty 7/8/9/9.3/9.4 与 Tomcat 7/8 全家桶。八、热部署与自动重启的秘密Scanner 机制 执行链路之外Gretty 最受好评的热部署功能也值得一看。StartBaseTask的createScannerManager()支持两种扫描器源码见 scanner/JDKScannerManager.groovy 和 JettyScannerManager.groovyJDK 扫描器基于WatchService性能更高优先使用Jetty 扫描器作为 JDK 扫描器不可用时的降级方案当扫描器检测到 class 或资源变化时会通过asyncResponse向 Runner 发送restartWithEvent命令并等待完成事件实现优雅的热重启。若开启了 Spring Loaded 的managedClassReload还能实现类级别的热替换。九、进阶场景Farm 多应用集群与集成测试 如果你有多个 Web 应用需要同时运行Gretty 的Farm机制会派出用场。GrettyPlugin.addTasks()会为每个 farm 生成farmRun、farmStart、farmStop等一系列任务在同一个容器中部署多个应用。此外appBeforeIntegrationTest/appAfterIntegrationTest任务与integrationTest任务配合可以在测试前自动启动服务器、测试后自动关闭——配合integrationTests/目录下的大量示例如 farm/、helloGretty/你可以快速学会各种场景的用法。十、总结一次点击背后的精妙设计 回看整条链路Gradle 插件注册任务 → 任务组装配置 → Launcher 协商端口 → 独立 JVM 中的 Runner 循环 → ServerManager 启动容器 → Scanner 驱动热部署。Gretty 的成功源于两个关键决策进程隔离服务器跑在独立 JVM 中与 Gradle 生命周期解耦协议抽象统一的服务协议 可插拔的容器适配层一份命令通吃所有容器希望这篇 Gretty 源码剖析能帮你建立起从 Gradle 插件到 Runner 的完整认知。下次运行gradle appRun时你就能清楚地知道屏幕背后那条精心设计的执行链路正在如何为你工作。如果想亲手验证可以用git clone https://gitcode.com/gh_mirrors/gr/gretty拉取源码边读边调试收获会更大。【免费下载链接】grettyAdvanced gradle plugin for running web-apps on jetty and tomcat.项目地址: https://gitcode.com/gh_mirrors/gr/gretty创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表