Erstellen von REST Microservices mit Javalin

Erstellen von REST-Microservices mit Javelin

1. Einführung

Javalin ist ein leichtes Webframework, das für Java und Kotlin geschrieben wurde. Es ist auf dem Jetty-Webserver geschrieben, was es sehr leistungsfähig macht. Javalin ist eng ankoa.js angelehnt, was bedeutet, dass es von Grund auf so geschrieben wurde, dass es einfach zu verstehen und darauf aufzubauen ist.

In diesem Tutorial werden die Schritte zum Erstellen eines grundlegenden REST-Mikroservices mit diesem Light-Framework beschrieben.

2. Abhängigkeiten hinzufügen

Um eine Basisanwendung zu erstellen, benötigen wir nur eine Abhängigkeit - Javalin selbst:


    io.javalin
    javalin
    1.6.1

Die aktuelle Version finden Sie unterhere.

3. Javalin einrichten

Javalin erleichtert das Einrichten einer Basisanwendung. Zunächst definieren wir unsere Hauptklasse und richten eine einfache "Hello World" -Anwendung ein.

Erstellen wir in unserem Basispaket eine neue Datei mit dem NamenJavalinApp.java.

In dieser Datei erstellen wir eine Hauptmethode und fügen Folgendes hinzu, um eine Basisanwendung einzurichten:

Javalin app = Javalin.create()
  .port(7000)
  .start();
app.get("/hello", ctx -> ctx.html("Hello, Javalin!"));

Wir erstellen eine neue Instanz von Javalin, lassen sie auf Port 7000 abhören und starten dann die Anwendung.

Wir richten auch unseren ersten Endpunkt ein, der auf eine Anforderung vonGETam Endpunkt von /hellowartet.

Führen Sie diese Anwendung aus und besuchen Siehttp://localhost:7000/hello, um die Ergebnisse anzuzeigen.

4. UserController erstellen

Ein Beispiel für "Hallo Welt" eignet sich hervorragend für die Einführung eines Themas, ist jedoch für eine echte Anwendung nicht vorteilhaft. Schauen wir uns jetzt einen realistischeren Anwendungsfall für Javalin an.

Zunächst müssen wir ein Modell des Objekts erstellen, mit dem wir arbeiten. Wir beginnen mit der Erstellung eines Pakets namensuser unter dem Root-Projekt.

Dann fügen wir eine neueUser-Klasse hinzu:

public class User {
    public final int id;
    public final String name;

    // constructors
}

Außerdem müssen wir unser Datenzugriffsobjekt (DAO) einrichten. In diesem Beispiel verwenden wir ein In-Memory-Objekt, um unsere Benutzer zu speichern.

Wir erstellen eine neue Klasse im Paketuser mit dem NamenUserDao.java:

class UserDao {

    private List users = Arrays.asList(
      new User(0, "Steve Rogers"),
      new User(1, "Tony Stark"),
      new User(2, "Carol Danvers")
    );

    private static UserDao userDao = null;

    private UserDao() {
    }

    static UserDao instance() {
        if (userDao == null) {
            userDao = new UserDao();
        }
        return userDao;
    }

    Optional getUserById(int id) {
        return users.stream()
          .filter(u -> u.id == id)
          .findAny();
    }

    Iterable getAllUsernames() {
        return users.stream()
          .map(user -> user.name)
          .collect(Collectors.toList());
    }
}

Die Implementierung unseres DAO als Singleton erleichtert die Verwendung im Beispiel. Wir könnten es auch als statisches Mitglied unserer Hauptklasse deklarieren oder die Abhängigkeitsinjektion aus einer Bibliothek wie Guice verwenden, wenn wir möchten.

Schließlich möchten wir unsere Controller-Klasse erstellen. Mit Javelin können wir sehr flexibel sein, wenn wir unsere Routenführer deklarieren. Dies ist also nur eine Möglichkeit, sie zu definieren.

Wir erstellen eine neue Klasse namensUserController.java im Paketuser:

public class UserController {
    public static Handler fetchAllUsernames = ctx -> {
        UserDao dao = UserDao.instance();
        Iterable allUsers = dao.getAllUsernames();
        ctx.json(allUsers);
    };

    public static Handler fetchById = ctx -> {
        int id = Integer.parseInt(Objects.requireNonNull(ctx.param("id")));
        UserDao dao = UserDao.instance();
        User user = dao.getUserById(id);
        if (user == null) {
            ctx.html("Not Found");
        } else {
            ctx.json(user);
        }
    };
}

Indem wir die Handler als statisch deklarieren, stellen wir sicher, dass der Controller selbst keinen Status hat. In komplexeren Anwendungen möchten wir möglicherweise den Status zwischen Anforderungen speichern. In diesem Fall müssen wir den statischen Modifikator entfernen.

Beachten Sie auch, dass Unit-Tests mit statischen Methoden schwieriger sind. Wenn Sie diese Teststufe verwenden möchten, müssen Sie nicht-statische Methoden verwenden.

5. Routen hinzufügen

Wir haben jetzt mehrere Möglichkeiten, Daten aus unserem Modell abzurufen. Der letzte Schritt besteht darin, diese Daten über REST-Endpunkte bereitzustellen. Wir müssen zwei neue Routen in unserer Hauptanwendung registrieren.

Fügen wir sie unserer Hauptanwendungsklasse hinzu:

app.get("/users", UserController.fetchAllUsernames);
app.get("/users/:id", UserController.fetchById);

Nach dem Kompilieren und Ausführen der Anwendung können wir eine Anforderung an jeden dieser neuen Endpunkte senden. Beim Aufrufen vonhttp://localhost:7000/users will werden alle Benutzer aufgelistet, und beim Aufrufen vonhttp://localhost:7000/users/0 will wird das JSON-Objekt für einen einzelnen Benutzer mit der ID 0 abgerufen. Wir haben jetzt einen Microservice, mit dem wirUser Daten abrufen können.

6. Routen erweitern

Das Abrufen von Daten ist eine wichtige Aufgabe der meisten Mikrodienste.

Wir müssen jedoch auch in der Lage sein, Daten in unserem Datenspeicher zu speichern. Javelin bietet alle Pfad-Handler, die zum Erstellen von Diensten erforderlich sind.

Wir haben oben ein Beispiel fürGET gesehen, aber auchPATCH, POST, DELETE, andPUT sind möglich.

Wenn wir Jackson als Abhängigkeit einbeziehen, können wir JSON-Anforderungskörper auch automatisch in unsere Modellklassen einteilen. Zum Beispiel:

app.post("/") { ctx ->
  User user = ctx.bodyAsClass(User.class);
}

würde es uns ermöglichen, das JSONUser-Objekt aus dem Anforderungshauptteil zu entnehmen und es in dasUser-Modellobjekt zu übersetzen.

7. Fazit

Wir können all diese Techniken kombinieren, um unseren Microservice zu erhalten.

In diesem Artikel haben wir gesehen, wie Javalin eingerichtet und eine einfache Anwendung erstellt wird. Wir haben auch darüber gesprochen, wie die verschiedenen HTTP-Methodentypen verwendet werden können, damit Clients mit unserem Service interagieren können.

Weitere Beispiele für die Verwendung von Javalin finden Sie indocumentation.

Wie immer kann der Code auchover on GitHub gefunden werden.