Introducción a JBoss Undertow

1. Información general

Undertow es un servidor web extremadamente ligero y de alto rendimiento de JBoss . Admite API de bloqueo y no bloqueo con NIO .

Dado que está escrito en Java, se puede usar en cualquier aplicación basada en JVM en modo embebido, incluso el servidor WilfFly de JBoss usa internamente Undertow para mejorar el rendimiento del servidor.

En este tutorial, mostraremos las características de Undertow y cómo usarlo.

2. ¿Por qué resaca?

  • Ligero: Undertow es extremadamente liviano con menos de 1 MB. En el modo integrado, utiliza solo 4 MB de espacio de pila en tiempo de ejecución
  • Servlet 3.1: es totalmente compatible con Servlet 3.1
  • Web Socket: admite la funcionalidad Web Socket (incluido JSR-356 )
  • Conexión persistente: de forma predeterminada, Undertow incluye conexiones persistentes HTTP al agregar un encabezado de respuesta de mantener vivo . Ayuda a los clientes que admiten conexiones persistentes a optimizar el rendimiento reutilizando los detalles de la conexión.

3. Uso de Undertow

Comencemos a usar Undertow creando un servidor web simple.

3.1. Dependencia de Maven

Para usar Undertow , necesitamos agregar la siguiente dependencia a nuestro pom.xml :

 io.undertow undertow-servlet 1.4.18.Final 

Para construir un jar ejecutable, también necesitamos agregar maven-shade-plugin. Es por eso que también necesitamos agregar la siguiente configuración:

 org.apache.maven.plugins maven-shade-plugin   package  shade    

La última versión de Undertow está disponible en Central Maven Repository.

3.2. Servidor simple

Con el siguiente fragmento de código, podemos crear un servidor web simple utilizando la API de construcción de Undertow :

public class SimpleServer { public static void main(String[] args) { Undertow server = Undertow.builder().addHttpListener(8080, "localhost").setHandler(exchange -> { exchange.getResponseHeaders() .put(Headers.CONTENT_TYPE, "text/plain"); exchange.getResponseSender().send("Hello Baeldung"); }).build(); server.start(); } }

Aquí, hemos utilizado la API del constructor para vincular el puerto 8080 a este servidor. Además, tenga en cuenta que hemos usado una expresión lambda para usar el controlador.

También podemos usar el siguiente fragmento de código para hacer lo mismo sin usar expresiones lambda:

Undertow server = Undertow.builder().addHttpListener(8080, "localhost") .setHandler(new HttpHandler() { @Override public void handleRequest(HttpServerExchange exchange) throws Exception { exchange.getResponseHeaders().put( Headers.CONTENT_TYPE, "text/plain"); exchange.getResponseSender().send("Hello Baeldung"); } }).build();

Lo importante a tener en cuenta aquí es el uso de la API HttpHandler . Es el complemento más importante para personalizar una aplicación Undertow en función de nuestras necesidades.

En este caso, hemos agregado un controlador personalizado que agregaría el encabezado de respuesta Content-Type: text / plain con cada solicitud.

De manera similar, si queremos devolver un texto predeterminado con cada respuesta, podemos usar el siguiente fragmento de código:

exchange.getResponseSender() .send("Hello Baeldung");

3.3. Acceso seguro

En la mayoría de los casos, no permitimos que todos los usuarios accedan a nuestro servidor. Por lo general, los usuarios con credenciales válidas pueden obtener acceso. Podemos implementar el mismo mecanismo con el Undertow .

Para implementarlo, necesitamos crear un administrador de identidad que verificará la autenticidad del usuario para cada solicitud.

Podemos usar IdentityManager de Undertow para esto:

