1. 概述
Ratpack 是一套轻量级的 Java 库,专为构建可扩展的 HTTP 应用程序设计,支持响应式、异步和非阻塞特性。
此外,Ratpack 还支持与 Google Guice、Spring Boot、RxJava 和 Hystrix 等技术或框架集成。
在本教程中,我们将探讨 如何在 Groovy 中使用 Ratpack。通过 Groovy 的动态特性与脚本能力,结合 Ratpack 的简洁 API,可以非常快速地搭建高性能的 Web 应用。
2. 为何选择 Groovy
Groovy 是一种运行在 JVM 上的动态语言,功能强大且语法灵活。
Groovy 让脚本编写和领域特定语言(DSL)的开发变得非常简单。结合 Ratpack,可以实现 Web 应用的快速开发。
Ratpack 提供了对 Groovy 的良好支持,主要通过两个核心库:ratpack-groovy
和 ratpack-groovy-test
。
3. 使用 Groovy 脚本创建 Ratpack 应用
Ratpack 的 Groovy API 是用 Java 编写的,因此可以轻松与 Java 或 Groovy 项目集成。这些 API 位于 ratpack.groovy
包中。
结合 Groovy 的脚本能力和 Grape 依赖管理机制,我们只需几行代码就能快速构建一个基于 Ratpack 的 Web 应用:
@Grab('io.ratpack:ratpack-groovy:1.6.1')
import static ratpack.groovy.Groovy.ratpack
ratpack {
handlers {
get {
render 'Hello World from Ratpack with Groovy!!'
}
}
}
✅ 这是我们第一个处理 GET 请求的 handler。我们只需要添加一些 DSL 语句即可启用 Ratpack 服务。
运行该脚本后,默认服务地址为 http://localhost:5050
:
$ curl -s localhost:5050
Hello World from Ratpack with Groovy!!
也可以通过 ServerConfig
自定义端口:
ratpack {
serverConfig {
port(5056)
}
}
⚠️ Ratpack 还支持热重载功能,修改 Ratpack.groovy
后,下一次 HTTP 请求即可看到变更。
4. Ratpack-Groovy 的依赖管理
启用 ratpack-groovy
支持有多种方式:
4.1. 使用 Grape
Groovy 内置的依赖管理工具 Grape 可以非常方便地引入依赖:
@Grab('io.ratpack:ratpack-groovy:1.6.1')
import static ratpack.groovy.Groovy.ratpack
4.2. Maven 依赖
使用 Maven 时,只需在 pom.xml
中添加如下依赖:
<dependency>
<groupId>io.ratpack</groupId>
<artifactId>ratpack-groovy</artifactId>
<version>${ratpack.version}</version>
</dependency>
4.3. Gradle 配置
在 build.gradle
中添加 Ratpack 的 Groovy 插件:
plugins {
id 'io.ratpack.ratpack-groovy' version '1.6.1'
}
5. Groovy 中的 Ratpack Handler
Handler 是处理 Web 请求和响应的核心机制。 请求和响应对象可以通过闭包访问。
我们可以通过 GET、POST 等 HTTP 方法来定义 handler:
handlers {
get("greet/:name") { ctx ->
render "Hello " + ctx.getPathTokens().get("name") + " !!!"
}
}
访问 http://localhost:5050/greet/Norman
测试接口:
$ curl -s localhost:5050/greet/Norman
Hello Norman!!!
在 handler 中,ctx
表示上下文对象,用于访问路径变量、请求和响应等信息。
Ratpack 也通过 Jackson 支持 JSON 数据处理。例如,我们可以将 Groovy Map 转换为 JSON 响应:
get("data") {
render Jackson.json([title: "Mr", name: "Norman", country: "USA"])
}
测试接口:
$ curl -s localhost:5050/data
{"title":"Mr","name":"Norman","country":"USA"}
6. Groovy 中的 Ratpack Promise
Ratpack 的异步和非阻塞特性是通过 Promise 实现的。Promise 类似于 JavaScript 中的 Promise,也可以类比 Java 中的 Future
。它代表一个将来可用的值。
示例代码如下:
post("user") {
Promise<User> user = parse(Jackson.fromJson(User))
user.then { u -> render u.name }
}
解析说明:
Jackson.fromJson(User)
通过ObjectMapper
解析请求体中的 JSON。Context.parse
将其绑定为 Promise。- 异步操作完成后,通过
then
处理结果并返回响应。
测试接口:
curl -X POST -H 'Content-type: application/json' --data \
'{"id":3,"title":"Mrs","name":"Jiney Weiber","country":"UK"}' \
http://localhost:5050/employee
Jiney Weiber
Promise 支持链式操作,如 map
和 flatMap
,可构建复杂的异步逻辑。
7. 与数据库集成
异步 handler 的优势在需要等待外部服务(如数据库)时尤为明显。下面我们演示如何将 Ratpack 与 H2 数据库集成。
7.1. 使用 HikariModule
添加 HikariCP 和 H2 的 Maven 依赖:
<dependency>
<groupId>io.ratpack</groupId>
<artifactId>ratpack-hikari</artifactId>
<version>${ratpack.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
Gradle 项目可添加如下依赖:
dependencies {
compile ratpack.dependency('hikari')
compile "com.h2database:h2:$h2.version"
}
在 ratpack
配置中声明 HikariModule:
import ratpack.hikari.HikariModule
ratpack {
bindings {
module(HikariModule) { config ->
config.dataSourceClassName = 'org.h2.jdbcx.JdbcDataSource'
config.addDataSourceProperty('URL',
"jdbc:h2:mem:devDB;INIT=RUNSCRIPT FROM 'classpath:/User.sql'")
}
}
}
使用 Java 的 Connection
和 PreparedStatement
进行数据库操作:
get('fetchUserName/:id') { Context ctx ->
Connection connection = ctx.get(DataSource.class).getConnection()
PreparedStatement queryStatement =
connection.prepareStatement("SELECT NAME FROM USER WHERE ID=?")
queryStatement.setInt(1, Integer.parseInt(ctx.getPathTokens().get("id")))
ResultSet resultSet = queryStatement.executeQuery()
resultSet.next()
render resultSet.getString(1)
}
测试接口:
$ curl -s localhost:5050/fetchUserName/1
Norman Potter
7.2. 使用 Groovy 的 Sql 类
Groovy 提供了便捷的 Sql
类用于快速数据库操作:
get('fetchUsers') {
def db = [url:'jdbc:h2:mem:devDB']
def sql = Sql.newInstance(db.url, db.user, db.password)
def users = sql.rows("SELECT * FROM USER");
render(Jackson.json(users))
}
测试接口:
$ curl -s localhost:5050/fetchUsers
[{"ID":1,"TITLE":"Mr","NAME":"Norman Potter","COUNTRY":"USA"},
{"ID":2,"TITLE":"Miss","NAME":"Ketty Smith","COUNTRY":"FRANCE"}]
POST 接口示例:
post('addUser') {
parse(Jackson.fromJson(User))
.then { u ->
def db = [url:'jdbc:h2:mem:devDB']
Sql sql = Sql.newInstance(db.url, db.user, db.password)
sql.executeInsert("INSERT INTO USER VALUES (?,?,?,?)",
[u.id, u.title, u.name, u.country])
render "User $u.name inserted"
}
}
测试接口:
$ curl -X POST -H 'Content-type: application/json' --data \
'{"id":3,"title":"Mrs","name":"Jiney Weiber","country":"UK"}' \
http://localhost:5050/addUser
User Jiney Weiber inserted
8. 单元测试
8.1. 测试环境搭建
Ratpack 提供了 ratpack-groovy-test
库用于测试 Groovy 应用。
Maven 项目添加如下依赖:
<dependency>
<groupId>io.ratpack</groupId>
<artifactId>ratpack-groovy-test</artifactId>
<version>1.6.1</version>
</dependency>
Gradle 项目添加:
testCompile ratpack.dependency('groovy-test')
创建主类 RatpackGroovyApp.groovy
用于启动测试服务:
public class RatpackGroovyApp {
public static void main(String[] args) {
File file = new File("src/main/groovy/com/baeldung/Ratpack.groovy");
def shell = new GroovyShell()
shell.evaluate(file)
}
}
编写测试类 RatpackGroovySpec.groovy
:
class RatpackGroovySpec {
ServerBackedApplicationUnderTest ratpackGroovyApp =
new MainClassApplicationUnderTest(RatpackGroovyApp.class)
@Delegate TestHttpClient client =
TestHttpClient.testHttpClient(ratpackGroovyApp)
}
8.2. 编写测试用例
测试应用是否启动成功:
@Test
void "test if app is started"() {
when:
get("")
then:
assert response.statusCode == 200
assert response.body.text ==
"Hello World from Ratpack with Groovy!!"
}
测试 fetchUsers
接口:
@Test
void "test fetchUsers"() {
when:
get("fetchUsers")
then:
assert response.statusCode == 200
assert response.body.text ==
'[{"ID":1,"TITLE":"Mr","NAME":"Norman Potter","COUNTRY":"USA"},{"ID":2,"TITLE":"Miss","NAME":"Ketty Smith","COUNTRY":"FRANCE"}]'
}
Ratpack 的测试框架会自动管理服务器的启动与关闭。
9. 总结
本文介绍了如何在 Groovy 中使用 Ratpack 构建 Web 应用,包括:
- 使用 Groovy 脚本快速启动服务
- Handler 的定义与 JSON 响应处理
- 异步 Promise 的使用
- 与 H2 数据库的集成(HikariModule 与 Groovy Sql)
- 使用 Ratpack 提供的测试框架进行单元测试
通过 Groovy 的闭包、DSL 和 Sql 支持,代码更加简洁、高效、可读性高。同时,Groovy 的测试能力也使得集成测试变得简单。
借助这些特性,我们可以快速构建高性能、可扩展的 HTTP 应用。
完整示例代码可在 GitHub 上找到。