Introduzione a Ratpack

1. Panoramica

Ratpack è un insieme di librerie basate su JVM create per le moderne applicazioni in tempo reale ad alte prestazioni. È costruito sulla base del motore di rete basato su eventi Netty incorporato ed è pienamente conforme al modello di progettazione reattiva.

In questo articolo impareremo come usare Ratpack e costruiremo una piccola applicazione utilizzandolo.

2. Perché Ratpack?

I principali vantaggi di Ratpack:

  • è molto leggero, veloce e scalabile
  • consuma meno memoria rispetto ad altri framework come DropWizard; un interessante risultato del confronto benchmark può essere trovato qui
  • poiché è costruito su Netty , Ratpack è totalmente guidato dagli eventi e di natura non bloccante
  • supporta la gestione delle dipendenze di Guice
  • proprio come Spring Boot , Ratpack ha le proprie librerie di test per configurare rapidamente i casi di test

3. Creazione di un'applicazione

Per capire come funziona Ratpack, iniziamo creando una piccola applicazione con esso.

3.1. Dipendenze di Maven

Innanzitutto, aggiungiamo le seguenti dipendenze nel nostro pom.xml:

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

Puoi controllare l'ultima versione su Maven Central.

Nota che anche se stiamo usando Maven come nostro sistema di compilazione, come da raccomandazione Ratpack, è meglio usare Gradle come strumento di compilazione poiché Ratpack ha un supporto Gradle di prima classe fornito tramite il plugin Gradle di Ratpack.

Possiamo usare il seguente script Gradle di build:

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. Creazione dell'applicazione

Una volta configurata la nostra gestione della build, dobbiamo creare una classe per avviare il server Netty incorporato e costruire un contesto semplice per gestire le richieste predefinite:

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

Come possiamo vedere, utilizzando RatpackServer possiamo ora avviare il server (porta predefinita 5050). Il metodo handlers () accetta una funzione che riceve un oggetto Chain, che mappa tutte le rispettive richieste in arrivo. Questa "API della catena del gestore" viene utilizzata per creare la strategia di gestione della risposta.

Se eseguiamo questo frammento di codice e premiamo il browser su // localhost: 5050, "Welcome to Baeldung ratpack !!!" dovrebbe essere visualizzato.

Allo stesso modo, possiamo mappare una richiesta HTTP POST.

3.3. Gestione dei parametri del percorso URL

Nel prossimo esempio, dobbiamo acquisire alcuni parametri del percorso URL nella nostra applicazione. In Ratpack usiamo PathTokens per catturarli:

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

Qui, stiamo mappando il nome URL param. Ogni volta che arriva una richiesta come // localhost: 5050 / John , la risposta sarà "Hello John !!!".

3.4. Modifica intestazione richiesta / risposta con / senza filtro

A volte, dobbiamo modificare l'intestazione della risposta HTTP inline in base alle nostre necessità. Ratpack ha MutableHeaders per personalizzare le risposte in uscita.

Ad esempio, dobbiamo modificare le seguenti intestazioni nella risposta: Access-Control-Allow-Origin , Accept-Language e Accept-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") + "!!!"))));

Utilizzando MutableHeaders , impostiamo le tre intestazioni e le inseriamo nella catena .

Allo stesso modo, possiamo controllare anche le intestazioni delle richieste in arrivo:

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

Lo stesso può essere ottenuto creando un filtro. Ratpack ha Handler interfaccia , che può essere implementato per creare un filtro. Ha solo un metodo handle (), che prende il contesto corrente come parametro:

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

Possiamo usare questo filtro nel modo seguente:

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

3.5. Parser JSON

Ratpack utilizza internamente il più veloce jackson per l'analisi JSON. Possiamo usare il modulo Jackson per analizzare qualsiasi oggetto in JSON.

Creiamo una semplice classe POJO che verrà utilizzata per l'analisi:

public class Employee { private Long id; private String title; private String name; // getters and setters }

Qui abbiamo creato una semplice classe POJO denominata Employee , che ha tre parametri: id, title e name . Ora useremo questo oggetto Employee per convertire in JSON e restituiremo lo stesso quando viene raggiunto un determinato URL:

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

Come possiamo vedere, stiamo aggiungendo manualmente due oggetti Employee in un elenco e li stiamo analizzando come JSON usando il modulo Jackson . Non appena viene raggiunto l'URL / data / dipendenti , verrà restituito l'oggetto JSON.

Punto da notare qui è che non stiamo usando ObjectMapper affatto dal modulo di Jackson Ratpack farà il necessario al volo.

3.6. Database in memoria

Ratpack ha il supporto di prima classe per i database in memoria. Utilizza HikariCP per il pool di connessioni JDBC. Per usarlo, dobbiamo aggiungere la dipendenza del modulo HikariCP di Ratpack nel pom.xml :

 io.ratpack ratpack-hikari 1.4.5 

Se stiamo usando Gradle , lo stesso deve essere aggiunto nel file di build Gradle:

compile ratpack.dependency('hikari')

Ora, dobbiamo creare un file SQL con istruzioni DDL di tabella in modo che le tabelle vengano create non appena il server è attivo e in esecuzione. Creeremo il file DDL.sql nella directory src / main / resources e aggiungeremo alcune istruzioni DDL al suo interno.

Dato che stiamo usando il database H2, dobbiamo aggiungere anche delle dipendenze.

Ora, utilizzando HikariModule, possiamo inizializzare il database in fase di esecuzione:

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

Come accennato in precedenza, Ratpack ha un supporto di prima classe per i casi di test jUnit. Utilizzando MainClassApplicationUnderTest possiamo creare facilmente casi di test e testare gli endpoint:

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

Si noti che è necessario terminare manualmente l' istanza MainClassApplicationUnderTest in esecuzione chiamando il metodo close () poiché potrebbe bloccare inutilmente le risorse JVM. Ecco perché abbiamo utilizzato l' annotazione @After per terminare forzatamente l'istanza una volta eseguito il test case.

5. conclusione

In questo articolo abbiamo visto la semplicità dell'utilizzo di Ratpack.

Come sempre, il codice sorgente completo è disponibile su GitHub.