Введение в JBoss Undertow

1. Обзор

Undertow - это чрезвычайно легкий и высокопроизводительный веб-сервер от JBoss . Он поддерживает как блокирующие, так и неблокирующие API с NIO .

Поскольку он написан на Java, его можно использовать в любых приложениях на основе JVM во встроенном режиме, даже сервер WilfFly от JBoss внутренне использует Undertow для повышения производительности сервера.

В этом уроке мы покажем возможности Undertow и способы его использования.

2. Почему Undertow?

  • Легковес: Undertow чрезвычайно легок и занимает менее 1 МБ. Во встроенном режиме он использует только 4 МБ кучи во время выполнения.
  • Сервлет 3.1: он полностью поддерживает сервлет 3.1
  • Веб-сокет: поддерживает функциональность веб-сокета (включая JSR-356 )
  • Постоянное соединение: по умолчанию Undertow включает постоянные HTTP-соединения, добавляя заголовок ответа keep-alive . Это помогает клиентам, которые поддерживают постоянные подключения, оптимизировать производительность за счет повторного использования сведений о подключении.

3. Использование Undertow

Давайте начнем использовать Undertow с создания простого веб-сервера.

3.1. Зависимость от Maven

Чтобы использовать Undertow , нам нужно добавить следующую зависимость к нашему pom.xml :

 io.undertow undertow-servlet 1.4.18.Final 

Чтобы создать работающий jar, нам также нужно добавить maven-shade-plugin. Вот почему нам также нужно добавить конфигурацию ниже:

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

Последняя версия Undertow доступна в центральном репозитории Maven.

3.2. Простой сервер

С помощью приведенного ниже фрагмента кода мы можем создать простой веб-сервер с помощью Undertow Builder API:

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

Здесь мы использовали API Builder для привязки порта 8080 к этому серверу. Также обратите внимание, что мы использовали лямбда-выражение для использования обработчика.

Мы также можем использовать приведенный ниже фрагмент кода, чтобы сделать то же самое без использования лямбда-выражений:

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

Здесь важно отметить использование HttpHandler API. Это самый важный плагин для настройки приложения Undertow в соответствии с нашими потребностями.

В этом случае мы добавили настраиваемый обработчик, который будет добавлять заголовок ответа Content-Type: text / plain с каждым запросом.

Аналогичным образом, если мы хотим возвращать некоторый текст по умолчанию с каждым ответом, мы можем использовать приведенный ниже фрагмент кода:

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

3.3. Безопасный доступ

В большинстве случаев мы не разрешаем всем пользователям получать доступ к нашему серверу. Обычно доступ могут получить пользователи с действующими учетными данными. Мы можем реализовать тот же механизм с помощью Undertow .

Для его реализации нам нужно создать диспетчер идентификации, который будет проверять подлинность пользователя при каждом запросе.

Для этого мы можем использовать IdentityManager Undertow :

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

После создания диспетчера удостоверений нам нужно создать область, в которой будут храниться учетные данные пользователя:

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

Здесь мы использовали AuthenticationMode как PRO_ACTIVE, что означает, что каждый запрос, поступающий на этот сервер, будет передан определенным механизмам аутентификации для быстрого выполнения аутентификации.

Если мы определим AuthenticationMode как CONSTRAINT_DRIVEN , то только те запросы будут проходить через определенные механизмы аутентификации, в которых срабатывает ограничение / s, которое требует аутентификации.

Теперь нам просто нужно сопоставить эту область и диспетчер удостоверений с сервером перед его запуском:

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

Здесь мы создали два пользовательских экземпляра с учетными данными. После того, как сервер будет запущен, для доступа к нему нам необходимо использовать любые из этих двух учетных данных.

3.4. Веб-сокет

Канал обмена веб- сокетами легко создать с помощью API-интерфейса WebSocketHttpExchange от UnderTow .

Например, мы можем открыть канал связи сокета на пути baeldungApp с помощью фрагмента кода ниже:

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

Мы можем создать HTML-страницу с именем index.html и использовать JavaScript WebSocket API для подключения к этому каналу.

3.5. Файловый сервер

С помощью Undertow мы также можем создать файловый сервер, который может отображать содержимое каталога и напрямую обслуживать файлы из каталога:

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

Нам не нужно создавать какое-либо содержимое пользовательского интерфейса для отображения содержимого каталога. В готовом к эксплуатации Undertow есть страница для этой функции отображения.

4. Плагин Spring Boot

Помимо Tomcat и Jetty, Spring Boot поддерживает UnderTow в качестве встроенного контейнера сервлетов. Чтобы использовать Undertow , нам нужно добавить следующую зависимость в pom.xml:

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

Последняя версия плагина Spring Boot Undertow доступна в центральном репозитории Maven.

5. Заключение

В этой статье мы узнали о Undertow и о том, как с его помощью создавать различные типы серверов.

Как всегда, полный исходный код доступен на GitHub.