Einführung in das Micronaut Framework

Einführung in das Micronaut Framework

1. Was ist Micronaut?

Micronaut ist ein JVM-basiertes Framework zum Erstellen leichter, modularer Anwendungen. Entwickelt von OCI, dem gleichen Unternehmen, das Grails erstellt hat,Micronaut is the latest framework designed to make creating microservices quick and easy.

Während Micronaut einige Funktionen enthält, die bestehenden Frameworks wie Spring ähneln, hat es auch einige neue Funktionen, die es auszeichnen. Mit der Unterstützung für Java, Groovy und Kotlin bietet es eine Vielzahl von Möglichkeiten zum Erstellen von Anwendungen.

2. Haupteigenschaften

Eine der aufregendsten Funktionen von Micronaut ist der zeitabhängige Kompilierungsmechanismus. Die meisten Frameworks verwenden Reflection und Proxys, um zur Laufzeit eine Abhängigkeitsinjektion durchzuführen. Micronaut, however, builds its dependency injection data at compile time. Das Ergebnis ist ein schnellerer Start der Anwendung und ein geringerer Speicherbedarf.

Another feature is its first class support for reactive programming, for both clients and servers. Die Auswahl einer bestimmten reaktiven Implementierung bleibt dem Entwickler überlassen, da sowohl RxJava als auch Project Reactor unterstützt werden.

Micronaut verfügt auch über mehrere Funktionen, die es zu einem hervorragenden Framework für die Entwicklung von Cloud-nativen Anwendungen machen. It supports multiple service discovery tools such as Eureka and Consul, and also works with different distributed tracing systems such as Zipkin and Jaeger.

Es bietet auch Unterstützung für die Erstellung von AWS-Lambda-Funktionen, wodurch die Erstellung serverloser Anwendungen vereinfacht wird.

3. Anfangen

Der einfachste Weg, um loszulegen, ist die Verwendung vonSDKMAN:

> sdk install micronaut 1.0.0.RC2

Dadurch werden alle Binärdateien installiert, die zum Erstellen, Testen und Bereitstellen von Micronaut-Anwendungen erforderlich sind. Es enthält auch das Micronaut CLI-Tool, mit dem wir problemlos neue Projekte starten können.

Die binären Artefakte sind auch fürSonatype undGitHub verfügbar.

In den folgenden Abschnitten werden einige Funktionen des Frameworks vorgestellt.

4. Abhängigkeitsspritze

Wie bereits erwähnt, verarbeitet Micronaut die Abhängigkeitsinjektion zur Kompilierungszeit, was sich von den meisten IoC-Containern unterscheidet.

Es ist jedoch immer nochfully supports JSR-330 annotations, so dass die Arbeit mit Beans anderen IoC-Frameworks ähnlich ist.

Um eine Bean automatisch in unseren Code zu verdrahten, verwenden wir@Inject:

@Inject
private EmployeeService service;

Die Annotation@Inject funktioniert genau wie@Autowired und kann für Felder, Methoden, Konstruktoren und Parameter verwendet werden.

Standardmäßig werden alle Beans als Prototyp definiert. Mit@Singleton. können wir schnell Singleton-Beans erstellen. Wenn mehrere Klassen dieselbe Bean-Schnittstelle implementieren, können sie mit@Primary dekonfliktiert werden:

@Primary
@Singleton
public class BlueCar implements Car {}

Die Annotation@Requires kann verwendet werden, wenn Beans optional sind, oder um das automatische Verdrahten nur durchzuführen, wenn bestimmte Bedingungen erfüllt sind.

In dieser Hinsicht verhält es sich ähnlich wie die Anmerkungen des Spring Boot@Conditional:

@Singleton
@Requires(beans = DataSource.class)
@Requires(property = "enabled")
@Requires(missingBeans = EmployeeService)
@Requires(sdk = Sdk.JAVA, value = "1.8")
public class JdbcEmployeeService implements EmployeeService {}

