Ratpack med Groovy

1. Oversigt

Ratpack er et sæt lette Java-biblioteker til opbygning af skalerbare HTTP-applikationer med reaktive, asynkrone og ikke-blokerende funktioner.

Derudover leverer Ratpack også integration med teknologier og rammer som Google Guice, Spring Boot, RxJava og Hystrix.

I denne vejledning undersøger vi hvordan man bruger Ratpack med Groovy.

2. Hvorfor Groovy?

Groovy er et kraftfuldt, dynamisk sprog, der kører i JVM.

Derfor gør Groovy scripting og domænespecifikke sprog virkelig let. Med Ratpack giver dette hurtig udvikling af webapplikationer.

Ratpack giver nem integration med Groovy gennem ratpack-groovy og ratpack-groovy-test biblioteker.

3. Ratpack-applikation ved hjælp af Groovy Script

Ratpack Groovy API'er er bygget i Java, så de let kan integreres med både Java- og Groovy-applikationer. De er tilgængelige i ratpack.groovy pakke.

Faktisk i kombination med Groovys scripting-evner og Grape-afhængighedsstyring kan vi hurtigt oprette en Ratpack-drevet webapplikation på få få linjer:

@Grab ('io.ratpack: ratpack-groovy: 1.6.1') importerer statisk ratpack.groovy.Groovy.ratpack ratpack {handlers {get {render 'Hello World from Ratpack with Groovy !!' }}}

Dette er vores første handler, håndtering af en GET-anmodning. Alt, hvad vi skulle gøre var at tilføje nogle grundlæggende DSL for at aktivere Ratpack-serveren.

Lad os nu køre dette som et Groovy-script for at starte applikationen. Som standard vil applikationen være tilgængelig den // lokal vært: 5050:

$ curl -s localhost: 5050 Hello World fra Ratpack med Groovy !!

Vi kan også konfigurere porten ved hjælp af ServerConfig:

ratpack {serverConfig {port (5056)}}

Ratpack giver også en hot genindlæsningsfunktion, hvilket betyder, at vi kan ændre os Ratpack.groovy, og se derefter ændringerne, i det øjeblik applikationen serverer vores næste HTTP-anmodning.

4. Ratpack-Groovy afhængighedsstyring

Der er flere måder at aktivere ratpack-groovy support.

4.1. Drue

Vi kan bruge Groovys integrerede afhængighedsmanager Grape.

Det er så simpelt som at tilføje en kommentar til vores Ratpack.groovy manuskript:

@Grab ('io.ratpack: ratpack-groovy: 1.6.1') importerer statisk ratpack.groovy.Groovy.ratpack

4.2. Maven afhængighed

For at bygge i Maven er alt, hvad vi har brug for, at tilføje afhængigheden af ratpack-groovy bibliotek:

 io.ratpack ratpack-groovy $ {ratpack.version} 

4.3. Gradle

Vi kan aktivere ratpack-groovy integration ved at tilføje Ratpack's Gradle-plugin til Groovy i build.gradle:

plugins {id 'io.ratpack.ratpack-groovy' version '1.6.1'}

5. Ratpack Handlers i Groovy

Handlere giver en måde at håndtere webanmodninger og svar på. Du kan få adgang til anmodnings- og svarobjekterne i denne lukning.

Vi kan håndtere webanmodninger ved hjælp af HTTP-metoder som GET og POST:

håndterere {get ("greet /: name") {ctx -> gengiv "Hello" + ctx.getPathTokens (). get ("name") + "!!!" }} 

Vi kan teste denne webanmodning igennem // localhost: 5050 / hilsen /:

$ curl -s localhost: 5050 / greet / Norman Hej Norman !!!

I koden til handler, ctx er Sammenhæng registreringsdatabaseobjekt, der giver adgang til stivariabler, anmodnings- og svarobjekter.

Handlere har også støtte til at håndtere JSON gennem Jackson.

Lad os returnere JSON, konverteret fra et Groovy-kort:

get ("data") {gengive Jackson.json ([titel: "Mr", navn: "Norman", land: "USA"))} 
$ curl -s localhost: 5050 / data {"title": "Mr", "name": "Norman", "country": "USA"}

