Einführung in Ratpack

Einführung in Ratpack

1. Überblick

Ratpack ist eine Reihe vonJVM-basierten Bibliotheken, die für moderne Hochleistungs-Echtzeitanwendungen erstellt wurden. Es basiert auf der ereignisgesteuerten Netzwerk-Engine von EmbeddedNettyund entspricht vollständig dem reaktiven Entwurfsmuster.

In diesem Artikel erfahren Sie, wie Sie Ratpack verwenden, und erstellen daraus eine kleine Anwendung.

2. Warum Ratpack?

Die Hauptvorteile von Ratpack:

  • Es ist sehr leicht, schnell und skalierbar

  • Es verbraucht weniger Speicher als andere Frameworks wie DropWizard. Ein interessantes Benchmark-Vergleichsergebnis kann inhere gefunden werden

  • Da Ratpack aufNetty basiert, ist es vollständig ereignisgesteuert und nicht blockierend

  • Es unterstützt das Abhängigkeitsmanagement vonGuice

  • Ähnlich wieSpringBoot verfügt Ratpack über eigene Testbibliotheken, mit denen Testfälle schnell eingerichtet werden können

3. Erstellen einer Anwendung

Um zu verstehen, wie Ratpack funktioniert, erstellen wir zunächst eine kleine Anwendung damit.

3.1. Maven-Abhängigkeiten

Fügen wir zunächst die folgenden Abhängigkeiten zu unserenpom.xml:hinzu


    io.ratpack
    ratpack-core
    1.4.5


    io.ratpack
    ratpack-test
    1.4.5

Sie können die neueste Version aufMavenCentral überprüfen.

Beachten Sie, dass wir, obwohl wir Maven als Build-System verwenden, gemäßRatpack recommendationGradle besser als Build-Tool verwenden, da Ratpack über dieRatpack’s Gradle plugin erstklassige Gradle-Unterstützung bietet.

Wir können das folgende Build-Gradle-Skript verwenden:

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. Erstellen der Anwendung

Sobald unser Build-Management konfiguriert ist, müssen wir eine Klasse erstellen, um den eingebettetenNetty-Server zu starten und einen einfachen Kontext für die Verarbeitung der Standardanforderungen zu erstellen:

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

Wie wir sehen können, können wir mitRatpackServer jetzt den Server starten (Standardport 5050). Die Methodehandlers() übernimmt eine Funktion, die ein ObjektChainempfängt, das alle jeweiligen eingehenden Anforderungen abbildet. Diese „Handler Chain API“ wird zum Erstellen der Antwortbehandlungsstrategie verwendet.

Wenn wir dieses Code-Snippet ausführen und den Browser beihttp://localhost:5050 drücken, "Willkommen zum Beispiel ratpack !!!" sollte angezeigt werden.

Ebenso können wir eine HTTP-POST-Anforderung zuordnen.

3.3. Umgang mit URL-Pfadparametern

Im nächsten Beispiel müssen wir einige URL-Pfadparameter in unserer Anwendung erfassen. In Ratpack verwenden wirPathTokens, um sie zu erfassen:

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

Hier ordnen wir den URL-Parameter vonnamezu. Wann immer eine Anfrage wiehttp://localhost:5050/John kommt, lautet die Antwort "Hallo John !!!".

3.4. Request/Response Header Modification With/Without Filter

Manchmal müssen wir den Inline-HTTP-Antwortheader nach Bedarf ändern. Ratpack hatMutableHeaders, um ausgehende Antworten anzupassen.

Zum Beispiel müssen wir die folgenden Überschriften in der Antwort ändern:Access-Control-Allow-Origin,Accept-Language undAccept-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") + "!!!"))));

MitMutableHeaders setzen wir die drei Header und schieben sie inChain.

Auf die gleiche Weise können wir auch die Header eingehender Anfragen überprüfen:

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

Dasselbe kann durch Erstellen eines Filters erreicht werden. Ratpack hat eineHandler-Schnittstelle,, die implementiert werden kann, um einen Filter zu erstellen. Es gibt nur eine Methodehandle(),, die den aktuellenContext als Parameter verwendet:

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

Wir können diesen Filter folgendermaßen verwenden:

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

3.5. JSON-Parser

Ratpack verwendet internfaster-jackson für die JSON-Analyse. Wir können das ModulJacksonverwenden, um jedes Objekt in JSON zu analysieren.

Erstellen wir eine einfache POJO-Klasse, die zum Parsen verwendet wird:

public class Employee {

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

    // getters and setters

}

Hier haben wir eine einfache POJO-Klasse mit dem NamenEmployee erstellt, die drei Parameter hat:id, title undname. Jetzt werden wir diesesEmployee-Objekt verwenden, um es in JSON zu konvertieren und dasselbe zurückzugeben, wenn eine bestimmte URL getroffen wird:

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

Wie wir sehen können, fügen wir manuell zweiEmployee-Objekte zu einer Liste hinzu und analysieren sie mit demJackson-Modul als JSON. Sobald die URL von/data/employeeserreicht ist, wird das JSON-Objekt zurückgegeben.

Hier ist zu beachten, dasswe are not using ObjectMapper at all, da das Jackson-Modul von Ratpack das Notwendige im laufenden Betrieb erledigt.

3.6. In-Memory-Datenbank

Ratpack bietet erstklassige Unterstützung für In-Memory-Datenbanken. Es verwendetHikariCP für das JDBC-Verbindungspooling. Um es zu verwenden, müssen wir RatpacksHikariCP module dependency inpom.xml hinzufügen:


    io.ratpack
    ratpack-hikari
    1.4.5

Wenn wirGradle verwenden, muss dasselbe in die Gradle-Build-Datei eingefügt werden:

compile ratpack.dependency('hikari')

Jetzt müssen wir eine SQL-Datei mit Tabellen-DDL-Anweisungen erstellen, damit die Tabellen erstellt werden, sobald der Server in Betrieb ist. Wir erstellen die DateiDDL.sqlim Verzeichnissrc/main/resourcesund fügen einige DDL-Anweisungen hinzu.

Da wir die H2-Datenbank verwenden, müssen wir auch dafür Abhängigkeiten hinzufügen.

Jetzt können wir mit HikariModule die Datenbank zur Laufzeit initialisieren:

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. Testen

Wie bereits erwähnt, bietet Ratpack erstklassigen Support für jUnit-Testfälle. MitMainClassApplicationUnderTest können wir einfach Testfälle erstellen und die Endpunkte testen:

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

}

Bitte beachten Sie, dass wir die laufendeMainClassApplicationUnderTest-Instanz manuell beenden müssen, indem wir dieclose()-Methode aufrufen, da sie möglicherweise JVM-Ressourcen unnötig blockiert. Aus diesem Grund haben wir die Annotation@Afterverwendet, um die Instanz nach Ausführung des Testfalls zwangsweise zu beenden.

5. Fazit

In diesem Artikel haben wir die Einfachheit der Verwendung von Ratpack gesehen.

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