1. 概述
Bootique 是一個非常輕量級的開源 容器化無 JVM 框架,旨在構建下一代可擴展的微服務。它基於嵌入式 Jetty 服務器,並完全支持 RESTful 處理程序,以及 jax-rs。
在本文中,我們將演示如何使用 Bootique 構建一個簡單的 Web 應用程序。
2. Maven 依賴
讓我們通過將以下依賴項添加到 <em pom.xml</em> 中來使用 <em Bootique</em>>:
<dependency>
<groupId>io.bootique.jersey</groupId>
<artifactId>bootique-jersey</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.bootique</groupId>
<artifactId>bootique-test</artifactId>
<scope>test</scope>
</dependency>
然而,Bootique 也需要聲明一些 BOM (“Bill of Material”) 導入。因此,需要添加如下 <dependencyManagement> 部分到 pom.xml 中:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.bootique.bom</groupId>
<artifactId>bootique-bom</artifactId>
<version>0.23</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>最新版本的 Bootique 已在 中央 Maven 倉庫 中提供。
要構建可執行的 JAR 包,Bootique 依賴於 maven-shade-plugin。 因此,我們也需要添加以下配置:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
</plugin>
</plugins>
</build>3. 啓動應用程序
啓動最簡單的 Bootique 應用程序的方法是,從主方法中調用 Bootique 的 exec() 方法:
public class App {
public static void main(String[] args) {
Bootique.app(args)
.autoLoadModules()
.exec();
}
}然而,這不會啓動嵌入式服務器。 一旦運行上述代碼,以下日誌應顯示:
NAME
com.baeldung.bootique.App
OPTIONS
-c yaml_location, --config=yaml_location
Specifies YAML config location, which can be a file path
or a URL.
-h, --help
Prints this message.
-H, --help-config
Prints information about application modules and their
configuration options.
-s, --server
Starts Jetty server.這些是預裝在 Bootique 應用程序中提供的所有程序參數。
參數名稱具有自解釋性,因此啓動服務器時,我們需要傳遞 –s 或 –server 參數,服務器將啓動並在 默認端口 8080 上運行。
4. 模塊
Bootique 應用程序由“模塊”的集合構建。在Bootique 的定義中,“模塊”是指包含一些代碼的 Java 庫,這意味着它將每個服務都視為一個模塊。它使用 Google Guice 進行依賴注入。
要了解其工作原理,讓我們創建一個接口:
public interface HelloService {
boolean save();
}現在,我們需要創建一個實現:
public class HelloServiceImpl implements HelloService {
@Override
public boolean save() {
return true;
}
}我們可以通過兩種方式加載模塊。第一種方式是使用 Guice 的 Module 接口,另一種方式是使用 Bootique 的 BQModuleProvider,它也被稱為 自動加載。
4.1. Guice 模塊
在這裏,我們可以使用 Guice 的 Module 接口來綁定實例:
public class ModuleBinder implements Module {
@Override
public void configure(Binder binder) {
binder
.bind(HelloService.class)
.to(HelloServiceImpl.class);
}
}一旦模塊定義完成,我們需要將其映射到 Bootique 實例上:
Bootique
.app(args)
.module(module)
.module(ModuleBinder.class)
.autoLoadModules()
.exec();4.2. BQModuleProvider (自動加載)
在這裏,我們只需要定義之前創建的模塊綁定器,使用 BQModuleProvider:
public class ModuleProvider implements BQModuleProvider {
@Override
public Module module() {
return new ModuleBinder();
}
}這種技術的優勢在於,我們無需將任何模塊信息映射到 Bootique 實例上。
我們只需要在 /resources/META-INF/services/io.bootique.BQModuleProvider 中創建一個文件,並寫入 ModuleProvider 的全名(包括包名),Bootique 將自動處理其餘部分:
com.baeldung.bootique.module.ModuleProvider現在,我們可以使用 <em><a href="https://google.github.io/guice/api-docs/latest/javadoc/index.html?com/google/inject/Inject.html">@Inject</a></em> 註解,在運行時使用服務實例:
@Inject
HelloService helloService;需要注意的是,由於我們使用了 Bootique 自身的 DI 機制,因此我們無需使用 Guice 中的 @ImplementedBy 註解來綁定服務實例。
5. REST 端點
使用 JAX-RS API 創建 REST 端點非常簡單:
@Path("/")
public class IndexController {
@GET
public String index() {
return "Hello, baeldung!";
}
@POST
public String save() {
return "Data Saved!";
}
}為了將端點映射到 Bootique 自身的 Jersey 實例中,我們需要定義一個 JerseyModule:
Module module = binder -> JerseyModule
.extend(binder)
.addResource(IndexController.class);6. 配置
我們可以提供基於 YAML 的屬性文件中內置或自定義的配置信息。
例如,如果我們想要在自定義端口上啓動應用程序並添加默認 URI 上下文“hello”,可以使用以下 YAML 配置:
jetty:
context: /hello
connector:
port: 10001現在,啓動應用程序時,我們需要在配置參數中提供該文件的位置:
--config=/home/baeldung/bootique/config.yml7. 日誌記錄
Bootique 默認自帶 bootique-logback 模塊。要使用該模塊,需要在 pom.xml 中添加以下依賴:
<dependency>
<groupId>io.bootique.logback</groupId>
<artifactId>bootique-logback</artifactId>
</dependency>這個模塊包含一個 BootLogger 接口,我們可以在其中進行覆蓋以實現自定義日誌記錄:
Bootique.app(args)
.module(module)
.module(ModuleBinder.class)
.bootLogger( new BootLogger() {
@Override
public void trace( Supplier<String> args ) {
// ...
}
@Override
public void stdout( String args ) {
// ...
}
@Override
public void stderr( String args, Throwable thw ) {
// ...
}
@Override
public void stderr( String args ) {
// ...
}
}).autoLoadModules().exec();此外,我們還可以通過在 config.yaml文件中定義日誌記錄配置信息:
log:
level: warn
appenders:
- type: file
logFormat: '%c{20}: %m%n'
file: /path/to/logging/dir/logger.log8. 測試
對於測試,Bootique 附帶了 bootique-test 模塊。我們可以通過兩種方式來測試一個 Bootique 應用程序。
第一種方法是 “前置” 方式,它使所有測試用例在主測試線程上運行。
另一種方法是 “後台” 方式,它使測試用例在隔離的線程池中運行。
“前置” 環境可以使用 BQTestFactory 初始化:
@Rule
public BQTestFactory bqTestFactory = new BQTestFactory();“background”環境可以使用BQDaemonTestFactory進行初始化:
@Rule
public BQDaemonTestFactory bqDaemonTestFactory = new BQDaemonTestFactory();一旦環境工廠準備就緒,我們就可以編寫簡單的測試用例來測試服務:
@Test
public void givenService_expectBoolen() {
BQRuntime runtime = bqTestFactory
.app("--server").autoLoadModules()
.createRuntime();
HelloService service = runtime.getInstance( HelloService.class );
assertEquals( true, service.save() );
}9. 結論
在本文中,我們展示瞭如何使用 Bootique 的核心模塊構建應用程序。 還有其他 Bootique 模塊可用,例如 bootique-jooq,bootique-kotlin,bootique-job 等。 可用的模塊完整列表可以在 這裏 找到。