Her, Jackson.json bruges til at foretage konverteringen.

6. Ratpack løfter i Groovy

Som vi ved, muliggør Ratpack de asynkrone og ikke-blokerende funktioner i applikationen. Dette implementeres med Ratpack Promises.

Løfter svarer til dem, der bruges i JavaScript, og ligner lidt Java Fremtid. Vi kan tænke på en Løfte som repræsentation af en værdi, der vil være tilgængelig i fremtiden:

post ("bruger") {Promise user = parse (Jackson.fromJson (User)) user.then {u -> render u.name}}

Den sidste handling her er derefter handling, der bestemmer, hvad der skal gøres med den endelige værdi. I dette tilfælde returnerer vi det som et svar på POSTEN.

Lad os forstå denne kode mere detaljeret. Her, Jackson. Fra Json analyserer JSON på anmodningsorganet ved hjælp af ObjectMapperBruger. Derefter den indbyggede Sammenhæng.parse metode binder det til Løfte objekt.

Løftet fungerer asynkront. Når derefter operation til sidst udføres, svaret returneres:

curl -X POST -H 'Content-type: application / json' --data \ '{"id": 3, "title": "Mrs", "name": "Jiney Weiber", "country": "UK "} '\ // localhost: 5050 / medarbejder Jiney Weiber

Vi skal bemærke, at Promise-biblioteket er ret rigt, så vi kan kæde handlinger ved hjælp af funktioner som kort og flatMap.

7. Integration med en database

At have asynkrone handlere er mest fordelagtigt, når vores handlers skal vente på tjenester. Lad os demonstrere dette ved at integrere vores Ratpack-applikation med en H2-database.

Vi kan enten bruge Ratpack's HikariModule klasse, som er en udvidelse af HikariCP JDBC-forbindelsespool eller Groovy Sql til databaseintegration.

7.1. HikariModule

For at tilføje HikariCP support, lad os først tilføje følgende Hikari og H2 maven afhængigheder i vores pom.xml:

 io.ratpack ratpack-hikari $ {ratpack.version} com.h2database h2 $ {h2.version} 

Eller vi kan tilføje følgende afhængigheder til vores build.gradle:

afhængigheder {kompilere ratpack.dependency ('hikari') kompilere "com.h2database: h2: $ h2.version"}

Nu skal vi erklære HikariModule under bindinger lukning for forbindelsesbassinet:

import ratpack.hikari.HikariModule ratpack {bindings {module (HikariModule) {config -> config.dataSourceClassName = 'org.h2.jdbcx.JdbcDataSource' config.addDataSourceProperty ('URL', "jdbc: h2: mem: devDB; INIT = KØRSKRIPT FRA 'classpath: /User.sql' ")}}} 

Endelig er vi klar til at bruge det til enkle databasefunktioner ved hjælp af Java'er Forbindelse og PreparedStatement:

get ('fetchUserName /: id') {Context ctx -> Connection connection = ctx.get (DataSource.class) .getConnection () PreparedStatement queryStatement = connection.prepareStatement ("SELECT NAME FROM USER WHERE ID =?") queryStatement.setInt (1, Integer.parseInt (ctx.getPathTokens (). Get ("id"))) ResultSet resultSet = queryStatement.executeQuery () resultSet.next () render resultSet.getString (1)} 

Lad os kontrollere, at handleren fungerer som forventet:

$ curl -s localhost: 5050 / fetchUserName / 1 Norman Potter

7.2. Groovy Kvm Klasse

Vi kan bruge Groovy Kvm til hurtige databasefunktioner gennem metoder som rækker og executeInsert:

get ('fetchUsers') {def db = [url: 'jdbc: h2: mem: devDB'] def sql = Sql.newInstance (db.url, db.user, db.password) def users = sql.rows (" VÆLG * FRA BRUGER "); gengive (Jackson.json (brugere))} 
$ curl -s localhost: 5050 / fetchUsers [{"ID": 1, "TITLE": "Mr", "NAME": "Norman Potter", "COUNTRY": "USA"}, {"ID": 2, "TITLE": "Miss", "NAME": "Ketty Smith", "COUNTRY": "FRANCE"}]

