Introduction to Bootique – Bootique简介

最后修改: 2017年 8月 7日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Bootique is a very lightweight open-source container-less JVM framework aimed to build next-generation scalable micro-services. It’s built on top of embedded Jetty server and fully supports REST handlers with jax-rs.

Bootique是一个非常轻量级的开源无容器JVM框架,旨在构建下一代可扩展的微服务。它建立在嵌入式Jetty服务器之上,并完全支持REST处理程序与jax-rs

In this article, we’ll show how to build a simple web application using Bootique.

在这篇文章中,我们将展示如何使用Bootique构建一个简单的网络应用。

2. Maven Dependencies

2.Maven的依赖性

Let’s start to use Bootique by adding the following dependency into the pom.xml:

让我们开始使用Bootique,在pom.xml中添加以下依赖项:

<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>

However, Bootique also requires declaring a few BOM (“Bill of Material”) imports. That’s why following <dependencyManagement> section needs to be added in the pom.xml:

然而,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>

The latest version of Bootique is available in Central Maven Repository.

Bootique的最新版本可在Central Maven Repository中找到。

To build a runnable jar, Bootique relies on maven-shade-plugin. That’s why we also need to add below configuration as well:

为了构建一个可运行的jar,Bootique依赖于maven-shad-plugin。这就是为什么我们还需要添加以下配置。

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

3. Starting an Application

3.开始申请

The simplest way to start a Bootique application is to invoke Bootique‘s exec() method from the main method:

启动Bootique应用程序的最简单方法是调用Bootiqueexec()方法。

public class App {
    public static void main(String[] args) {
        Bootique.app(args)
          .autoLoadModules()
          .exec();
    }
}

However, this won’t start the embedded server. Once, the above code is run, following log should be displayed:

然而,这不会启动嵌入式服务器。一旦,上述代码被运行,应该显示以下日志。

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.

These are nothing but the available program arguments that comes pre-bundled with Bootique.

这些只不过是预先捆绑在Bootique中的可用程序参数。

The names are self-explanatory; hence, to start the server we need to pass either –s or –server argument and the server will be up and running on the default port 8080.

这些名字不言自明;因此,要启动服务器,我们需要传递-s-server参数,服务器将在默认端口8080上启动和运行。

4. Modules

4.模块

Bootique applications are made with collections of “modules”. In Bootique‘s term “A module is a Java library that contains some code” which means it treats every service as a module. It uses Google Guice for Dependency Injection.

Bootique应用程序是由 “模块 “集合而成的。在Bootique的术语中,“模块是一个包含一些代码的Java库”,这意味着它将每个服务都视为一个模块。它使用Google Guice进行依赖注入。

To see how it works, let’s create one interface:

为了看看它是如何工作的,让我们创建一个界面。

public interface HelloService {
    boolean save();
}

Now, we need to create an implementation:

现在,我们需要创建一个实现。

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

There are two ways, in which we can load the module. The first one is to use Guice‘s Module interface, and the other one is by using Bootique‘s BQModuleProvider which is also known as auto-loading.

有两种方法,我们可以加载模块。第一种是使用GuiceModule接口,另一种是通过使用BootiqueBQModuleProvider,也被称为自动加载

4.1. Guice Module

4.1.Guice模块

Here, we can use Guice‘s Module interface to bind instances:

在这里,我们可以使用GuiceModule接口来绑定实例。

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

Once the module is defined, we need to map this custom module to the Bootique instance:

一旦模块被定义,我们需要将这个自定义模块映射到Bootique实例。

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

4.2. BQModuleProvider (auto-loading)

4.2.BQModuleProvider(自动加载)

Here, all we need to do is to define the earlier created module-binder with BQModuleProvider:

在这里,我们需要做的是用BQModuleProvider定义先前创建的模块绑定器。

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

The advantage of this technique is that we don’t need to map any module information with the Bootique instance.

这种技术的优点是,我们不需要将任何模块信息与Bootique实例进行映射。

We just need to create a file in /resources/META-INF/services/io.bootique.BQModuleProvider and write the full name of the ModuleProvider including package name and Bootique will take care of the rest:

