Introduction à JBoss Undertow

1. Vue d'ensemble

Undertow est un serveur Web extrêmement léger et performant de JBoss . Il prend en charge les API bloquantes et non bloquantes avec NIO .

Comme il est écrit en Java, il peut être utilisé dans toutes les applications basées sur JVM en mode intégré, même le serveur WilfFly de JBoss utilise Undertow en interne pour améliorer les performances du serveur.

Dans ce didacticiel, nous montrerons les fonctionnalités d'Undertow et comment l'utiliser.

2. Pourquoi Undertow?

  • Léger: Undertow est extrêmement léger à moins de 1 Mo. En mode intégré, il n'utilise que 4 Mo d'espace de tas au moment de l'exécution
  • Servlet 3.1: Il prend entièrement en charge Servlet 3.1
  • Web Socket: il prend en charge la fonctionnalité Web Socket (y compris JSR-356 )
  • Connexion persistante: par défaut, Undertow inclut les connexions persistantes HTTP en ajoutant un en - tête de réponse keep-alive . Il aide les clients qui prennent en charge les connexions persistantes à optimiser les performances en réutilisant les détails de connexion

3. Utilisation d'Undertow

Commençons à utiliser Undertow en créant un serveur Web simple.

3.1. Dépendance de Maven

Pour utiliser Undertow , nous devons ajouter la dépendance suivante à notre pom.xml :

 io.undertow undertow-servlet 1.4.18.Final 

Pour créer un fichier jar exécutable, nous devons également ajouter maven-shadow-plugin. C'est pourquoi nous devons également ajouter la configuration ci-dessous:

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

La dernière version d' Undertow est disponible dans le référentiel central de Maven.

3.2. Serveur simple

Avec l'extrait de code ci-dessous, nous pouvons créer un serveur Web simple à l'aide de l' API Builder d'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(); } }

Ici, nous avons utilisé l' API Builder pour lier le port 8080 à ce serveur. Notez également que nous avons utilisé une expression lambda pour utiliser le gestionnaire.

Nous pouvons également utiliser l'extrait de code ci-dessous pour faire la même chose sans utiliser d'expressions 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();

La chose importante à noter ici est l'utilisation de l' API HttpHandler . C'est le plugin le plus important pour personnaliser une application Undertow en fonction de nos besoins.

Dans ce cas, nous avons ajouté un gestionnaire personnalisé qui ajouterait l'en - tête Content-Type: text / plain response à chaque requête.

De manière similaire, si nous voulons renvoyer du texte par défaut avec chaque réponse, nous pouvons utiliser l'extrait de code ci-dessous:

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

3.3. Accès sécurisé

Dans la plupart des cas, nous n'autorisons pas tous les utilisateurs à accéder à notre serveur. Habituellement, les utilisateurs avec des informations d' identification valides peuvent obtenir access.We peut mettre en œuvre le même mécanisme avec le Undertow .

Pour l'implémenter, nous devons créer un gestionnaire d'identité qui vérifiera l'authenticité de l'utilisateur pour chaque demande.

Nous pouvons utiliser IdentityManager d' Undertow pour cela:

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

Une fois le gestionnaire d'identité créé, nous devons créer un domaine qui contiendra les informations d'identification de l'utilisateur:

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

Ici, nous avons utilisé le AuthenticationMode comme PRO_ACTIVE, ce qui signifie que chaque demande provenant de ce serveur sera transmise aux mécanismes d'authentification définis pour effectuer l'authentification avec empressement.

Si nous définissons AuthenticationMode comme CONSTRAINT_DRIVEN , alors seules ces demandes passeront par les mécanismes d'authentification définis où la ou les contraintes qui imposent l'authentification sont déclenchées.

Maintenant, nous avons juste besoin de mapper ce domaine et le gestionnaire d'identité avec le serveur avant qu'il ne démarre:

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

Ici, nous avons créé deux instances utilisateur avec des informations d'identification. Une fois le serveur en place, pour y accéder, nous devons utiliser l'une de ces deux informations d'identification.

3.4. Prise Web

Il est simple de créer un canal d'échange de socket Web avec l' API WebSocketHttpExchange d' UnderTow .

Par exemple, nous pouvons ouvrir un canal de communication de socket sur le chemin baeldungApp avec l'extrait de code ci-dessous:

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

Nous pouvons créer une page HTML nommée index.html et utiliser l' API WebSocket de JavaScript pour nous connecter à ce canal.

3.5. Serveur de fichiers

Avec Undertow , nous pouvons également créer un serveur de fichiers qui peut afficher le contenu du répertoire et sert directement les fichiers du répertoire:

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

Nous n'avons pas besoin de créer de contenu d'interface utilisateur pour afficher le contenu du répertoire. Out-of-the-box Undertow fournit une page pour cette fonctionnalité d'affichage.

4. Plug-in Spring Boot

Outre Tomcat et Jetty, Spring Boot prend en charge UnderTow en tant que conteneur de servlet intégré. Pour utiliser Undertow , nous devons ajouter la dépendance suivante dans le pom.xml:

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

La dernière version du plugin Spring Boot Undertow est disponible dans le référentiel central Maven.

5. Conclusion

Dans cet article, nous avons découvert Undertow et comment nous pouvons créer différents types de serveurs avec.

Comme toujours, le code source complet est disponible à l'adresse over sur GitHub.