1. 概述

Jooby 是一个基于主流 NIO Web 服务器构建的可扩展、高性能微 Web 框架。它设计简洁且高度模块化,专为现代 Web 架构量身打造,同时支持 JavaScript 和 Kotlin 开发。

默认情况下,Jooby 对 Netty、Jetty 和 Undertow 提供开箱即用的支持。

本文将带你了解 Jooby 的项目结构,并手把手教你构建一个简单的 Web 应用。

2. 应用架构

典型的 Jooby 应用结构如下:

├── public
|   └── welcome.html
├── conf
|   ├── application.conf
|   └── logback.xml
└── src
|   ├── main
|   |   └── java
|   |       └── com
|   |           └── baeldung
|   |               └── jooby
|   |                   └── App.java
|   └── test
|       └── java
|           └── com
|               └── baeldung
|                   └── jooby
|                       └── AppTest.java
├── pom.xml

关键点说明:

  • public 目录:存放静态资源(CSS/JS/HTML 等)
  • conf 目录:存放配置文件(如 logback.xmlapplication.conf

3. Maven 依赖

通过以下依赖即可快速构建 Jooby 应用:

<dependency>
    <groupId>io.jooby</groupId>
    <artifactId>jooby-netty</artifactId>
    <version>2.16.1</version>
</dependency>

若需改用 Jetty 或 Undertow:

<!-- Jetty -->
<dependency>
    <groupId>io.jooby</groupId>
    <artifactId>jooby-jetty</artifactId>
    <version>2.16.1</version>
</dependency>

<!-- Undertow -->
<dependency>
    <groupId>io.jooby</groupId>
    <artifactId>jooby-undertow</artifactId>
    <version>2.16.1</version>
</dependency>

最新版本可查阅 Maven 中央仓库

4. 构建应用

4.1. 启动服务器

启动嵌入式服务器只需以下代码:

public class App extends Jooby {
    public static void main(String[] args) {
        run(args, App::new);
    }
}

默认运行在 8080 端口。自定义端口和 HTTPS 端口配置如下:

{
    setServerOptions(new ServerOptions()
        .setPort(8080)
        .setSecurePort(8433));
}

4.2. 实现路由

Jooby 的路由定义极其简洁。例如创建 /login 接口:

{
    get("/login", ctx -> "Hello from Baeldung");
}

处理其他 HTTP 方法(POST/PUT 等)同样简单:

{
    post("/save", ctx -> {
        String userId = ctx.query("id").value();
        return userId;
    });
}

参数类型支持:header、cookie、path、query、form、multipart、session、flash,均提供统一类型安全的 API。

路径参数处理示例:

// 两种写法等价
get("/user/{id}", ctx -> "Hello user : " + ctx.path("id").value());
get("/user/:id", ctx -> "Hello user: " + ctx.path("id").value());

固定前缀路径参数(如 uid:):

get("/uid:{id}", ctx -> "Hello User with id : uid = " + ctx.path("id").value());

4.3. MVC 模式控制器

企业级开发中,Jooby 提供类似 Spring MVC 的 MVC API。例如处理 /hello 接口:

@Path("/submit")
public class PostController {
    
    @POST
    public String hello() {
        return "Submit Baeldung";
    }
}

其他 HTTP 方法通过 @POST@PUT@DELETE 等注解实现。

4.4. 处理静态资源

将静态文件(HTML/CSS/JS/图片等)放入 public 目录后,通过以下方式映射:

{
    assets("/employee", "public/form.html");
}

4.5. 表单处理

Jooby 的 Request 接口自动处理表单对象,无需手动类型转换。以员工信息提交为例:

  1. 定义数据模型:

    public class Employee {
     String id;
     String name;
     String email;
    
     // 标准构造器、getter/setter
    }
    
  2. 创建表单页面:

    <form enctype="application/x-www-form-urlencoded" action="/submitForm" method="post">
     <label>Employee id:</label><br>
     <input name="id"/><br>
     <label>Name:</label><br>
     <input name="name"/><br>
     <label>Email:</label><br>
     <input name="email"/><br><br>
     <input type="submit" value="Submit"/>
    </form>
    
  3. 处理表单提交:

    post("/submitForm", ctx -> {
     Employee employee = ctx.path(Employee.class);
     // 业务逻辑...
     return "employee data saved successfully";
    });
    

⚠️ 关键点:表单必须声明 enctype="application/x-www-form-urlencoded" 才能启用动态绑定。

4.6. 会话管理

Jooby 提供三种会话实现:内存会话、签名会话、带存储的内存会话。

内存会话

{
    get("/sessionInMemory", ctx -> {
        Session session = ctx.session();
        session.put("token", "value");
        return session.get("token").value();
    });
}

签名会话(无状态)

{
    String secret = "super secret token";

    setSessionStore(SessionStore.signed(secret));

    get("/signedSession", ctx -> {
        Session session = ctx.session();
        session.put("token", "value");
        return session.get("token").value();
    });
}

存储扩展

除内置内存存储外,还支持:

  • Caffeine:基于 Caffeine 缓存的内存存储
  • JWT:JSON Web Token 存储

以 Redis 为例:

  1. 添加依赖:

    <dependency>
     <groupId>io.jooby</groupId>
     <artifactId>jooby-redis</artifactId>
     <version>2.16.1</version>
    </dependency>
    
  2. 配置 Redis 会话:

    {
     install(new RedisModule("redis"));
     setSessionStore(new RedisSessionStore(require(RedisClient.class)));
     get("/redisSession", ctx -> {
         Session session = ctx.session();
         session.put("token", "value");
         return session.get("token");
     });
    }
    

application.conf 中配置 Redis 地址:

redis = "redis://localhost:6379"

更多示例参考 Jooby 官方文档

5. 测试

单元测试

添加测试依赖:

<dependency>
  <groupId>io.jooby</groupId>
  <artifactId>jooby-test</artifactId>
  <version>2.16.1</version>
</dependency>

使用 MockRouter 测试默认接口:

public class AppUnitTest {

    @Test
    public void given_defaultUrl_with_mockrouter_expect_fixedString() {
        MockRouter router = new MockRouter(new App());
        assertEquals("Hello World!", router.get("/").value());
    }
}

集成测试

基于 JUnit 5 的集成测试示例:

@JoobyTest(value = App.class, port = 8080)
public class AppLiveTest {

    static OkHttpClient client = new OkHttpClient();

    @Test
    public void given_defaultUrl_expect_fixedString() {
        Request request = new Request.Builder()
            .url("http://localhost:8080")
            .build();
        
        try (Response response = client.newCall(request).execute()) {
            assertEquals("Hello World!", response.body().string());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

关键说明:

  • @JoobyTest 自动管理应用启停
  • 默认端口 8911,可通过 port() 方法修改
  • 注解支持类级别和方法级别使用

更多测试示例见 官方文档

6. 总结

本文系统介绍了 Jooby 框架的核心功能与实战技巧。作为一款现代化的微框架,Jooby 在保持简洁性的同时提供了强大的扩展能力,特别适合构建高性能 Web 服务。

完整源码请查阅 GitHub 仓库


原始标题:Introduction to Jooby

« 上一篇: Kryo 介绍