我们只需要在/resources/META-INF/services/io.bootique.BQModuleProvider中创建一个文件,并写入ModuleProvider的全名,包括包名,Bootique将负责其他工作。

com.baeldung.bootique.module.ModuleProvider

Now, we can use @Inject annotation to use the service instances at the runtime:

现在,我们可以使用@Inject注解来在运行时使用服务实例。

@Inject
HelloService helloService;

One important thing to note here is that since we’re using Bootique‘s own DI mechanism, we don’t need to use Guice @ImplementedBy annotation for binding the service instances.

这里需要注意的一件事是,由于我们使用的是Bootique自己的DI机制,我们不需要使用Guice @ImplementedBy注解来绑定服务实例。

5. REST Endpoint

5.REST端点

It’s straightforward to create REST endpoints using JAX-RS API:

使用JAX-RS API创建REST端点是很直接的。

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

To map the endpoints into the Bootique‘s own Jersey instance, we need to define a JerseyModule:

为了将端点映射到Bootique自己的Jersey实例,我们需要定义一个JerseyModule

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

6. Configuration

6.配置

We can provide inbuilt or custom configuration information in a YAML-based property file.

我们可以在基于YAML的属性文件中提供内置的或自定义的配置信息。

For example, if we want to start the application on a custom port and add a default URI context ‘hello’, we can use following YAML configuration:

例如,如果我们想在一个自定义端口上启动应用程序,并添加一个默认的URI上下文 “hello”,我们可以使用以下YAML配置。

jetty:
    context: /hello
    connector:
        port: 10001

Now, while starting the application, we need to provide this file’s location in the config parameter:

现在,在启动应用程序时,我们需要在配置参数中提供这个文件的位置。

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

7. Logging

7.登录

Out-of-the-box Bootique comes with a bootique-logback module. To use this module, we need to add the following dependency in the pom.xml:

开箱即用的Bootique带有一个bootique-logback模块。要使用这个模块,我们需要在pom.xml中添加以下依赖项。

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

This module comes with a BootLogger interface with we can override to implement custom logging:

这个模块带有一个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();

Also, we can define logging configuration information in the config.yaml file:

另外,我们可以在config.yaml文件中定义日志配置信息。

log:
    level: warn
    appenders:
    - type: file
      logFormat: '%c{20}: %m%n'
      file: /path/to/logging/dir/logger.log

8. Testing

8.测试

For testing, Bootique comes with the bootique-test module. There are two ways by which we can test a Bootique application.

对于测试,Bootique带有bootique-test模块。有两种方法可以让我们测试Bootique应用程序。

The first approach is ‘foreground’ approach which makes all test-cases run on the main test thread.

第一种方法是‘foreground’方法,它使所有测试案例在主测试线程上运行。

The other one is ‘background’ approach which makes the test-cases run on an isolated thread pool.

另一种是‘background’方法,它使测试案例在一个孤立的线程池上运行。

The ‘foreground’ environment can be initialized using BQTestFactory:

前台 “环境可以使用BQTestFactory来初始化。

@Rule
public BQTestFactory bqTestFactory = new BQTestFactory();

The ‘background’ environment can be initialized using BQDaemonTestFactory:

背景 “环境可以使用BQDaemonTestFactory进行初始化。

@Rule
public BQDaemonTestFactory bqDaemonTestFactory = new BQDaemonTestFactory();

Once the environment factory is ready we can write simple test-cases to test the services:

一旦环境工厂准备就绪,我们就可以编写简单的测试案例来测试服务。

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

9. Conclusion

9.结论

In this article, we showed how to build an application using Bootique‘s core modules. There are several other Bootique modules available like bootique-jooq, bootique-kotlin, bootique-job, etc. The full list of available modules is available here.

在这篇文章中,我们展示了如何使用Bootique的核心模块构建一个应用程序。还有其他几个Bootique模块可用,如bootique-jooqbootique-kotlinbootique-job,等等。可用模块的完整列表可在这里获得。

Like always, the full source code is available over on GitHub.

像往常一样,完整的源代码可以在GitHub上获得