Einführung in Bootique

Einführung in Bootique

1. Überblick

Bootique ist ein sehr leichtes Open-Source-JVM-Framework voncontainer-less, mit dem skalierbare Mikrodienste der nächsten Generation erstellt werden sollen. Es basiert auf dem eingebetteten Jetty-Server und unterstützt die Handler vonRESTmitjax-rs vollständig.

In diesem Artikel zeigen wir, wie Sie mitBootique eine einfache Webanwendung erstellen.

2. Maven-Abhängigkeiten

Beginnen wir mit der Verwendung vonBootique, indem wir die folgenden Abhängigkeiten zupom.xml: hinzufügen


    io.bootique.jersey
    bootique-jersey
    compile


    io.bootique
    bootique-test
    test

FürBootique müssen jedoch auch einigeBOM (“Bill of Material”) Importe deklariert werden. Aus diesem Grund muss der folgende Abschnitt von<dependencyManagement>inpom.xml:hinzugefügt werden


    
        
            io.bootique.bom
            bootique-bom
            0.23
            pom
            import
        
    

Die neueste Version vonBootique ist inCentral Maven Repository verfügbar.

Um ein lauffähiges Glas zu erstellen, istBootique aufmaven-shade-plugin angewiesen. Aus diesem Grund müssen wir auch folgende Konfiguration hinzufügen:


    
        
            org.apache.maven.plugins
            maven-shade-plugin
        
    

3. Starten einer Anwendung

Der einfachste Weg, eineBootique-Anwendung zu starten, besteht darin, dieBootiqueexec()-Methode von der Hauptmethode aus aufzurufen:

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

However, this won’t start the embedded server. Sobald der obige Code ausgeführt wurde, sollte das folgende Protokoll angezeigt werden:

NAME
      com.example.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.

Dies sind nichts anderes als die verfügbaren Programmargumente, die mitBootique vorgebündelt sind.

Die Namen sind selbsterklärend; Um den Server zu starten, müssen wir entweder das Argument–s oder–server übergeben, und der Server ist auf demdefault port 8080 betriebsbereit.

4. Module

Bootique Anwendungen werden mit Sammlungen von „Modulen“ erstellt. InBootique Term“A module is a Java library that contains some code”, was bedeutet, dass jeder Dienst als Modul behandelt wird. Es verwendetGoogle Guice für die Abhängigkeitsinjektion.

Um zu sehen, wie es funktioniert, erstellen wir eine Schnittstelle:

public interface HelloService {
    boolean save();
}

Nun müssen wir eine Implementierung erstellen:

public class HelloServiceImpl implements HelloService {

    @Override
    public boolean save() {
        return true;
    }
}

Es gibt zwei Möglichkeiten, wie wir das Modul laden können. Die erste besteht darin, dieGuiceModule-Schnittstelle zu verwenden, und die andere besteht darin,BootiqueBQModuleProvider zu verwenden, was auch alsauto-loading bezeichnet wird.

4.1. Guice-Modul

Hier können wir dieGuice-Schnittstelle vonGuiceverwenden, um Instanzen zu binden:

public class ModuleBinder implements Module {

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

Sobald das Modul definiert ist, müssen wir dieses benutzerdefinierte Modul der Instanz vonBootiquezuordnen:

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

4.2. BQModuleProvider (automatisches Laden)

Hier müssen wir nur den zuvor erstellten Modulbinder mitBQModuleProvider definieren:

public class ModuleProvider implements BQModuleProvider {

