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]から入手可能です。