5. Erstellen eines HTTP-Servers

Schauen wir uns nun die Erstellung einer einfachen HTTP-Serveranwendung an. Zunächst erstellen wir mit SDKMAN ein Projekt:

> mn create-app hello-world-server -build maven

Dadurch wird ein neues Java-Projekt mit Maven in einem Verzeichnis mit dem Namenhello-world-server.erstellt. In diesem Verzeichnis finden Sie unseren Hauptanwendungsquellcode, die Maven-POM-Datei und andere Unterstützungsdateien für das Projekt.

Die Standardanwendung, die sehr einfach ist:

public class ServerApplication {
    public static void main(String[] args) {
        Micronaut.run(ServerApplication.class);
    }
}

5.1. HTTP blockieren

Diese Anwendung allein macht nicht viel. Fügen wir einen Controller mit zwei Endpunkten hinzu. Beide geben eine Begrüßung zurück, aber einer verwendet das HTTP-VerbGET und der anderePOST:

@Controller("/greet")
public class GreetController {

    @Inject
    private GreetingService greetingService;

    @Get("/{name}")
    public String greet(String name) {
        return greetingService.getGreeting() + name;
    }

    @Post(value = "/{name}", consumes = MediaType.TEXT_PLAIN)
    public String setGreeting(@Body String name) {
        return greetingService.getGreeting() + name;
    }
}

5.2. Reaktives IO

Standardmäßig implementiert Micronaut diese Endpunkte mithilfe herkömmlicher blockierender E / A. we can quickly implement non-blocking endpoints by merely changing the return type to any reactive non-blocking type.

Zum Beispiel können wir mit RxJavaObservable verwenden. Ebenso können wir bei Verwendung von Reactor die DatentypenMono oderFlux zurückgeben:

@Get("/{name}")
public Mono greet(String name) {
    return Mono.just(greetingService.getGreeting() + name);
}

Für blockierende und nicht blockierende Endpunkte ist Netty der zugrunde liegende Server, der zur Verarbeitung von HTTP-Anforderungen verwendet wird.

Normalerweise werden die Anforderungen im Haupt-E / A-Thread-Pool verarbeitet, der beim Start erstellt wird, wodurch sie blockiert werden.

Wenn jedoch ein nicht blockierender Datentyp von einem Controller-Endpunkt zurückgegeben wird, verwendet Micronaut den Netty-Ereignisschleifenthread, wodurch die gesamte Anforderung nicht blockiert wird.

6. Erstellen eines HTTP-Clients

Erstellen wir nun einen Client, der die soeben erstellten Endpunkte verwendet. Micronaut bietet zwei Möglichkeiten zum Erstellen von HTTP-Clients:

  • Ein deklarativer HTTP-Client

  • Ein programmatischer HTTP-Client

6.1 Declarative HTTP Client

Die erste und schnellste Methode zum Erstellen ist die Verwendung eines deklarativen Ansatzes:

@Client("/greet")
public interface GreetingClient {
    @Get("/{name}")
    String greet(String name);
}

Beachten Sie, wiewe don’t implement any code to call our service. Stattdessen versteht Micronaut, wie der Service anhand der von uns bereitgestellten Methodensignatur und Anmerkungen aufgerufen wird.

Um diesen Client zu testen, können wir einen JUnit-Test erstellen, der die eingebettete Server-API verwendet, um eine eingebettete Instanz unseres Servers auszuführen:

public class GreetingClientTest {
    private EmbeddedServer server;
    private GreetingClient client;

    @Before
    public void setup() {
        server = ApplicationContext.run(EmbeddedServer.class);
        client = server.getApplicationContext().getBean(GreetingClient.class);
    }

    @After
    public void cleanup() {
        server.stop();
    }

    @Test
    public void testGreeting() {
        assertEquals(client.greet("Mike"), "Hello Mike");
    }
}

6.2. Programmatischer HTTP-Client