Lad os skrive et HTTP POST-eksempel med Kvm:

post ('addUser') {parse (Jackson.fromJson (User)). derefter {u -> def db = [url: 'jdbc: h2: mem: devDB'] Sql sql = Sql.newInstance (db.url, db .bruger, db.password) sql.executeInsert ("INDSÆT I BRUGERVÆRDIER (?,?,?,?)", [u.id, u.title, u.name, u.country]) gengiver "Bruger $ u .navn indsat "}}
$ curl -X POST -H 'Content-type: application / json' --data \ '{"id": 3, "title": "Mrs", "name": "Jiney Weiber", "country": " UK "} '\ // localhost: 5050 / addUser bruger Jiney Weiber indsat

8. Enhedstest

8.1. Opsætning af testene

Som diskuteret giver Ratpack også ratpack-groovy-test bibliotek til testning a ratpack-groovy Ansøgning.

For at bruge det kan vi tilføje det som Maven-afhængighed i vores pom.xml:

 io.ratpack ratpack-groovy-test 1.6.1 

Alternativt kan vi tilføje Gradle-afhængighed i vores build.gradle:

testCompile ratpack.dependency ('groovy-test')

Så er vi nødt til at oprette en Groovy-hovedklasse RatpackGroovyApp.groovy at lade os teste Ratpack.groovy manuskript.

offentlig klasse RatpackGroovyApp {public static void main (String [] args) {File file = new File ("src / main / groovy / com / baeldung / Ratpack.groovy"); def shell = ny GroovyShell () shell.evaluate (fil)}}

Når du kører Groovy-tests som JUnit-tests, klassen påberåber sig Ratpack.groovy script ved hjælp af GroovyShell. Til gengæld starter Ratpack-serveren til test.

Lad os nu skrive vores Groovy Test-klasse RatpackGroovySpec.groovy sammen med koden for at starte Ratpack-serveren via RatpackGroovyApp:

klasse RatpackGroovySpec {ServerBackedApplicationUnderTest ratpackGroovyApp = ny MainClassApplicationUnderTest (RatpackGroovyApp.class) @Delegate TestHttpClient client = TestHttpClient.testHttpClient (ratpackGroovyApp)}

Ratpack giver MainClassApplicationUnderTest for at spotte applikationsklassen til start af serveren.

8.2. Skrivning af vores tests

Lad os skrive vores tests startende med en meget grundlæggende test for at kontrollere, om applikationen kan starte:

@Test annullerer "test hvis app startes" () {når: get ("") derefter: hævde respons.statusCode == 200 hævde respons.body.text == "Hej verden fra Ratpack med Groovy !!" }

Lad os nu skrive en anden test for at kontrollere svaret fra fetchUsers få handler:

@Test annullerer "test fetchUsers" () {når: get ("fetchUsers") så: assert response.statusCode == 200 assert response.body.text == '[{"ID": 1, "TITLE": "Mr. "," NAME ":" Norman Potter "," COUNTRY ":" USA "}, {" ID ": 2," TITLE ":" Miss "," NAME ":" Ketty Smith "," COUNTRY ":" FRANKRIG "}] '}

Ratpack testrammerne sørger for at starte og stoppe serveren for os.

9. Konklusion

I denne artikel har vi set et par måder at skrive HTTP-handlers til Ratpack ved hjælp af Groovy. Vi undersøgte også løfter og integration af databaser.

Vi har set, hvordan Groovy-lukninger, DSL'er og Groovy's Kvm gøre vores kode kortfattet, effektiv og læsbar. På samme tid gør Groovys testunderstøttelse enkelt- og integrationstest ligetil.

Med disse teknikker kan vi bruge Groovys dynamiske sprogfunktioner og udtryksfulde API'er til hurtigt at udvikle højtydende, skalerbare HTTP-applikationer med Ratpack.

Som sædvanlig kan eksempelkoden findes på GitHub.