«1. Обзор

Bootique — это очень легкая среда JVM без контейнеров с открытым исходным кодом, предназначенная для создания масштабируемых микросервисов следующего поколения. Он построен на основе встроенного сервера Jetty и полностью поддерживает обработчики REST с помощью jax-rs.

В этой статье мы покажем, как создать простое веб-приложение с помощью Bootique.

2. Зависимости Maven

Давайте начнем использовать 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>

Однако Bootique также требует объявления нескольких спецификаций («Bill of Material» €) импорт. Вот почему в pom.xml необходимо добавить следующий раздел \u003cdependencyManagement\u003e:

<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 — вызвать метод exec() Bootique из основного метода:

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, а второй — использовать BQModuleProvider от Bootique, который также известен как автозагрузка.

4.1. Модуль Guice

Здесь мы можем использовать интерфейс модуля Guice для привязки экземпляров:

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

~~ ~ Теперь мы можем использовать аннотацию @Inject для использования экземпляров службы во время выполнения:

@Inject
HelloService helloService;

Здесь важно отметить, что, поскольку мы используем собственный механизм DI Bootique, нам не нужно использовать аннотацию Guice @ImplementedBy для привязки экземпляров службы.

5. Конечная точка REST

Создать конечные точки REST с помощью JAX-RS API очень просто:

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

Чтобы сопоставить конечные точки с собственным экземпляром Джерси Bootique, нам нужно определить 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.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 и т. д. Полный список доступных модулей доступен здесь.

Как всегда, полный исходный код доступен на GitHub.