1. Información general
Ratpack es un conjunto de bibliotecas basadas en JVM creadas para las aplicaciones en tiempo real de alto rendimiento de la actualidad. Está construido sobre el motor de red integrado basado en eventos de Netty y es totalmente compatible con el patrón de diseño reactivo.
En este artículo, aprenderemos a usar Ratpack y crearemos una pequeña aplicación usándolo.
2. ¿Por qué Ratpack?
Las principales ventajas de Ratpack:
- es muy ligero, rápido y escalable
- consume menos memoria que otros marcos como DropWizard; un resultado de comparación de referencia interesante se puede encontrar aquí
- Dado que está construido sobre Netty , Ratpack es totalmente impulsado por eventos y de naturaleza no bloqueante.
- tiene soporte para la gestión de la dependencia de Guice
- al igual que Spring Boot , Ratpack tiene sus propias bibliotecas de prueba para configurar rápidamente casos de prueba
3. Creación de una aplicación
Para entender cómo funciona Ratpack, comencemos creando una pequeña aplicación con él.
3.1. Dependencias de Maven
Primero, agreguemos las siguientes dependencias en nuestro pom.xml:
io.ratpack ratpack-core 1.4.5 io.ratpack ratpack-test 1.4.5
Puede consultar la última versión en Maven Central.
Tenga en cuenta que, aunque estamos usando Maven como nuestro sistema de compilación, según la recomendación de Ratpack, es mejor usar Gradle como una herramienta de compilación, ya que Ratpack tiene soporte Gradle de primera clase proporcionado a través del complemento Gradle de Ratpack.
Podemos usar el siguiente script de compilación de Gradle:
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. Construyendo la Aplicación
Una vez que nuestra administración de compilación está configurada, necesitamos crear una clase para iniciar el servidor Netty integrado y construir un contexto simple para manejar las solicitudes predeterminadas:
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!!!")))); } }
Como podemos ver, al usar RatpackServer ahora podemos iniciar el servidor (puerto predeterminado 5050). El método handlers () toma una función que recibe un objeto Chain, que mapea todas las solicitudes entrantes respectivas. Esta "API de cadena de manejadores" se utiliza para construir la estrategia de manejo de respuestas.
Si ejecutamos este fragmento de código y accedemos al navegador en // localhost: 5050, "¡¡¡Bienvenido a Baeldung ratpack !!!" debería mostrarse.
De manera similar, podemos asignar una solicitud HTTP POST.
3.3. Manejo de parámetros de ruta de URL
En el siguiente ejemplo, necesitamos capturar algún parámetro de ruta de URL en nuestra aplicación. En Ratpack usamos PathTokens para capturarlos:
RatpackServer.start(server -> server .handlers(chain -> chain .get(":name", ctx -> ctx.render("Hello " + ctx.getPathTokens().get("name") + " !!!"))));
Aquí, estamos mapeando el nombre URL param. Siempre que venga una solicitud como // localhost: 5050 / John , la respuesta será "¡¡¡Hola John !!!".
3.4. Modificación del encabezado de solicitud / respuesta con / sin filtro
A veces, necesitamos modificar el encabezado de respuesta HTTP en línea según nuestras necesidades. Ratpack tiene MutableHeaders para personalizar las respuestas salientes.
Por ejemplo, necesitamos modificar los siguientes encabezados en la respuesta: Access-Control-Allow-Origin , Accept-Language y 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") + "!!!"))));
Al usar MutableHeaders , configuramos los tres encabezados y los empujamos en la cadena .
De la misma manera, también podemos verificar los encabezados de las solicitudes entrantes:
ctx.getRequest().getHeaders().get("//TODO")
Lo mismo se puede lograr creando un filtro. Ratpack tiene una interfaz Handler , que se puede implementar para crear un filtro. Tiene un solo método handle (), que toma el contexto actual como parámetro:
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(); } }
Podemos utilizar este filtro de la siguiente manera:
RatpackServer.start( server -> server.handlers(chain -> chain .all(new RequestValidatorFilter()) .get(ctx -> ctx.render("Welcome to baeldung ratpack!!!")))); }
3.5. Analizador JSON
Ratpack utiliza internamente quick -jackson para el análisis de JSON. Podemos usar el módulo Jackson para analizar cualquier objeto en JSON.
Creemos una clase POJO simple que se utilizará para analizar:
public class Employee { private Long id; private String title; private String name; // getters and setters }
Aquí, hemos creado una clase POJO simple llamada Empleado , que tiene tres parámetros: id, título y nombre . Ahora usaremos este objeto Empleado para convertirlo a JSON y devolver el mismo cuando se acceda a cierta 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)))));
Como podemos ver, estamos agregando manualmente dos objetos Empleado en una lista y analizándolos como JSON usando el módulo Jackson . Tan pronto como se llegue a la URL / data / employee , se devolverá el objeto JSON.
El punto a tener en cuenta aquí es que no estamos usando ObjectMapper en absoluto, ya que el módulo Jackson de Ratpack hará lo necesario sobre la marcha.
3.6. Base de datos en memoria
Ratpack tiene soporte de primera clase para bases de datos en memoria. Utiliza HikariCP para la agrupación de conexiones JDBC. Para usarlo, necesitamos agregar la dependencia del módulo HikariCP de Ratpack en el pom.xml :
io.ratpack ratpack-hikari 1.4.5
Si usamos Gradle , es necesario agregar lo mismo en el archivo de compilación de Gradle:
compile ratpack.dependency('hikari')
Ahora, necesitamos crear un archivo SQL con declaraciones DDL de tabla para que las tablas se creen tan pronto como el servidor esté en funcionamiento. Crearemos el archivo DDL.sql en el directorio src / main / resources y agregaremos algunas declaraciones DDL en él.
Dado que estamos usando la base de datos H2, también tenemos que agregar dependencias para eso.
Ahora, al usar HikariModule, podemos inicializar la base de datos en el tiempo de ejecución:
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. Prueba
Como se mencionó anteriormente, Ratpack tiene soporte de primera clase para casos de prueba de jUnit. Al usar MainClassApplicationUnderTest, podemos crear fácilmente casos de prueba y probar los puntos finales:
@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(); } }
Tenga en cuenta que debemos finalizar manualmente la instancia de MainClassApplicationUnderTest en ejecución llamando al método close () , ya que puede bloquear innecesariamente los recursos de JVM. Es por eso que hemos usado la anotación @After para terminar forzosamente la instancia una vez que se ejecutó el caso de prueba.
5. Conclusión
En este artículo, vimos la simplicidad de usar Ratpack.
Como siempre, el código fuente completo está disponible en GitHub.