Création de microservices REST avec Javalin

Créer des microservices REST avec Javelin

1. introduction

Javalin est un framework Web léger écrit pour Java et Kotlin. Il est écrit sur le serveur Web Jetty, ce qui le rend très performant. Javalin est modélisé étroitement à partir dekoa.js, ce qui signifie qu'il est écrit à partir de zéro pour être simple à comprendre et à développer.

Dans ce didacticiel, nous allons parcourir les étapes de création d'un microservice REST de base à l'aide de ce framework léger.

2. Ajout de dépendances

Pour créer une application de base, nous n’avons besoin que d’une seule dépendance: Javalin lui-même:


    io.javalin
    javalin
    1.6.1

La version actuelle peut être trouvéehere.

3. Configurer Javalin

Javalin facilite la configuration d’une application de base. Nous allons commencer par définir notre classe principale et configurer une simple application "Hello World".

Créons un nouveau fichier dans notre package de base appeléJavalinApp.java.

Dans ce fichier, nous créons une méthode principale et ajoutons les éléments suivants pour configurer une application de base:

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

Nous créons une nouvelle instance de Javalin, la faisons écouter sur le port 7000, puis démarrons l'application.

Nous configurons également notre premier point de terminaison à l’écoute d’une requêteGET au point de terminaison /hello.

Lançons cette application et visitonshttp://localhost:7000/hello pour voir les résultats.

4. Créer unUserController

Un exemple «Hello World» est idéal pour introduire un sujet, mais il n’est pas utile pour une vraie application. Examinons maintenant un cas d'utilisation plus réaliste de Javalin.

Tout d'abord, nous devons créer un modèle de l'objet avec lequel nous travaillons. Nous commençons par créer un package appeléuser sous le projet racine.

Ensuite, nous ajoutons une nouvelle classeUser:

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

    // constructors
}

Nous devons également configurer notre objet d'accès aux données (DAO). Nous utiliserons un objet en mémoire pour stocker nos utilisateurs dans cet exemple.

Nous créons une nouvelle classe dans le packageuser appeléUserDao.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());
    }
}

L'implémentation de notre DAO en tant que singleton facilite son utilisation dans l'exemple. Nous pourrions également le déclarer comme membre statique de notre classe principale ou utiliser l'injection de dépendance à partir d'une bibliothèque comme Guice si nous le voulions.

Enfin, nous voulons créer notre classe de contrôleurs. Javelin nous permet d’être très flexibles lorsque nous déclarons nos gestionnaires de routage. Ce n’est donc qu’un moyen de les définir.

Nous créons une nouvelle classe appeléeUserController.java dans le packageuser:

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);
        }
    };
}

En déclarant les gestionnaires comme étant statiques, nous nous assurons que le contrôleur lui-même ne détient aucun état. Mais, dans les applications plus complexes, nous pouvons vouloir stocker l'état entre les requêtes, auquel cas nous devrons supprimer le modificateur statique.

Notez également que les tests unitaires sont plus difficiles avec les méthodes statiques. Par conséquent, si nous voulons ce niveau de test, nous devrons utiliser des méthodes non statiques.

5. Ajouter des itinéraires

Nous avons maintenant plusieurs façons d'extraire des données de notre modèle. La dernière étape consiste à exposer ces données via des points de terminaison REST. Nous devons enregistrer deux nouvelles routes dans notre application principale.

Ajoutons-les à notre classe d’application principale:

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

Après avoir compilé et exécuté l'application, nous pouvons adresser une demande à chacun de ces nouveaux points de terminaison. L'appel dehttp://localhost:7000/users will liste tous les utilisateurs et l'appel dehttp://localhost:7000/users/0 will obtient l'objet JSON utilisateur unique avec l'ID 0. Nous avons maintenant un microservice qui nous permet de récupérer les données deUser.

6. Extension des itinéraires

La récupération des données est une tâche vitale de la plupart des microservices.

Cependant, nous devons également pouvoir stocker des données dans notre magasin de données. Javelin fournit l’ensemble complet des gestionnaires de chemins nécessaires à la création de services.

Nous avons vu un exemple deGET ci-dessus, maisPATCH, POST, DELETE, andPUT sont également possibles.

De même, si nous incluons Jackson en tant que dépendance, nous pouvons analyser automatiquement les corps des requêtes JSON dans nos classes de modèle. Par exemple:

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

nous permettrait de récupérer l'objet JSONUser du corps de la requête et de le traduire dans l'objet modèleUser.

7. Conclusion

Nous pouvons combiner toutes ces techniques pour rendre notre microservice.

Dans cet article, nous avons vu comment configurer Javalin et créer une application simple. Nous avons également expliqué comment utiliser les différents types de méthodes HTTP pour permettre aux clients d’interagir avec notre service.

Pour des exemples plus avancés d'utilisation de Javalin, assurez-vous de consulter lesdocumentation.

De plus, comme toujours, le code peut être trouvéover on GitHub.