【特集】

Tomcat 6の実力を早速試す - 移行するべき? その時期は?

15 I/O機能の拡張によるCometのサポート(2)

    杉山貴章  [2007/04/03]

    Cometを利用したサーブレットの例

    それでは、早速Cometを利用したアプリケーションを作ってみよう。TomcatでComtを使用するには、HttpServletにおいてorg.apache.catalina.CometProcessorというインタフェースをimplementsする。このインタフェースにはeventというメソッドが宣言されている。CometProcessorをimplementsしたサーブレットにアクセスがあると、org.apache.catalina.CometEventというイベントが発生し、doGetやdoPostの代わりにeventメソッドにCometEventが渡されて呼び出される。

    したがって基本的な形はリスト23のようになる。eventメソッド内にリクエストを処理するコードを記述しておけばよい。

    リスト23 Cometを使うサーブレットプログラムの基本形

    public class CometSampleServlet 
           extends HttpServlet  implements CometProcessor {
        public void event(CometEvent event) 
               throws IOException, ServletException {
            //ここに処理を記述する
        }
    }

    CometEventには次に示す4種類のタイプが定義されている。セッションを終了するにはCometEventのcloseメソッドを呼び出す。

    • EventType.BEGIN: コネクションが確率した際のイベント
    • EventType.END: リクエストの処理が終了した際のイベント
    • EventType.ERROR: I/Oエラーなど、何らかのエラーが発生した際のイベント
    • EventType.READ: データの入力があった場合のイベント

    リスト24に、Cometを使用したサーブレットの例を示す。このサーブレットはリクエストを発行したブラウザに対して、コネクションを張ったまま5秒毎に時刻を送り続けるという処理をする。データの送信はMessageSenderというスレッドで行う。

    リスト24 Cometを使うサーブレットの例(CometSampleServlet.java)

    package sample;
     
    import java.io.*;
    import java.net.*;
    import java.util.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import org.apache.catalina.CometEvent;
    import org.apache.catalina.CometProcessor;
     
    public class CometSampleServlet 
            extends HttpServlet  implements CometProcessor {
        
        protected ArrayList<HttpServletResponse> connections = 
            new ArrayList<HttpServletResponse>();
        protected MessageSender sender = null;
     
        /**
         * アクセスがあった際に呼び出されるイベントハンドラ
         */
        public void event(CometEvent event) throws IOException, ServletException {
            HttpServletRequest request = event.getHttpServletRequest();
            HttpServletResponse response = event.getHttpServletResponse();
    
            if (event.getEventType() == CometEvent.EventType.BEGIN) {
                // データの送信を開始
                request.setAttribute("org.apache.tomcat.comet", Boolean.TRUE);
                PrintWriter writer = response.getWriter();
                writer.println("<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">");
                writer.println("<head><title>Comet Sample</title></head><body>");
                writer.flush();
                synchronized(connections) {
                    connections.add(response);
                }
            }
            else if (event.getEventType() == CometEvent.EventType.ERROR) {
                // エラー発生時
                synchronized(connections) {
                    connections.remove(response);
                }
                event.close();
            }
            else if (event.getEventType() == CometEvent.EventType.END) {
                // データの送信を終了
                synchronized(connections) {
                    connections.remove(response);
                }
                PrintWriter writer = response.getWriter();
                writer.println("</body></html>");
                event.close();
            } 
            else if (event.getEventType() == CometEvent.EventType.READ) {
            }
        }
        
        /**
         * 初期化処理
         */
        public void init() throws ServletException {
            sender = new MessageSender();
            Thread senderThread = new Thread(sender);
            senderThread.setDaemon(true);
            senderThread.start();
        }
     
        /**
         * 終了処理
         */
        public void destroy() {
            connections.clear();
            sender.stop();
            sender = null;
        }
        
        /**
         * データ送信用のスレッド
         */
        public class MessageSender implements Runnable {
            // 後述
        }
    }

    まず、初期化段階でMessageSenderスレッドを起動して送信の準備を行う(initメソッド)。eventメソッドでは、BEGINイベントを受け取った場合にHTMLのヘッダを送信する。複数のコネクションを処理するために、受け取ったHttpResponseはリストに保持しておく。ENDイベントの場合はHTMLの閉じタグを送信してセッションを終了する。ERRORイベントでも同様にセッションを終了する。READイベントは今回は処理しない。

    新着記事

    特設サイトの情報

      人気記事

      一覧

        イチオシ記事

        新着記事

        特別企画

        マイナビニュースマガジン