Einführung in Ratpack

1. Übersicht

Ratpack ist eine Reihe von JVM- basierten Bibliotheken, die für moderne Hochleistungs-Echtzeitanwendungen entwickelt wurden. Es basiert auf der eingebetteten ereignisgesteuerten Netty -Netzwerk-Engine und 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 finden Sie hier
  • Da Ratpack auf Netty basiert, ist es vollständig ereignisgesteuert und nicht blockierend
  • Es unterstützt das Guice- Abhängigkeitsmanagement
  • Ähnlich wie Spring Boot 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 unserer pom.xml hinzu:

 io.ratpack ratpack-core 1.4.5   io.ratpack ratpack-test 1.4.5 

Sie können die neueste Version auf Maven Central überprüfen.

Beachten Sie, dass es gemäß Ratpack-Empfehlung besser ist, Gradle als Build-Tool zu verwenden, obwohl wir Maven als Build-System verwenden, da Ratpack über das Gradle-Plugin von Ratpack 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 eingebetteten Netty- Server zu starten, und einen einfachen Kontext erstellen , um die Standardanforderungen zu verarbeiten:

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

Wie wir sehen können, können wir mit RatpackServer jetzt den Server starten (Standardport 5050). Die Methode handlers () übernimmt eine Funktion, die ein Chain-Objekt empfä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 unter // localhost: 5050 aufrufen, "Willkommen bei Baeldung 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 wir PathTokens, 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 Namen URL param zu. Wann immer eine Anfrage wie // localhost: 5050 / John kommt, lautet die Antwort "Hallo John !!!".

3.4. Änderung des Anforderungs- / Antwort-Headers mit / ohne Filter

Manchmal müssen wir den Inline-HTTP-Antwortheader entsprechend unseren Anforderungen ändern. Ratpack verfügt über MutableHeaders, um ausgehende Antworten anzupassen.

Zum Beispiel müssen wir die folgenden Überschriften in der Antwort ändern: Zugriffssteuerung-Zulassen-Ursprung , Akzeptieren-Sprache und Akzeptieren-Zeichensatz :

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

Mit MutableHeaders setzen wir die drei Header und schieben sie in die Kette .

Auf die gleiche Weise können wir auch die Header für eingehende Anforderungen überprüfen:

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

Das gleiche kann durch Erstellen eines Filters erreicht werden. Ratpack verfügt über eine Handler- Schnittstelle , die zum Erstellen eines Filters implementiert werden kann. Es gibt nur eine Methode handle (), die den aktuellen Kontext 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 baeldung ratpack!!!")))); }

3.5. JSON-Parser

Ratpack verwendet intern schnelleres Jackson für das JSON-Parsing. Wir können das Jackson-Modul verwenden, 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 namens Employee erstellt , die drei Parameter enthält: id, title und name . Jetzt werden wir dieses Employee- 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 zwei Employee- Objekte manuell zu einer Liste hinzu und analysieren sie mithilfe des Jackson- Moduls als JSON . Sobald die URL / data / employee getroffen wird, wird das JSON-Objekt zurückgegeben.

Zeigen Sie auf hier beachten ist , dass wir nicht verwenden ObjectMapper überhaupt seit Ratpack des Jackson - Modul wird das Nötige on the fly tun.

3.6. In-Memory-Datenbank

Ratpack bietet erstklassige Unterstützung für In-Memory-Datenbanken. Es verwendet HikariCP für das JDBC-Verbindungspooling. Um es zu verwenden, müssen wir die HikariCP-Modulabhängigkeit von Ratpack in die Datei pom.xml einfügen :

 io.ratpack ratpack-hikari 1.4.5 

Wenn wir Gradle verwenden , muss dasselbe in der Gradle-Builddatei hinzugefü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 betriebsbereit ist. Wir erstellen die Datei DDL.sql im Verzeichnis src / main / resources und fügen einige DDL-Anweisungen hinzu.

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

Mit HikariModule können wir jetzt 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:baeldung;INIT=RUNSCRIPT FROM 'classpath:/DDL.sql'"); }))).handlers(...));

4. Testen

Wie bereits erwähnt, bietet Ratpack erstklassige Unterstützung für jUnit-Testfälle. Mit MainClassApplicationUnderTest 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 baeldung 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(); } }

Beachten Sie, dass wir die ausgeführte MainClassApplicationUnderTest- Instanz manuell beenden müssen, indem wir die close () -Methode aufrufen , da sie möglicherweise JVM-Ressourcen unnötig blockiert. Aus diesem Grund haben wir die Annotation @After verwendet , um die Instanz nach Ausführung des Testfalls zwangsweise zu beenden.

5. Schlussfolgerung

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

Wie immer ist der vollständige Quellcode auf GitHub verfügbar.