1. 概述
在这篇教程中,我们将带你快速了解一个轻量级的 Java REST 框架 —— RESTX。
2. 特性一览
使用 RESTX 构建 RESTful API 相当简单。它提供了我们对现代 REST 框架的所有基本预期功能:
✅ JSON 的请求与响应处理
✅ 支持查询参数和路径参数
✅ 路由机制和过滤器机制
✅ 使用统计和监控支持
此外,RESTX 还内置了一个直观的管理后台 Web UI 和命令行工具,用于快速初始化项目。
项目采用 Apache License 2 开源协议,并由社区维护。最低 JDK 要求为 JDK 7。
3. 环境配置
RESTX 提供了一个命令行工具(shell app),可以快速帮你搭建一个 Java 项目。
不过在使用之前,需要先安装这个工具。详细的安装说明可以参考官方文档。
4. 安装核心插件
安装完 shell 工具后,下一步是安装核心插件,这样我们就可以在 shell 中直接创建应用了。
在 RESTX shell 中执行以下命令:
shell install
系统会提示你选择要安装的插件。我们需要选择 io.restx:restx-core-shell
这一项。✅ 安装完成后 shell 会自动重启。
5. 使用 Shell 初始化项目
使用 RESTX shell 初始化项目非常方便,它提供了一个向导式的流程。
在 shell 中执行以下命令开始:
app new
这个命令会启动向导流程,你可以使用默认配置,也可以根据需要自定义:
如果你选择了生成 pom.xml
文件,项目就可以轻松导入到任意标准 Java IDE 中。
有些时候你可能需要调整 IDE 的配置。
接下来我们构建项目:
mvn clean install -DskipTests
✅ 构建成功后,你可以在 IDE 中直接运行 AppServer
类,它会启动一个嵌入式 Jetty 服务器,管理后台默认监听 8080 端口。
访问地址:http://127.0.0.1:8080/api/@/ui
即可看到基本界面。
⚠️ 注意:所有以 /@/
开头的路由是管理后台专用路径,属于保留路径。
登录管理后台的默认用户名是 admin
,密码是你在创建项目时设置的。
在进一步探索之前,我们先来看看向导生成的代码结构。
6. 一个 RESTX 资源类
路由定义在 <main_package>.rest.HelloResource
类中:
@Component
@RestxResource
public class HelloResource {
@GET("/message")
@RolesAllowed(Roles.HELLO_ROLE)
public Message sayHello() {
return new Message().setMessage(String.format("hello %s, it's %s",
RestxSession.current().getPrincipal().get().getName(),
DateTime.now().toString("HH:mm:ss")));
}
}
从代码可以看出,RESTX 使用了标准 J2EE 的注解来处理安全和 REST 绑定,同时也自定义了一些注解来处理依赖注入。
RESTX 对方法参数的映射也支持很多合理的默认行为。比如自动将请求参数映射到方法参数。
⚠️ @RestxResource
是 RESTX 的核心注解,用于标识这是一个 REST 资源类。
基础路径配置在 src/main/webapp/WEB-INF/web.xml
中,默认是 /api
,因此你可以发送 GET 请求到:
http://localhost:8080/api/message
前提是已经完成身份认证。
Message
类只是一个普通的 Java Bean,RESTX 会自动将其序列化为 JSON。
通过 @RolesAllowed
注解,我们可以控制访问权限。示例中使用了向导自动生成的 HELLO_ROLE
权限。
7. 模块类(Module Class)
如前所述,RESTX 使用标准的 J2EE 依赖注入注解,比如 @Named
,同时也在必要时自定义了 @Module
和 @Provides
,灵感可能来源于 Dagger。
这些注解用于定义应用的主模块,其中也包括管理后台的密码配置:
@Module
public class AppModule {
@Provides
public SignatureKey signatureKey() {
return new SignatureKey("restx-demo -44749418370 restx-demo 801f-4116-48f2-906b"
.getBytes(Charsets.UTF_8));
}
@Provides
@Named("restx.admin.password")
public String restxAdminPassword() {
return "1234";
}
@Provides
public ConfigSupplier appConfigSupplier(ConfigLoader configLoader) {
return configLoader.fromResource("restx/demo/settings");
}
// 其他组件创建方法
}
@Module
:声明一个模块类,类似于 Dagger 中的@Module
,或 Spring 中的@Configuration
@Provides
:用于声明一个组件的创建方法,类似 Dagger 的@Provides
或 Spring 的@Bean
@Named
:标识组件名称
AppModule
还提供了一个 SignatureKey
,用来对客户端内容进行签名。例如,创建会话时会设置一个签名 Cookie:
HTTP/1.1 200 OK
...
Set-Cookie: RestxSessionSignature-restx-demo="ySfv8FejvizMMvruGlK3K2hwdb8="; RestxSession-restx-demo="..."
...
更多依赖注入内容可参考 RESTX 组件工厂文档。
8. 启动类(Launcher Class)
最后是 AppServer
类,用于在嵌入式 Jetty 服务器中运行应用:
public class AppServer {
public static final String WEB_INF_LOCATION = "src/main/webapp/WEB-INF/web.xml";
public static final String WEB_APP_LOCATION = "src/main/webapp";
public static void main(String[] args) throws Exception {
int port = Integer.valueOf(Optional.fromNullable(System.getenv("PORT")).or("8080"));
WebServer server =
new Jetty8WebServer(WEB_INF_LOCATION, WEB_APP_LOCATION, port, "0.0.0.0");
System.setProperty("restx.mode", System.getProperty("restx.mode", "dev"));
System.setProperty("restx.app.package", "restx.demo");
server.startAndAwait();
}
}
这里使用了 dev
模式来启用开发阶段的功能,比如自动编译,缩短开发反馈周期。
✅ 你可以将项目打包为 war
文件部署到标准 J2EE 容器中。
9. 使用 Specs 进行集成测试
RESTX 的一大亮点是它的“specs”机制。一个典型的 spec 看起来是这样的:
title: should admin say hello
given:
- time: 2013-08-28T01:18:00.822+02:00
wts:
- when: |
GET hello?who=xavier
then: |
{"message":"hello xavier, it's 01:18:00"}
测试采用 Given-When-Then 结构,写在 YAML 文件中,描述了在给定条件下,某个请求应返回什么样的响应。
HelloResourceSpecTest
类会触发这些测试:
@RunWith(RestxSpecTestsRunner.class)
@FindSpecsIn("specs/hello")
public class HelloResourceSpecTest {}
RestxSpecTestsRunner
是一个自定义的 JUnit Runner,它会:
✅ 启动嵌入式服务器
✅ 设置系统状态(given)
✅ 发送请求(when)
✅ 验证响应(then)
@FindSpecsIn
注解用于指定 spec 文件的位置。
✅ Specs 不仅用于集成测试,还能作为 API 文档中的示例。此外,它还能 模拟 HTTP 请求并记录请求/响应对。
10. 手动测试
你也可以通过 HTTP 手动测试接口。首先需要登录,先在 shell 中对密码进行 MD5 加密:
hash md5 <clear-text-password>
然后调用 /sessions
接口登录:
curl -b u1 -c u1 -X POST -H "Content-Type: application/json"
-d '{"principal":{"name":"admin","passwordHash":"1d528266b85cf052803a57288"}}'
http://localhost:8080/api/sessions
⚠️ Windows 用户需要先 下载 curl。
登录后,带上 Cookie 调用 /message
接口:
curl -b u1 "http://localhost:8080/api/message?who=restx"
会得到类似这样的响应:
{"message" : "hello admin, it's 09:56:51"}
11. 管理后台功能概览
访问地址:http://127.0.0.1:8080/admin/@/ui
11.1. API 文档
API Docs 页面列出了所有可用的接口路由,并支持直接在页面中调用测试:
11.2. 监控
JVM Metrics 页面展示了应用运行时指标,包括:
✅ 活跃会话数
✅ 内存使用情况
✅ 线程堆栈信息
Application Metrics 默认监控两类指标:
BUILD
:组件初始化相关HTTP
:HTTP 请求处理相关
11.3. 统计信息
RESTX 支持收集匿名使用统计信息,帮助社区了解使用情况。你可以通过排除 restx-stats-admin
模块来关闭该功能。
统计信息包括操作系统、JVM 版本等:
⚠️ 该页面包含敏感信息,请务必检查其 配置选项。
此外,管理后台还可以:
✅ 查看日志(Logs)
✅ 查看错误(Errors)
✅ 查看配置项(Config)
12. 权限控制
RESTX 默认对所有接口进行权限控制。 例如下面这个接口:
@GET("/greetings/{who}")
public Message sayHello(String who) {
return new Message(who);
}
如果未认证访问,会返回 401 Unauthorized
。
要让接口公开访问,需要使用 @PermitAll
注解:
@PermitAll
@GET("/greetings/{who}")
public Message sayHello(String who) {
return new Message(who);
}
⚠️ 如果加在类上,整个类的所有接口都会公开。
你也可以通过 @RolesAllowed
指定用户角色:
@RolesAllowed("admin")
@GET("/greetings/{who}")
public Message sayHello(String who) {
return new Message(who);
}
此时,如果用户没有 admin
角色,会返回 403 Forbidden
而不是 401
。
默认情况下,用户信息和角色分别存储在两个文件中:
用户密码文件:/data/credentials.json
{
"user1": "$2a$10$iZluUbCseDOvKnoe",
"user2": "$2a$10$oym3Swr7pScdiCXu"
}
用户角色文件:/data/users.json
[
{"name":"user1", "roles": ["hello"]},
{"name":"user2", "roles": []}
]
这些文件在 AppModule
中通过 FileBasedUserRepository
加载:
new FileBasedUserRepository<>(StdUser.class, mapper,
new StdUser("admin", ImmutableSet.<String> of("*")),
Paths.get("data/users.json"), Paths.get("data/credentials.json"), true)
StdUser
是默认的用户类,你也可以自定义自己的用户类,只要能序列化为 JSON 即可。
当然,你也可以使用自定义的 UserRepository
实现,比如连接数据库的版本。
13. 总结
这篇教程带你快速了解了基于 Java 的轻量级 REST 框架 RESTX。
虽然框架仍在发展中,可能存在一些不完善的地方,但它已经具备了构建 RESTful API 所需的核心功能。
更多内容请参考 官方文档。
示例项目代码已上传至 GitHub 仓库。