Jettyで始めるWebSocket超入門

第4回サーバ側の実装(後編)

今回は、前回に引き続き、Jettyを使ったWebSocketに対応したチャットアプリケーションのサーバ側の実装を行ないます。

MyWebSocketServlet

クライアントから接続要求があった時に、⁠WebSocket」インターフェイスの実装クラスを返す「Servlet」を作成する必要があります。

以下のように新規クラスを作成してください。

  • ソース・フォルダー:WebSocketChat/src/main/java
  • パッケージ:webSocketChat
  • 名前:MyWebSocketServlet
  • スーパークラス:org.eclipse.jetty.websocket.WebSocketServlet

クライアントから接続があった時に呼ばれる「doWebSocketConnect」メソッドを、⁠MyWebSocket」インスタンスを返すように修正します。

package webSocketChat;

import javax.servlet.http.HttpServletRequest;

import org.eclipse.jetty.websocket.WebSocket;
import org.eclipse.jetty.websocket.WebSocketServlet;

public class MyWebSocketServlet extends WebSocketServlet {

  @Override
  protected WebSocket doWebSocketConnect(HttpServletRequest request,
      String protocol) {
    return new MyWebSocket();
  }

}

WebSocketChat

WebSocketChatの本体を実装します。次のように新規クラスを作成してください。

  • ソース・フォルダー:WebSocketChat/src/main/java
  • パッケージ:webSocketChat
  • 名前:WebSocketChat
  • スーパークラス:java.lang.Object
  • 「public static void main(String[] args)」にチェック

このクラスでは、サーバの作成・サーバに乗せるためのHandlerの作成と設定を行ない、サーバを起動します。コード全体を示した後に詳しく説明します。

package webSocketChat;

import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

public class WebSocketChat {

  public static void main(String[] args) throws Exception {
    new WebSocketChat();
  }

  public WebSocketChat() throws Exception {

    Server server = new Server(8040);

    ResourceHandler rh = new ResourceHandler();
    rh.setResourceBase(this.getClass().getClassLoader().getResource("html").toExternalForm());

    MyWebSocketServlet wss = new MyWebSocketServlet();
    ServletHolder sh = new ServletHolder(wss);
    ServletContextHandler sch = new ServletContextHandler();
    sch.addServlet(sh, "/ws/*");

    HandlerList hl = new HandlerList();
    hl.setHandlers(new Handler[] {rh, sch});
    server.setHandler(hl);

    server.start();

  }

}

それでは、それぞれの処理内容を見ていきましょう。

    Server server = new Server(8040);

ポート番号を指定しJettyのサーバをインスタンス化しています。ここまでに作成したMyWebSocketServletは、Handlerとしてサーバに登録する必要があります。同様に、HTTPでアクセスできるようにするためにResourceHanderも必要です。

まず、ResourceHandlerを先に準備します。ResourceHandlerは以下のようになっています。

    ResourceHandler rh = new ResourceHandler();
    rh.setResourceBase(this.getClass().getClassLoader().getResource("html").toExternalForm());

setResourceBaseの引数には、HTMLファイル等のクライアントで使用するリソースへのパスを指定しています。リソースは、Mavenでプロジェクトを作成した時に作られる「src/main/resources」内に配置します。ここはプログラム全体からアクセスが可能なため、⁠resources」ディレクトリ内に「html」ディレクトリを作成し、この中にプラウザ向け、つまりHTTPでアクセスされた時に使用されるファイルを格納します[1]⁠。そして、⁠this.getClass().getClassLoader().getResource("html")」「html」ディレクトリへの「URL」オブジェクトを取得し文字列に変換しています[2]⁠。

以上で、ResourceHandlerの準備ができました。

次は、MyWebSocketServletです。

    MyWebSocketServlet wss = new MyWebSocketServlet();
    ServletHolder sh = new ServletHolder(wss);
    ServletContextHandler sch = new ServletContextHandler();
    sch.addServlet(sh, "/ws/*");

ServletをHandlerとして登録する必要があると言及しましたが、ServletをそのままHandlerにすることはできません。そこで、MyWebSocketServletをまず「ServletHolder」オブジェクトでラップした後、⁠ServletContextHandler」に追加しています。追加の時に、⁠/ws/」にマッピングしています[3]⁠。

次に、ServerオブジェクトにHandlerを登録します。バージョン6のJettyのServerオブジェクトは、Handlerを引数にとる「setHandler」「addHandler」メソッド、Handlerの配列を引数にとる「setHandlers」メソッドを持っていました。ところが、バージョン7ではHandlerを登録するメソッドは「setHandler」しかありません。Jetty7では次のようにすると複数登録できます。

    HandlerList hl = new HandlerList();
    hl.setHandlers(new Handler[] {rh, sch});
    server.setHandler(hl);

つまり、⁠Handler」インターフェイスを実装した「HandlerList」インスタンスに対しHandlerを複数追加し、それをサーバに設定します[4]⁠。

最後にサーバを起動します。

    server.start();

次回予告

次回は、クライアント側の実装を解説します。

おすすめ記事

記事・ニュース一覧