Jooby简介

2025/04/07

1. 概述

Jooby是一个可扩展且快速的微Web框架,建立在最常用的NIO Web服务器之上。它非常简单且模块化,专为现代Web架构而设计,还支持Javascript和Kotlin。

默认情况下,Jooby对Netty、Jetty和Undertow提供了强大的支持。

在本文中,我们将了解Jooby的整体项目结构以及如何使用Jooby构建一个简单的Web应用程序。

2. 应用程序架构

一个简单的Jooby应用程序结构如下所示:

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

这里要注意的一点是,在public目录中,我们可以放置静态文件,例如css/js/html等。在conf目录中,我们可以放置应用程序需要的任何配置文件,例如logback.xml或application.conf等。

3. Maven依赖

我们可以通过在pom.xml中添加以下依赖来创建一个简单的Jooby应用程序:

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

如果我们要选择Jetty或Undertow,我们可以使用以下依赖:

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

你可以在中央Maven仓库中查看Jooby项目的最新版本。

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 Tuyucheng");
}

类似地,如果我们想要处理其他HTTP方法(如POST、PUT等),我们可以使用以下代码片段:

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

这里,我们从请求中获取请求参数名称id。有几种参数类型:header、cookie、path、query、form、multipart、session和flash,它们都共享一个统一/类型安全的API来访问和操作它们的值。

我们可以通过以下方式检查任何URI路径参数:

{
    get("/user/{id}", ctx -> "Hello user : " + ctx.path("id").value());
    get("/user/:id", ctx -> "Hello user: " + ctx.path("id").value());
}

我们可以使用上述任何一种方法,也可以查找以固定内容开头的URI路径参数。例如,我们可以按以下方式查找以“uid:”开头的URI路径参数:

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

4.3 实现MVC模式控制器

对于企业级应用程序,Jooby带有MVC API,与任何其他MVC框架(如Spring MVC)非常相似。

例如,我们可以处理名为’/hello’的路径:

@Path("/submit")
public class PostController {

    @POST
    public String hello() {
        return "Submit Tuyucheng";
    }
}

非常相似,我们可以创建一个处理程序来使用@POST@PUT@DELETE等注解来处理其他HTTP方法。

4.4 处理静态内容

为了提供任何静态内容(如HTML、Javascript、CSS、图像等),我们需要将这些文件放在public目录中。

放置完成后,我们可以从路由将任何URL映射到这些资源:

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

4.5 处理表单

Jooby的Request接口默认处理任何表单对象,而无需使用任何手动类型转换。

假设我们需要通过表单提交员工详细信息,第一步,我们需要创建一个用于保存数据的Employee Bean对象:

public class Employee {
    String id;
    String name;
    String email;

    // standard constructors, getters and setters
}

现在,我们需要创建一个页面来创建表单:

<form enctype="application/x-www-form-urlencoded" action="/submitForm" method="post">
    <label>Employed 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>

接下来,我们将创建一个POST处理程序来处理此表单并获取提交的数据:

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

这里需要注意的是,我们必须将表单enctype声明为application/x-www-form-urlencoded,才能支持动态表单绑定。

4.6 会话

Jooby有3种类型的会话实现:内存会话、签名会话和带存储的内存会话。

内存会话

实现内存中的会话管理非常简单,在这个过程中,Jooby将会话数据存储在内存中,并使用cookie/header来读取/保存会话ID。

{
    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();
    });
}

在上面的例子中,我们使用secret作为密钥来签署数据,并使用该secret创建了一个cookie会话存储。

存储会话

除了内置内存存储外,Jooby还提供以下功能:

  • Caffeine:使用Caffeine缓存的内存会话存储
  • JWT:JSON Web Token会话存储
  • Redis:Redis会话存储

例如,为了实现基于Redis的会话存储,我们需要添加以下Maven依赖:

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

现在我们可以使用下面的代码片段来启用会话管理:

{
    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");
    });
}

这里要注意的一点是,我们可以通过添加以下行将Redis url配置为application.conf中的“db”属性:

redis = "redis://localhost:6379"

有关更多示例,请参阅Jooby文档

5. 测试

测试MVC路由确实很容易,因为路由与某些类的策略绑定,MockRouter允许你执行路由功能。

在测试之前我们需要添加Jooby测试依赖:

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

例如,我们可以快速为默认URL创建一个测试用例:

public class AppUnitTest {

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

在上面的例子中,MockRouter返回路由处理程序生成的值。

Jooby通过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()方法来改变它:

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

在上面的例子中,我们在类级别添加了@JoobyTest注解,也可以在方法级别使用此注解。有关更多示例,请查看Jooby官方文档

6. 总结

在本教程中,我们探索了Jooby项目及其基本功能。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章