Introduction à Ratpack

Introduction à Ratpack

1. Vue d'ensemble

Ratpack est un ensemble de bibliothèques basées surJVM construites pour les applications temps réel hautes performances modernes. Il repose sur le moteur de mise en réseau événementiel deNettyintégré et est entièrement conforme au modèle de conception réactive.

Dans cet article, nous allons apprendre à utiliser Ratpack et nous allons créer une petite application en l'utilisant.

2. Pourquoi Ratpack?

Les principaux avantages de Ratpack:

  • il est très léger, rapide et évolutif

  • il consomme moins de mémoire que les autres frameworks tels que DropWizard; un résultat de comparaison de référence intéressant peut être trouvéhere

  • comme il est construit surNetty, Ratpack est totalement événementiel et non bloquant par nature

  • il prend en charge la gestion des dépendancesGuice

  • tout commeSpringBoot, Ratpack a ses propres bibliothèques de test pour configurer rapidement les cas de test

3. Créer une application

Pour comprendre le fonctionnement de Ratpack, commençons par créer une petite application avec.

3.1. Dépendances Maven

Tout d'abord, ajoutons les dépendances suivantes dans nospom.xml:


    io.ratpack
    ratpack-core
    1.4.5


    io.ratpack
    ratpack-test
    1.4.5

Vous pouvez vérifier la dernière version surMavenCentral.

Notez que bien que nous utilisions Maven comme système de construction, selonRatpack recommendation, il est préférable d'utiliserGradle comme outil de construction puisque Ratpack a un support Gradle de première classe fourni via lesRatpack’s Gradle plugin.

Nous pouvons utiliser le script de compilation Gradle suivant:

buildscript {
    repositories {
      jcenter()
    }
    dependencies {
      classpath "io.ratpack:ratpack-gradle:1.4.5"
    }
}

apply plugin: "io.ratpack.ratpack-java"
repositories {
    jcenter()
}
dependencies {
    testCompile 'junit:junit:4.11'
    runtime "org.slf4j:slf4j-simple:1.7.21"
}
test {
    testLogging {
      events 'started', 'passed'
    }
}

3.2. Construire l'application

Une fois notre gestion de build configurée, nous devons créer une classe pour démarrer le serveur intégréNetty et construire un contexte simple pour gérer les requêtes par défaut:

public class Application {

    public static void main(String[] args) throws Exception {
        RatpackServer.start(server -> server.handlers(chain -> chain
          .get(ctx -> ctx.render("Welcome to example ratpack!!!"))));
    }
}

Comme nous pouvons le voir, en utilisantRatpackServer, nous pouvons maintenant démarrer le serveur (port par défaut 5050). La méthodehandlers() prend une fonction qui reçoit un objetChain, qui mappe toutes les demandes entrantes respectives. Cette «API de chaîne de traitement» est utilisée pour créer la stratégie de traitement des réponses.

Si nous exécutons cet extrait de code et frappons le navigateur àhttp://localhost:5050, "Bienvenue dans l'exemple ratpack !!!" devrait être affiché.

De même, nous pouvons mapper une requête HTTP POST.

3.3. Gestion des paramètres de chemin d'URL

Dans l'exemple suivant, nous devons capturer certains paramètres de chemin d'URL dans notre application. Dans Ratpack, nous utilisonsPathTokens pour les capturer:

RatpackServer.start(server -> server
  .handlers(chain -> chain
  .get(":name", ctx -> ctx.render("Hello "
  + ctx.getPathTokens().get("name") + " !!!"))));

Ici, nous mappons le paramètre d'URL dename. Chaque fois qu'une demande commehttp://localhost:5050/John arriverait, la réponse sera "Hello John !!!".

3.4. Request/Response Header Modification With/Without Filter

Parfois, nous devons modifier l'en-tête de réponse HTTP en ligne en fonction de nos besoins. Ratpack aMutableHeaders pour personnaliser les réponses sortantes.

Par exemple, nous devons modifier les en-têtes suivants dans la réponse:Access-Control-Allow-Origin,Accept-Language etAccept-Charset:

RatpackServer.start(server -> server.handlers(chain -> chain.all(ctx -> {
    MutableHeaders headers = ctx.getResponse().getHeaders();
    headers.set("Access-Control-Allow-Origin", "*");
    headers.set("Accept-Language", "en-us");
    headers.set("Accept-Charset", "UTF-8");
    ctx.next();
}).get(":name", ctx -> ctx
    .render("Hello " + ctx.getPathTokens().get("name") + "!!!"))));

En utilisantMutableHeaders, nous définissons les trois en-têtes et les poussons dans lesChain.

De la même manière, nous pouvons également vérifier les en-têtes des requêtes entrantes:

ctx.getRequest().getHeaders().get("//TODO")

La même chose peut être obtenue en créant un filtre. Ratpack a une interfaceHandler, qui peut être implémentée pour créer un filtre. Il n'a qu'une seule méthodehandle(), qui prend leContext courant comme paramètre:

