Apache Groovy 快速入门与集成示例
从环境检查到首个 Groovy 程序,掌握闭包、GString 与集合操作;并给出与 Gradle、Spring Boot、普通 Java 动态执行 Groovy 的集成示例与真实输出。
Apache Groovy 快速入门与集成示例
本文先以最小示例快速上手 Groovy,再给出与 Gradle、Spring Boot 及普通 Java 工程的集成样例。示例基于 Groovy 4.0.24 + JDK 11,命令与回显均来自真实执行。
一、快速入门
1.1 环境准备
确认 groovy 已可用,并设置好 JAVA_HOME:
# export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 # CentOS: /usr/lib/jvm/java-11-openjdk
# export GROOVY_HOME=/opt/groovy
# export PATH=$GROOVY_HOME/bin:$JAVA_HOME/bin:$PATH
# groovy --version
Groovy Version: 4.0.24 JVM: 11.0.32.1 Vendor: Ubuntu OS: Linux
1.2 第一个程序
创建 Hello.groovy:
def name = "Groovy"
def nums = [1, 2, 3, 4, 5]
println "Hello, ${name}!" // GString 插值
println "doubled = ${nums.collect { it * 2 }}" // 闭包 + 集合变换
println "total = ${nums.sum()}"
运行:
# groovy Hello.groovy
Hello, Groovy!
doubled = [2, 4, 6, 8, 10]
total = 15
1.3 逐行解读
def:动态类型声明,无需指定类型,运行时推断。"Hello, ${name}!":GString,双引号内可嵌入表达式;单引号字符串不做插值。nums.collect { it * 2 }:collect接收闭包,对每个元素变换后返回新列表;it是单参数闭包的隐式名。nums.sum():Groovy 为集合扩展的聚合方法。
二、语言要点速览
2.1 闭包
def square = { int x -> x * x }
println square(9)
def adder = { a, b -> a + b }
println adder(3, 4)
2.2 GString 与安全导航
def maybe = null
println "safe len = ${maybe?.size()}" // 安全导航,空对象不抛异常
println "elvis = ${maybe ?: 'default'}" // Elvis 运算符
2.3 集合与 Map
def nums = [1, 2, 3, 4, 5]
println nums.findAll { it % 2 == 0 } // [2, 4]
println nums.every { it > 0 } // true
def map = [k1: 'v1', k2: 'v2']
map.each { k, v -> println "map ${k} -> ${v}" }
2.4 正则与静态编译
def m = "order-2026-10-12.log" =~ /(\d{4})-(\d{2})-(\d{2})/
println m[0][0]
import groovy.transform.CompileStatic
@CompileStatic
int total(int[] xs) { xs.sum() as int }
三、Gradle 构建集成
3.1 工程结构
gradle-proj/
├── build.gradle
├── gradle.properties
└── src/main/groovy/App.groovy
3.2 构建脚本
build.gradle:
plugins { id 'groovy'; id 'application' }
repositories { mavenCentral() }
dependencies { implementation 'org.apache.groovy:groovy:4.0.24' }
application { mainClass = 'App' }
gradle.properties(控制构建 JVM 堆):
org.gradle.jvmargs=-Xmx512m
3.3 应用源码与运行
src/main/groovy/App.groovy:
class App {
static void main(String[] args) {
println "Hello from Gradle + Groovy ${GroovySystem.version}"
def nums = [3, 1, 2, 5, 4]
println "sorted = ${nums.sort()}"
}
}
运行(Gradle 8.5):
# gradle run -q --no-daemon
Hello from Gradle + Groovy 4.0.24
sorted = [1, 2, 3, 4, 5]
四、Spring Boot 集成
Groovy 类可被 Spring 的 IoC 上下文直接扫描并作为 Bean 使用。
4.1 依赖坐标
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy</artifactId>
<version>4.0.24</version>
</dependency>
4.2 Groovy 编写的 REST 组件(参考实现)
import org.springframework.web.bind.annotation.*
import groovy.transform.CompileStatic
@RestController
@CompileStatic
class GreetController {
@GetMapping('/hello')
String hello(@RequestParam(defaultValue = 'world') String name) {
"Hello, ${name}!"
}
}
将该文件放在 src/main/groovy 下,与 Java 代码同包结构,Spring Boot 启动后访问 /hello?name=apache 即返回 Hello, apache!。@CompileStatic 可让该控制器获得接近 Java 的运行性能。
说明:以上为集成骨架,依赖 Spring Boot 运行环境,未在本文所述命令行环境中单独运行。
五、普通 Java 中集成
5.1 GroovyShell 动态执行
Embed.java:
import groovy.lang.GroovyShell;
import groovy.lang.Binding;
public class Embed {
public static void main(String[] args) {
GroovyShell shell = new GroovyShell();
Object sum = shell.evaluate("(1..10).sum()");
System.out.println("sum(1..10) = " + sum);
shell.evaluate("println 'hello from embedded groovy'");
Binding binding = new Binding();
binding.setVariable("user", "apache");
GroovyShell shell2 = new GroovyShell(binding);
shell2.evaluate("greeting = \"Welcome, ${user}!\"");
System.out.println("binding.greeting = " + binding.getVariable("greeting"));
}
}
编译与运行:
# javac -encoding UTF-8 -cp /opt/groovy/lib/groovy-4.0.24.jar Embed.java -d .
# java -cp .:/opt/groovy/lib/groovy-4.0.24.jar Embed
sum(1..10) = 55
hello from embedded groovy
binding.greeting = Welcome, apache!
5.2 GroovyClassLoader 动态加载类
def gcl = new GroovyClassLoader()
def cls = gcl.parseClass('''
class Greeter {
String hi(String name) { "Hello, ${name}!" }
}
''')
println cls.newInstance().hi('Groovy')
println "loaded class = ${cls.name}"
真实回显:
# groovy gcl.groovy
Hello, Groovy!
loaded class = Greeter
factorial(5) = 120
5.3 Binding 数据传递
Binding 是 Java 与 Groovy 的双向变量通道:Java 侧 setVariable 注入、脚本内直接读取;脚本内赋值的变量可通过 getVariable 取回,实现参数下发与结果回收。
六、常见问题
Q1:脚本中文乱码?
运行脚本时指定编码 groovy -c UTF-8 script.groovy;使用 Java 编译 Groovy 相关源码时加 -encoding UTF-8。
Q2:groovysh 输入后长时间无反应?
不要在根目录 / 启动,切换到业务目录再启动,避免类路径全盘递归扫描。
Q3:@Grab 拉取失败?
确认可访问 Maven Central,或通过 @GrabResolver 指向私有仓库;离线环境请预先缓存 ~/.groovy/grapes。
Q4:集成时出现 NoClassDefFoundError: groovy/lang/...?
运行时类路径缺少 Groovy 运行时 jar,请将 groovy-4.0.24.jar(或 Maven 坐标 org.apache.groovy:groovy)加入 classpath。