1. 概述

Bootique 是一款轻量级开源的无容器 JVM 框架,专为构建下一代可扩展微服务设计。它基于嵌入式 Jetty 服务器,并通过 JAX-RS 完整支持 REST 接口处理。

本文将演示如何使用 Bootique 构建一个简单的 Web 应用。⚠️ 踩坑提示:虽然 Bootique 设计简洁,但首次接触时需注意其模块化特性与常规框架的差异。

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(Bill of Material) 导入。因此在 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>

最新版本可查阅 中央 Maven 仓库

为构建可执行 JAR,Bootique 依赖 maven-shade-plugin。需补充以下配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
        </plugin>
    </plugins>
</build>

3. 启动应用

最简单的启动方式是在 main 方法中调用 Bootique.app(args).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
           指定 YAML 配置路径(支持文件路径或 URL)

      -h, --help
           打印帮助信息

      -H, --help-config
           打印模块及配置选项说明

      -s, --server
           启动 Jetty 服务器

这些是 Bootique 预置的命令行参数。✅ 要启动服务器,需添加 --server 参数(或简写 -s),默认监听 8080 端口

4. 模块系统

Bootique 应用由 模块 集合构成。在 Bootique 中,“模块即包含代码的 Java 库”——它将每个服务视为独立模块,并使用 Google Guice 实现依赖注入。

4.1 定义服务接口

public interface HelloService {
    boolean save();
}

4.2 实现服务

public class HelloServiceImpl implements HelloService {
 
    @Override
    public boolean save() {
        return true;
    }
}

4.3 模块加载方式

Bootique 提供两种模块加载方式:

方式一:Guice Module
通过 Module 接口绑定实例:

public class ModuleBinder implements Module {
 
    @Override
    public void configure(Binder binder) {
        binder
          .bind(HelloService.class)
          .to(HelloServiceImpl.class);
    }
}

然后在启动时手动注册:

Bootique
  .app(args)
    .module(module)
    .module(ModuleBinder.class)
  .autoLoadModules()
  .exec();

方式二:BQModuleProvider(自动加载)
✅ 推荐方式:通过 BQModuleProvider 定义模块:

public class ModuleProvider implements BQModuleProvider {
 
    @Override
    public Module module() {
        return new ModuleBinder();
    }
}

优势:无需手动注册模块。只需在 /resources/META-INF/services/io.bootique.BQModuleProvider 文件中写入实现类全限定名:

com.baeldung.bootique.module.ModuleProvider

运行时通过 @Inject 注解即可获取服务实例:

@Inject
HelloService helloService;

踩坑提示:Bootique 自带 DI 机制,无需使用 Guice 的 @ImplementedBy 注解!

5. REST 接口开发

使用 JAX-RS 创建 REST 接口非常简单粗暴:

@Path("/")
public class IndexController {
 
    @GET
    public String index() {
        return "Hello, baeldung!";
    }
 
    @POST
    public String save() {
        return "Data Saved!";
    }
}

需通过 JerseyModule 将控制器注册到 Bootique:

Module module = binder -> JerseyModule
  .extend(binder)
  .addResource(IndexController.class);

6. 配置管理

支持通过 YAML 文件配置内置或自定义参数。例如修改端口和上下文路径:

jetty:
    context: /hello
    connector:
        port: 10001

启动时通过 --config 参数指定配置文件路径:

--config=/home/user/bootique/config.yml

7. 日志集成

开箱即用支持 bootique-logback 模块。添加依赖:

<dependency>
    <groupId>io.bootique.logback</groupId>
    <artifactId>bootique-logback</artifactId>
</dependency>

可通过 BootLogger 接口实现自定义日志:

Bootique.app(args)
  .module(module)
  .bootLogger(new BootLogger() {
      @Override
      public void trace(Supplier<String> supplier) {
          // 自定义 trace 实现
      }
      @Override
      public void stdout(String message) {
          // 标准输出处理
      }
      @Override
      public void stderr(String message, Throwable th) {
          // 错误输出处理
      }
      @Override
      public void stderr(String message) {
          // 错误输出处理(无异常)
      }
  })
  .autoLoadModules()
  .exec();

或在 YAML 中配置日志格式:

log:
    level: warn
    appenders:
    - type: file
      logFormat: '%c{20}: %m%n'
      file: /var/log/bootique/app.log

8. 测试支持

通过 bootique-test 模块提供测试能力。包含两种测试模式:

8.1 前台测试(主线程执行)

@Rule
public BQTestFactory bqTestFactory = new BQTestFactory();

8.2 后台测试(独立线程池)

@Rule
public BQDaemonTestFactory bqDaemonTestFactory = new BQDaemonTestFactory();

示例测试用例

@Test
public void givenService_whenCallSave_thenReturnsTrue() {
    BQRuntime runtime = bqTestFactory
      .app("--server")
      .autoLoadModules()
      .createRuntime();
      
    HelloService service = runtime.getInstance(HelloService.class);
    assertEquals(true, service.save());
}

9. 总结

本文演示了使用 Bootique 核心模块构建应用的基础流程。该框架还提供丰富的扩展模块:

  • bootique-jooq:数据库访问层
  • bootique-kotlin:Kotlin 支持
  • bootique-job:任务调度

完整模块列表请查阅 GitHub 仓库。对于追求极致轻量化和模块化设计的微服务架构,Bootique 值得尝试!


原始标题:Introduction to Bootique | Baeldung