public class RequestValidatorFilter implements Handler {

    @Override
    public void handle(Context ctx) throws Exception {
        MutableHeaders headers = ctx.getResponse().getHeaders();
        headers.set("Access-Control-Allow-Origin", "*");
        ctx.next();
    }
}

Nous pouvons utiliser ce filtre de la manière suivante:

RatpackServer.start(
    server -> server.handlers(chain -> chain
      .all(new RequestValidatorFilter())
      .get(ctx -> ctx.render("Welcome to example ratpack!!!"))));
}

3.5. Analyseur JSON

Ratpack utilise en internefaster-jackson pour l'analyse JSON. Nous pouvons utiliser le moduleJackson pour analyser n'importe quel objet en JSON.

Créons une classe POJO simple qui sera utilisée pour l'analyse:

public class Employee {

    private Long id;
    private String title;
    private String name;

    // getters and setters

}

Ici, nous avons créé une classe POJO simple nomméeEmployee, qui a trois paramètres:id, title etname. Nous allons maintenant utiliser cet objetEmployee pour le convertir en JSON et le renvoyer lorsque certaines URL sont atteintes:

List employees = new ArrayList();
employees.add(new Employee(1L, "Mr", "John Doe"));
employees.add(new Employee(2L, "Mr", "White Snow"));

RatpackServer.start(
    server -> server.handlers(chain -> chain
      .get("data/employees",
      ctx -> ctx.render(Jackson.json(employees)))));

Comme nous pouvons le voir, nous ajoutons manuellement deux objetsEmployee dans une liste et les analysons comme JSON en utilisant le moduleJackson. Dès que l'URL de/data/employees est atteinte, l'objet JSON sera renvoyé.

Il faut noter ici quewe are not using ObjectMapper at all puisque le module Jackson de Ratpack fera le nécessaire à la volée.

3.6. Base de données en mémoire

Ratpack a le support de première classe pour les bases de données en mémoire. Il utiliseHikariCP pour le regroupement de connexions JDBC. Pour l'utiliser, nous devons ajouter lesHikariCP module dependency de Ratpack dans lespom.xml:


    io.ratpack
    ratpack-hikari
    1.4.5

Si nous utilisonsGradle, la même chose doit être ajoutée dans le fichier de construction Gradle:

compile ratpack.dependency('hikari')

Nous devons maintenant créer un fichier SQL avec des instructions DDL de table afin que les tables soient créées dès que le serveur est opérationnel. Nous allons créer le fichierDDL.sql dans le répertoiresrc/main/resources et y ajouter des instructions DDL.

Puisque nous utilisons la base de données H2, nous devons également ajouter des dépendances pour cela.

Maintenant, en utilisant HikariModule, nous pouvons initialiser la base de données au moment de l'exécution:

RatpackServer.start(
    server -> server.registry(Guice.registry(bindings ->
      bindings.module(HikariModule.class, config -> {
          config.setDataSourceClassName("org.h2.jdbcx.JdbcDataSource");
          config.addDataSourceProperty("URL",
          "jdbc:h2:mem:example;INIT=RUNSCRIPT FROM 'classpath:/DDL.sql'");
      }))).handlers(...));

4. Essai

Comme mentionné précédemment, Ratpack offre un support de première classe pour les cas de test jUnit. En utilisantMainClassApplicationUnderTest, nous pouvons facilement créer des cas de test et tester les points de terminaison:

@RunWith(JUnit4.class)
public class ApplicationTest {

    MainClassApplicationUnderTest appUnderTest
      = new MainClassApplicationUnderTest(Application.class);

    @Test
    public void givenDefaultUrl_getStaticText() {
        assertEquals("Welcome to example ratpack!!!",
          appUnderTest.getHttpClient().getText("/"));
    }

    @Test
    public void givenDynamicUrl_getDynamicText() {
        assertEquals("Hello dummybot!!!",
          appUnderTest.getHttpClient().getText("/dummybot"));
    }

    @Test
    public void givenUrl_getListOfEmployee()
      throws JsonProcessingException {

        List employees = new ArrayList();
        ObjectMapper mapper = new ObjectMapper();
        employees.add(new Employee(1L, "Mr", "John Doe"));
        employees.add(new Employee(2L, "Mr", "White Snow"));

        assertEquals(mapper.writeValueAsString(employees),
          appUnderTest.getHttpClient().getText("/data/employees"));
    }

    @After
    public void shutdown() {
        appUnderTest.close();
    }

}

Veuillez noter que nous devons terminer manuellement l'instanceMainClassApplicationUnderTest en cours d'exécution en appelant la méthodeclose() car elle peut bloquer inutilement les ressources JVM. C’est pourquoi nous avons utilisé l’annotation@After pour mettre fin de force à l’instance une fois le scénario de test exécuté.

5. Conclusion

Dans cet article, nous avons vu la simplicité d'utilisation de Ratpack.

Comme toujours, le code source complet est disponibleover on GitHub.