    @Override
    public Module module() {
        return new ModuleBinder();
    }
}

Der Vorteil dieser Technik besteht darin, dass wir der Instanz vonBootiquekeine Modulinformationen zuordnen müssen.

Wir müssen nur eine Datei in/resources/META-INF/services/io.bootique.BQModuleProvider erstellen und den vollständigen Namen derModuleProvider einschließlich des Paketnamens schreiben, undBootique erledigt den Rest:

com.example.bootique.module.ModuleProvider

Jetzt können wir die Annotation@Injectverwenden, um die Dienstinstanzen zur Laufzeit zu verwenden:

@Inject
HelloService helloService;

Eine wichtige Sache, die hier zu beachten ist, ist, dass wir, da wir den eigenen DI-Mechanismus vonBootiqueverwenden, die Annotation vonGuice @ImplementedBynicht zum Binden der Dienstinstanzen verwenden müssen.

5. REST-Endpunkt

Es ist einfach, REST-Endpunkte mithilfe der JAX-RS-API zu erstellen:

@Path("/")
public class IndexController {

    @GET
    public String index() {
        return "Hello, example!";
    }

    @POST
    public String save() {
        return "Data Saved!";
    }
}

Um die Endpunkte der eigenenJersey-Instanz vonBootiquezuzuordnen, müssen wirJerseyModuledefinieren:

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

6. Aufbau

Wir können eingebaute oder benutzerdefinierte Konfigurationsinformationen in einer YAML-basierten Eigenschaftendatei bereitstellen.

Wenn wir beispielsweise die Anwendung auf einem benutzerdefinierten Port starten und einen Standard-URI-Kontext "Hallo" hinzufügen möchten, können wir die folgende YAML-Konfiguration verwenden:

jetty:
    context: /hello
    connector:
        port: 10001

Nun müssen wir beim Starten der Anwendung den Speicherort dieser Datei im Konfigurationsparameter angeben:

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

7. Protokollierung

Out-of-the-BoxBootique wird mit einembootique-logback-Modul geliefert. Um dieses Modul zu verwenden, müssen wir die folgenden Abhängigkeiten inpom.xml hinzufügen:


    io.bootique.logback
    bootique-logback

Dieses Modul verfügt über eineBootLogger-Schnittstelle, die wir überschreiben können, um die benutzerdefinierte Protokollierung zu implementieren:

Bootique.app(args)
  .module(module)
  .module(ModuleBinder.class)
    .bootLogger( new BootLogger() {
      @Override
      public void trace( Supplier args ) {
          // ...
      }
      @Override
      public void stdout( String args ) {
          // ...
      }
      @Override
      public void stderr( String args, Throwable thw ) {
          // ...
      }
      @Override
      public void stderr( String args ) {
          // ...
      }
}).autoLoadModules().exec();

Außerdem können wir Informationen zur Protokollierungskonfiguration in der Dateiconfig.yamldefinieren:

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

8. Testen

Zum Testen wirdBootique mit dem Modulbootique-test geliefert. Es gibt zwei Möglichkeiten, wie wir die Anwendung vonBootiquetesten können.

Der erste Ansatz ist der Ansatz von‘foreground', bei dem alle Testfälle auf dem Haupttest-Thread ausgeführt werden.

Der andere ist der Ansatz von‘background', bei dem die Testfälle in einem isolierten Thread-Pool ausgeführt werden.

Die Vordergrundumgebung kann mitBQTestFactory initialisiert werden:

@Rule
public BQTestFactory bqTestFactory = new BQTestFactory();

Die Hintergrundumgebung kann mitBQDaemonTestFactory initialisiert werden:

@Rule
public BQDaemonTestFactory bqDaemonTestFactory = new BQDaemonTestFactory();

Sobald die Umgebungsfabrik fertig ist, können wir einfache Testfälle schreiben, um die Dienste zu testen:

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

    assertEquals( true, service.save() );
}

9. Fazit

In diesem Artikel haben wir gezeigt, wie eine Anwendung mit den Kernmodulen vonBootiqueerstellt wird. Es sind mehrere andereBootique-Module verfügbar, z. B.bootique-jooq,bootique-kotlin,bootique-job usw. Die vollständige Liste der verfügbaren Module ist inhere verfügbar.

Wie immer ist der vollständige Quellcodeover on GitHub. verfügbar