1. 概述
本教程將帶您瞭解輕量級 Java REST 框架 RESTX。
2. 功能特性
使用 RESTX 框架構建 RESTful API 非常簡單。它包含了我們從 REST 框架中期望的所有默認功能,例如服務和消費 JSON 數據、查詢和路徑參數、路由和過濾機制、使用統計信息以及監控。
RESTX 還配備了直觀的管理員 Web 控制枱和命令行安裝程序,方便快速啓動。
此外,RESTX 採用 Apache License 2 許可,並由開發人員社區維護。 RESTX 的最低 Java 需求是 JDK 7。
3. 配置
RESTX 提供了一個便捷的 Shell/命令行應用,可用於快速啓動 Java 項目。
在繼續之前,您需要先安裝該應用。詳細的安裝説明請參考 這裏。
4. 安裝核心插件
現在,是時候安裝核心插件,以便您可以使用 shell 本身創建應用程序。
在 RESTX shell 中,請運行以下命令:
shell install它隨後會提示我們選擇要安裝的插件。我們需要選擇指向 io.restx:restx-core-shell 的編號。安裝完成後,殼層會自動重啓。
5. Shell App 啓動引導
使用 RESTX shell,非常方便地啓動新的應用程序。它提供了一種基於嚮導的引導方式。
我們首先在 shell 上執行以下命令:
app new此命令將觸發嚮導。然後我們可以選擇使用默認選項或根據我們的要求進行更改。
由於我們選擇了生成一個 pom.xml,該項目可以輕鬆導入到任何標準的 Java IDE 中。
在某些情況下,我們可能需要調整 IDE 設置。
下一步將是構建項目:
mvn clean install -DskipTests構建成功後,我們可以從 IDE 中以 Java 應用程序運行 AppServer 類。這將啓動服務器,並使用管理控制枱,監聽 8080 端口。
可以瀏覽到 http://127.0.0.1:8080/api/@/ui,查看基本 UI。
以 /@/ 開頭的路由用於管理控制枱,這是 RESTX 中預留的路徑。
要登錄管理控制枱,可以使用默認用户名“admin”和我們在創建應用程序時提供的密碼。
在玩轉控制枱之前,讓我們探索代碼並瞭解魔術師生成的代碼。
6. RESTX 資源
路由定義在 <em>main_package 類中的 <em>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 識別的資源。
基本路徑在 src/main/webapp/WEB-INF/web.xml 中添加。 在我們的例子中,它是 /api,因此我們可以向 http://localhost:8080/api/message 發送 GET 請求,前提是已正確配置身份驗證。
Message 類只是 RESTX 將其序列化為 JSON 的 Java Bean。
我們通過使用由啓動器生成的 HELLO_ROLE 註解來控制用户訪問權限。
7. 模塊類
如前所述,RESTX 使用 J2EE 標準的依賴注入註解,例如 @Named,並在需要時自行創建,很可能受到了 Dagger 框架中 @Module 和 @Provides 的啓發。
它利用這些註解來創建應用程序的主模塊,該模塊中定義了管理員密碼等。
@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");
}
// other provider methods to create components
}@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 類
最後,AppServer 類用於在嵌入式 Jetty 服務器上以標準 Java 應用的形式運行應用程序:
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();
}
}在此,開發模式在開發階段用於啓用諸如自動編譯等功能,從而縮短開發反饋循環。
我們可以將應用程序打包為 WAR文件(Web存檔)以在獨立 J2EE Web 容器中部署。
在下一部分中,我們將瞭解如何測試該應用程序。
9. 使用規範進行集成測試
RESTX 的強大功能之一是其“規範”的概念。一個示例 規範 如下所示:
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 文件中定義,該文件基本上描述了 API 應該如何響應(then)針對特定請求(when)在當前系統狀態下(given)。
位於 src/test/resources 目錄中的 HelloResourceSpecTest 類將觸發上述規範中的測試。
@RunWith(RestxSpecTestsRunner.class)
@FindSpecsIn("specs/hello")
public class HelloResourceSpecTest {}RestxSpecTestsRunner 類是一個自定義的 JUnit 運行器。它包含自定義的 JUnit 規則,用於:
- 設置嵌入式服務器
- 準備系統狀態(根據規範中的given 部分)
- 發出指定的請求,以及
- 驗證預期的響應
@FindSpecsIn 註解指向用於運行測試的規範文件路徑。
規範有助於編寫集成測試並提供 API 文檔中的示例。規範還對模擬 HTTP 請求和記錄請求/響應對有幫助。
10. 手動測試
我們還可以通過 HTTP 進行手動測試。首先,我們需要登錄。為此,需要在 RESTX 控制枱中對管理員密碼進行哈希處理:
hash md5 <clear-text-password>然後我們可以將它傳遞到 sessions</em/> 端點:
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)
現在,如果我們使用 session 作為我們的 /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 文檔部分列出了所有可用的路由,包括所有選項:
我們還可以點擊單個路由並嘗試在控制枱中執行:
11.2. 監控
《JVM 指標》部分顯示了具有活動會話、內存使用情況和線程轉儲的應用程序指標:
在《應用程序指標》下,我們默認監控了兩種主要類別:
- BUILD 對應於應用程序組件的實例化
- HTTP 對應於 RESTX 處理的 HTTP 請求
11.3. 統計數據
RESTX 允許用户選擇收集和分享應用程序的匿名統計數據,以便向 RESTX 社區提供信息。 我們可以輕鬆地通過排除 restx-stats-admin 模塊來取消收集統計數據。
統計數據報告包括底層操作系統和 JVM 版本:
除了這些之外,管理控制枱還可以幫助我們:
- 查看服務器日誌(Logs)
- 查看遇到的錯誤(Errors)
- 檢查環境變量(Config)
12. 授權
RESTX 端點默認已啓用安全保護。這意味着對於任何端點:
@GET("/greetings/{who}")
public Message sayHello(String who) {
return new Message(who);
}當不進行身份驗證時,將默認返回一個 401 錯誤。
為了使某個端點公開,我們需要在方法或類級別使用 @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);
}通過此註解,RESTX 將驗證已認證的用户是否也擁有 admin 角色。如果未擁有 admin 角色且已認證的用户嘗試訪問該端點,應用程序將返回 403 而不是 401。
默認情況下,用户角色和憑據存儲在文件系統中,通過單獨的文件進行管理。
因此,包含加密密碼的用户 ID 存儲在 /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 的輕量級 RESTX 框架。
該框架仍在開發中,使用時可能存在一些不完善之處。請訪問 官方文檔 以獲取更多詳細信息。