public class CustomIdentityManager implements IdentityManager { private Map users; // standard constructors @Override public Account verify(Account account) { return account; } @Override public Account verify(Credential credential) { return null; } @Override public Account verify(String id, Credential credential) { Account account = getAccount(id); if (account != null && verifyCredential(account, credential)) { return account; } return null; } }

Una vez que se crea el administrador de identidad, necesitamos crear un reino que contendrá las credenciales del usuario:

private static HttpHandler addSecurity( HttpHandler toWrap, IdentityManager identityManager) { HttpHandler handler = toWrap; handler = new AuthenticationCallHandler(handler); handler = new AuthenticationConstraintHandler(handler); List mechanisms = Collections.singletonList( new BasicAuthenticationMechanism("Baeldung_Realm")); handler = new AuthenticationMechanismsHandler(handler, mechanisms); handler = new SecurityInitialHandler( AuthenticationMode.PRO_ACTIVE, identityManager, handler); return handler; }

Aquí, hemos utilizado AuthenticationMode como PRO_ACTIVE, lo que significa que cada solicitud que llegue a este servidor se pasará a los mecanismos de autenticación definidos para realizar la autenticación con entusiasmo.

Si definimos AuthenticationMode como CONSTRAINT_DRIVEN , solo esas solicitudes pasarán por los mecanismos de autenticación definidos donde se activan las restricciones que exigen la autenticación.

Ahora, solo necesitamos mapear este reino y el administrador de identidad con el servidor antes de que comience:

public static void main(String[] args) { Map users = new HashMap(2); users.put("root", "password".toCharArray()); users.put("admin", "password".toCharArray()); IdentityManager idm = new CustomIdentityManager(users); Undertow server = Undertow.builder().addHttpListener(8080, "localhost") .setHandler(addSecurity(e -> setExchange(e), idm)).build(); server.start(); } private static void setExchange(HttpServerExchange exchange) { SecurityContext context = exchange.getSecurityContext(); exchange.getResponseSender().send("Hello " + context.getAuthenticatedAccount().getPrincipal().getName(), IoCallback.END_EXCHANGE); }

Aquí, hemos creado dos instancias de usuario con credenciales. Una vez que el servidor está activo, para acceder a él, necesitamos usar cualquiera de estas dos credenciales.

3.4. Zócalo web

Es sencillo crear un canal de intercambio de sockets web con la API WebSocketHttpExchange de UnderTow .

Por ejemplo, podemos abrir un canal de comunicación de socket en la ruta baeldungApp con el siguiente fragmento de código:

public static void main(String[] args) { Undertow server = Undertow.builder().addHttpListener(8080, "localhost") .setHandler(path().addPrefixPath("/baeldungApp", websocket( (exchange, channel) -> { channel.getReceiveSetter().set(getListener()); channel.resumeReceives(); })).addPrefixPath("/", resource(new ClassPathResourceManager( SocketServer.class.getClassLoader(), SocketServer.class.getPackage())).addWelcomeFiles("index.html"))) .build(); server.start(); } private static AbstractReceiveListener getListener() { return new AbstractReceiveListener() { @Override protected void onFullTextMessage(WebSocketChannel channel, BufferedTextMessage message) { String messageData = message.getData(); for (WebSocketChannel session : channel.getPeerConnections()) { WebSockets.sendText(messageData, session, null); } } }; }

Podemos crear una página HTML llamada index.html y usar la API WebSocket de JavaScript para conectarnos a este canal.

3.5. Servidor de archivos

Con Undertow , también podemos crear un servidor de archivos que puede mostrar el contenido del directorio y sirve directamente los archivos del directorio:

public static void main( String[] args ) { Undertow server = Undertow.builder().addHttpListener(8080, "localhost") .setHandler(resource(new PathResourceManager( Paths.get(System.getProperty("user.home")), 100 )) .setDirectoryListingEnabled( true )) .build(); server.start(); }

No necesitamos crear ningún contenido de interfaz de usuario para mostrar el contenido del directorio. Fuera de la caja Undertow ofrece una página para esta funcionalidad de visualización.

4. Complemento Spring Boot

Además de Tomcat y Jetty, Spring Boot admite UnderTow como contenedor de servlets integrado. Para usar Undertow , necesitamos agregar la siguiente dependencia en pom.xml:

 org.springframework.boot spring-boot-starter-undertow 1.5.6.RELEASE 

La última versión del complemento Spring Boot Undertow está disponible en Central Maven Repository.

5. Conclusión

En este artículo, aprendimos sobre Undertow y cómo podemos crear diferentes tipos de servidores con él.

Como siempre, el código fuente completo está disponible en GitHub.