1. 概述

Ratpack 是一套基于 JVM 的库,专为现代高性能实时应用设计。它构建在嵌入式 Netty 事件驱动网络引擎之上,完全符合响应式编程模式。

本文将带你快速上手 Ratpack,并通过实战示例掌握其核心用法。

2. 为什么选择 Ratpack?

Ratpack 的核心优势:

轻量高效:内存占用远低于 DropWizard 等框架,性能对比数据一目了然
事件驱动:基于 Netty 实现,天然非阻塞架构
依赖管理:原生支持 Guice 依赖注入
测试友好:类似 Spring Boot,提供专用测试库快速构建测试用例

⚠️ 注意:官方推荐使用 Gradle 作为构建工具(通过 Ratpack Gradle 插件),Maven 支持相对有限。

3. 构建应用

3.1. Maven 依赖

pom.xml 中添加核心依赖:

<dependency>
    <groupId>io.ratpack</groupId>
    <artifactId>ratpack-core</artifactId>
    <version>1.4.5</version>
</dependency>
<dependency>
    <groupId>io.ratpack</groupId>
    <artifactId>ratpack-test</artifactId>
    <version>1.4.5</version>
</dependency>

最新版本可在 Maven Central 查询

3.2. 启动应用

创建主类启动嵌入式 Netty 服务器:

public class Application {
    public static void main(String[] args) throws Exception {
        RatpackServer.start(server -> server.handlers(chain -> chain
          .get(ctx -> ctx.render("Welcome to Baeldung ratpack!!!"))));
    }
}

关键点解析:

  • 默认监听端口 5050
  • handlers() 方法接收 Chain 对象构建请求处理链
  • 访问 http://localhost:5050 将返回欢迎文本

3.3. 处理路径参数

使用 PathTokens 捕获 URL 参数:

RatpackServer.start(server -> server
  .handlers(chain -> chain
  .get(":name", ctx -> ctx.render("Hello " 
  + ctx.getPathTokens().get("name") + " !!!"))));

访问 http://localhost:5050/John 将返回 Hello John !!!

3.4. 请求/响应头处理

直接修改响应头

RatpackServer.start(server -> server.handlers(chain -> chain.all(ctx -> {
    MutableHeaders headers = ctx.getResponse().getHeaders();
    headers.set("Access-Control-Allow-Origin", "*");
    headers.set("Accept-Language", "en-us");
    headers.set("Accept-Charset", "UTF-8");
    ctx.next();
}).get(":name", ctx -> ctx
    .render("Hello " + ctx.getPathTokens().get("name") + "!!!"))));

通过过滤器实现

创建过滤器类:

public class RequestValidatorFilter implements Handler {
    @Override
    public void handle(Context ctx) throws Exception {
        MutableHeaders headers = ctx.getResponse().getHeaders();
        headers.set("Access-Control-Allow-Origin", "*");
        ctx.next();
    }
}

注册过滤器:

RatpackServer.start(
    server -> server.handlers(chain -> chain
      .all(new RequestValidatorFilter())
      .get(ctx -> ctx.render("Welcome to baeldung ratpack!!!"))));
}

3.5. JSON 处理

Ratpack 内置 faster-jackson 进行 JSON 解析。创建 POJO:

public class Employee {
    private Long id;
    private String title;
    private String name;
    // getters and setters 
}

返回 JSON 响应:

List<Employee> employees = new ArrayList<>();
employees.add(new Employee(1L, "Mr", "John Doe"));
employees.add(new Employee(2L, "Mr", "White Snow"));

RatpackServer.start(
    server -> server.handlers(chain -> chain
      .get("data/employees",
      ctx -> ctx.render(Jackson.json(employees)))));

无需手动操作 ObjectMapper,Ratpack 自动完成序列化

3.6. 内存数据库

集成 HikariCP 连接池:

添加依赖

<dependency>
    <groupId>io.ratpack</groupId>
    <artifactId>ratpack-hikari</artifactId>
    <version>1.4.5</version>
</dependency>

初始化数据库

RatpackServer.start(
    server -> server.registry(Guice.registry(bindings -> 
      bindings.module(HikariModule.class, config -> {
          config.setDataSourceClassName("org.h2.jdbcx.JdbcDataSource");
          config.addDataSourceProperty("URL",
          "jdbc:h2:mem:baeldung;INIT=RUNSCRIPT FROM 'classpath:/DDL.sql'");
      }))).handlers(...));

需在 src/main/resources 创建 DDL.sql 定义表结构

4. 测试

使用 MainClassApplicationUnderTest 进行接口测试:

@RunWith(JUnit4.class)
public class ApplicationTest {
    MainClassApplicationUnderTest appUnderTest
      = new MainClassApplicationUnderTest(Application.class);

    @Test
    public void givenDefaultUrl_getStaticText() {
        assertEquals("Welcome to baeldung ratpack!!!", 
          appUnderTest.getHttpClient().getText("/"));
    }

    @Test
    public void givenDynamicUrl_getDynamicText() {
        assertEquals("Hello dummybot!!!", 
          appUnderTest.getHttpClient().getText("/dummybot"));
    }

    @Test
    public void givenUrl_getListOfEmployee() 
      throws JsonProcessingException {
        List<Employee> employees = new ArrayList<>();
        ObjectMapper mapper = new ObjectMapper();
        employees.add(new Employee(1L, "Mr", "John Doe"));
        employees.add(new Employee(2L, "Mr", "White Snow"));

        assertEquals(mapper.writeValueAsString(employees), 
          appUnderTest.getHttpClient().getText("/data/employees"));
    }
 
    @After
    public void shutdown() {
        appUnderTest.close(); // 必须手动释放资源
    }
}

⚠️ 踩坑提示:务必调用 close() 释放测试资源,否则可能阻塞 JVM。

5. 总结

Ratpack 以其轻量、高效的事件驱动架构,成为构建高性能应用的利器。通过本文的实战示例,我们掌握了:

  • 核心请求处理机制
  • 路径参数与响应头控制
  • JSON 序列化与数据库集成
  • 一站式测试方案

完整代码示例见 GitHub 仓库


原始标题:Introduction to Ratpack