Wir haben auch die Möglichkeit, einen traditionelleren Kunden zu schreiben, wenn wir mehr Kontrolle über dessen Verhalten und Implementierung benötigen:

@Singleton
public class ConcreteGreetingClient {
   private RxHttpClient httpClient;

   public ConcreteGreetingClient(@Client("/") RxHttpClient httpClient) {
      this.httpClient = httpClient;
   }

   public String greet(String name) {
      HttpRequest req = HttpRequest.GET("/greet/" + name);
      return httpClient.retrieve(req).blockingFirst();
   }

   public Single greetAsync(String name) {
      HttpRequest req = HttpRequest.GET("/async/greet/" + name);
      return httpClient.retrieve(req).first("An error as occurred");
   }
}

Der Standard-HTTP-Client verwendet RxJava und kann daher problemlos mit blockierenden oder nicht blockierenden Aufrufen arbeiten.

7. Micronaut CLI

Wir haben das Micronaut CLI-Tool bereits oben in Aktion gesehen, als wir es zum Erstellen unseres Beispielprojekts verwendet haben.

In unserem Fall haben wir eine eigenständige Anwendung erstellt, die jedoch auch über mehrere andere Funktionen verfügt.

7.1. Föderationsprojekte

In Micronaut, a federation is just a group of standalone applications that live under the same directory. Mithilfe von Verbänden können wir sie problemlos zusammen verwalten und sicherstellen, dass sie dieselben Standardeinstellungen und Einstellungen erhalten.

Wenn wir das CLI-Tool zum Generieren eines Verbunds verwenden, werden dieselben Argumente wie beim Befehlcreate-appverwendet. Es wird eine Projektstruktur auf oberster Ebene erstellt, und jede eigenständige App wird von dort aus in ihrem Unterverzeichnis erstellt.

7.2. Eigenschaften

When creating a standalone application or federation, we can decide which features our app needs. Auf diese Weise wird sichergestellt, dass das Projekt nur minimale Abhängigkeiten enthält.

Wir spezifizieren Features mit-features argument und liefern eine durch Kommas getrennte Liste von Feature-Namen.

Eine Liste der verfügbaren Funktionen finden Sie, wenn Sie den folgenden Befehl ausführen:

> mn profile-info service

Provided Features:
--------------------
* annotation-api - Adds Java annotation API
* config-consul - Adds support for Distributed Configuration with Consul
* discovery-consul - Adds support for Service Discovery with Consul
* discovery-eureka - Adds support for Service Discovery with Eureka
* groovy - Creates a Groovy application
[...] More features available

7.3. Bestehende Projekte

We can also use the CLI tool to modify existing projects. Ermöglicht das Erstellen von Beans, Clients, Controllern und mehr. Wenn wir den Befehlmn in einem vorhandenen Projekt ausführen, steht ein neuer Befehlssatz zur Verfügung:

> mn help
| Command Name         Command Description
-----------------------------------------------
create-bean            Creates a singleton bean
create-client          Creates a client interface
create-controller      Creates a controller and associated test
create-job             Creates a job with scheduled method

8. Fazit

In dieser kurzen Einführung in Micronaut haben wir gesehen, wie einfach es ist, blockierende und nicht blockierende HTTP-Server und -Clients zu erstellen. Außerdem haben wir einige Funktionen der CLI untersucht.

Dies ist jedoch nur ein kleiner Vorgeschmack auf die angebotenen Funktionen. Es gibt auch volle Unterstützung für serverlose Funktionen, Service Discovery, verteiltes Tracing, Überwachung und Metriken, eine verteilte Konfiguration und vieles mehr.

Und während viele seiner Funktionen von vorhandenen Frameworks wie Grails und Spring abgeleitet sind, verfügt es auch über zahlreiche einzigartige Funktionen, mit denen es sich von anderen abheben kann.

Wie immer finden wir den obigen Beispielcode in unserenGitHub repo.