JBoss Undertowの紹介

1概要

  • Undertow は、 JBoss 製の非常に軽量で高性能なWebサーバーです。** NIO を使用したブロッキングAPIと非ブロッキングAPIの両方をサポートします。

この記事はJavaで書かれているので、組み込みモードのJVMベースのアプリケーションであればどれでも使用できます。JBossの WilfFly サーバーでも内部で Undertow を使用してサーバーのパフォーマンスを向上させます。

このチュートリアルでは、Undertowの機能と使い方について説明します。

** 2なぜUndertow?

**

  • 軽量: Undertow は1MB以下で非常に軽量です。に

埋め込みモード。実行時に4MBのヒープスペースしか使用しません。 ** Servlet 3.1: Servlet 3.1 を完全にサポート

  • Web Socket:Web Socket機能をサポートします( JSR-356 を含む)。

  • 持続的接続:デフォルトでは、 Undertow はHTTP持続的を含みます

keep-alive 応答ヘッダーを追加して接続します。持続的接続をサポートするクライアントが、接続の詳細を再利用することによってパフォーマンスを最適化するのに役立ちます。

** 3 Undertowを使う

**

簡単なWebサーバーを作成して Undertow を使い始めましょう。

** 3.1. メーベン依存

**

Undertow を使用するには、 pom.xml に次の依存関係を追加する必要があります。

<dependency>
    <groupId>io.undertow</groupId>
    <artifactId>undertow-servlet</artifactId>
    <version>1.4.18.Final</version>
</dependency>

実行可能なjarファイルを作成するには、https://maven.apache.org/plugins/maven-shade-plugin/[maven-shade-plugin]も追加する必要があります。

そのため、以下の設定も追加する必要があります。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Undertow の最新版はhttps://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22io.undertow%22[Central Maven Repository]にあります。

** 3.2. シンプルサーバー

**

下記のコードスニペットを使うと、Undertowのhttp://undertow.io/javadoc/1.4.x/io/undertow/Undertow.Builder.html[ Builder ]APIを使用して簡単なWebサーバーを作成できます。

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

ここでは、 Builder APIを使用して 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();

ここで注意すべき重要なことはhttp://undertow.io/javadoc/1.4.x/io/undertow/server/HttpHandler.html[ HttpHandler ]APIの使用法です。 私たちのニーズに基づいて Undertow アプリケーションをカスタマイズすることが最も重要なプラグインです。

この場合、各リクエストに Content-Type:text/plain レスポンスヘッダーを追加するカスタマイズされたハンドラーを追加しました。

同様に、各応答とともにデフォルトのテキストを返したい場合は、以下のコードスニペットを使用できます。

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

3.3. 安全なアクセス

ほとんどの場合、すべてのユーザーにサーバーへのアクセスを許可するわけではありません。通常、有効な認証情報を持つユーザーがアクセスできます。 Undertow を使用して同じメカニズムを実装できます。

  • それを実装するには、リクエストごとにユーザーの信頼性をチェックするIDマネージャを作成する必要があります。**

これには、Undertowの http://undertow.io/javadoc/1.4.x/io/undertow/security/idm/IdentityManager ** 。 を使用できます。

public class CustomIdentityManager implements IdentityManager {
    private Map<String, char[]> 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<AuthenticationMechanism> mechanisms = Collections.singletonList(
      new BasicAuthenticationMechanism("Baeldung__Realm"));
    handler = new AuthenticationMechanismsHandler(handler, mechanisms);
    handler = new SecurityInitialHandler(
      AuthenticationMode.PRO__ACTIVE, identityManager, handler);
    return handler;
}

ここでは、このサーバーに送られるすべての要求が、積極的に認証を実行するために、定義された認証メカニズムに渡されます。

  • AuthenticationMode CONSTRAINT DRIVEN__として定義した場合、それらの要求だけが認証を要求する制約が引き起こされる定義された認証メカニズムを通ります。

それでは、起動する前に、このレルムとIDマネージャをサーバーにマッピングするだけです。

public static void main(String[]args) {
    Map<String, char[]> 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);
}

ここでは、認証情報を使用して2つのユーザーインスタンスを作成しました。サーバーが起動したら、アクセスするには、これら2つの資格情報のいずれかを使用する必要があります。

** 3.4. Webソケット

**

UnderTowのhttp://undertow.io/javadoc/1.4.x/io/undertow/webbsockets/spi/WebSocketHttpExchange.html[ WebSocketHttpExchange ] APIを使用してWebソケット交換チャネルを作成するのは簡単です。

例えば、以下のコードスニペットでパス 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);
            }
        }
    };
}

index.html という名前のHTMLページを作成し、JavaScriptの https://developer.mozilla.org/en-US/docs/Web/API/WebSockets API/Writing WebSocket client applications[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();
}

ディレクトリの内容を表示するためのUIコンテンツを作成する必要はありません。すぐに使用可能な Undertow は、この表示機能に関するページを提供します。

** 4 Spring Boot Plugin

**

Tomcat および Jetty 以外に、 Spring Boot は組み込みサーブレットコンテナとして UnderTow をサポートしています。 Undertow を使用するには、__pom.xmlに次の依存関係を追加する必要があります。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-undertow</artifactId>
    <version>1.5.6.RELEASE</version>
</dependency>

Spring Boot Undertow plugin の最新バージョンはhttps://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.springframework.boot%22%20AND%20a%3A%22spring-で入手可能ですboot-starter-undertow%22[Central Mavenリポジトリ]。

5結論

この記事では、 Undertow と、それを使ってさまざまなタイプのサーバーを作成する方法について学びました。

いつものように、完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/undertow[over on GitHub]から入手可能です。