1. 概述
Bootique是一款非常轻量级的开源无容器JVM框架,旨在构建下一代可扩展微服务。它建立在嵌入式Jetty服务器之上,并完全支持使用JAX-RS的REST处理程序。
在本文中,我们将展示如何使用Bootique构建一个简单的Web应用程序。
2. Maven依赖
让我们通过在pom.xml中添加以下依赖来开始使用Bootique:
<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导入,因此需要在pom.xml中添加以下<dependencyManagement>部分:
<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的最新版本可在中央仓库中找到。
为了构建可运行的jar,Bootique依赖于maven-shade-plugin,因此我们还需要添加以下配置:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
</plugin>
</plugins>
</build>
3. 启动应用程序
启动Bootique应用程序的最简单方法是从main方法中调用Bootique的exec()方法:
public class App {
public static void main(String[] args) {
Bootique.app(args)
.autoLoadModules()
.exec();
}
}
但是,这不会启动嵌入式服务器,一旦运行上述代码,应该会显示以下日志:
NAME
cn.tuyucheng.taketoday.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将处理剩下的事情:
cn.tuyucheng.taketoday.bootique.module.ModuleProvider
现在,我们可以使用@Inject注解在运行时使用服务实例:
@Inject
HelloService helloService;
这里要注意的一件重要的事情是,由于我们使用的是Bootique自己的DI机制,所以我们不需要使用Guice @ImplementedBy注解来绑定服务实例。
5. REST端点
使用JAX-RS API创建REST端点非常简单:
@Path("/")
public class IndexController {
@GET
public String index() {
return "Hello, tuyucheng!";
}
@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/tuyucheng/bootique/config.yml
7. 日志记录
开箱即用的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.log
8. 测试
为了进行测试,Bootique附带了bootique-test模块,我们可以通过两种方式测试Bootique应用程序。
第一种方法是“前台”方法,它使所有测试用例都在主测试线程上运行。
另一种是“后台”方法,它使测试用例在隔离的线程池上运行。
可以使用BQTestFactory初始化“前台”环境:
@Rule
public BQTestFactory bqTestFactory = new BQTestFactory();
可以使用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等,可用模块的完整列表可在此处查看。
Post Directory
