Jetty comet技术初探

 

 

Jetty的org.mortbay.util.ajax.Continuation 接口:

    suspend(long timeout)  Suspend handling. // 相当于Object的wait
    resume() Resume the request. // 相当于Object的notify

    ......

 

 

Jetty 的Streaming Comet实现:

 

/**
 *
 */
package comet.first;

import java.io.IOException;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.mortbay.util.ajax.Continuation;
import org.mortbay.util.ajax.ContinuationSupport;

/**
 * Streaming Comet
 *
 * @author yangwm Sep 26, 2010 11:47:02 AM
 */
public class JettyCometStreaming extends HttpServlet {
    
    /**
     *
     */
    private static final long serialVersionUID = 8098872819945693191L;
    
    private static final int TIMEOUT = 3 * 1000;

    public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // handle the time request
        
        // get the jetty continuation
        Continuation con = ContinuationSupport.getContinuation(req, null);
        
        // set the header
        resp.setContentType("text/html");
        
        resp.getWriter().print("service begin " + new Date() + ", ");
        resp.getWriter().flush();

        // write time periodically
        while (resp.getWriter().checkError() == false) { // validity of the response's connection
            resp.getWriter().print("first... ");
            resp.getWriter().flush();
            
            /*
             * 每次被唤醒后恢复执行两次while循环开始 到con.suspend之前的代码 ,
             * 因为con.suspend() equivalence con.reset() if con.isPending() is true
             * 所以timeout之后重新从service开始执行--> con.suspend() --> con.suspend之后的代码 --> 继续while循环开始到con.suspend之前的代码,
             */
            con.suspend(TIMEOUT); // suspend the response
            
            resp.getWriter().print("end!");
            resp.getWriter().flush();
        }
        // ...
    }
    
}

 

 

 

Jetty 的Long Polling Comet实现:

/**
 *
 */
package comet.second;

import java.io.IOException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.mortbay.util.ajax.Continuation;
import org.mortbay.util.ajax.ContinuationSupport;

/**
 * Long Polling Comet
 *
 * @author yangwm Sep 28, 2010 11:47:02 AM
 */
public class JettyCometLongPolling extends HttpServlet {
   
    /**
     *
     */
    private static final long serialVersionUID = 8098872819945693191L;
   
    private static final int TIMEOUT = 30 * 1000;

    public void service(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        // handle the time request
       
        // get the jetty continuation
        Continuation con = ContinuationSupport.getContinuation(req, null);
        JettyContinuationManager.add("yangwm", con); // id is yangwm
       
        // set the header
        resp.setContentType("text/html");
       
        // write continuation resume
        if(con.suspend(TIMEOUT)) {
            System.out.println(con + ", get data: " + con.getObject());
            resp.getWriter().write(con + ", get data: " + con.getObject());
            resp.getWriter().flush();
        } else {
            System.out.println(con + ", timeout");
           
            resp.getWriter().write(con + ", timeout");
            resp.getWriter().flush();
           
            JettyContinuationManager.clear("yangwm"); // id is yangwm
        }
       
        // ...
    }
   
}

 

/**
 *
 */
package comet.second;

import java.io.IOException;
import java.util.Date;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.mortbay.util.ajax.Continuation;

/**
 * Notify Comet
 *
 * @author yangwm Sep 28, 2010 11:47:02 AM
 */
public class JettyCometNotify extends HttpServlet {
   
    /**
     *
     */
    private static final long serialVersionUID = 8098872819945693191L;

    public void service(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        // handle the time request
       
        Continuation con = JettyContinuationManager.get("yangwm"); // id is yangwm
       
        System.out.println(con + ", resume: ");
        resp.getWriter().write(con + ", resume: ");
        resp.getWriter().flush();
       
        if (con != null) {
            con.setObject(new Date() + ", it works!");
            con.resume();
        }

        // ...
    }
   
}

package comet.second;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.mortbay.util.ajax.Continuation;

/**
 * Continuation Manager
 *
 * @author yangwm Sep 28, 2010 11:47:02 AM
 */
public class JettyContinuationManager {
   
    private static ConcurrentMap map = new ConcurrentHashMap();
   
    public static void add(String key, Continuation con) {
        map.put(key, con);
    }
   
    public static void clear(String key) {
        map.remove(key);
    }
   
    public static Continuation get(String key){
        return map.get(key);
    }

}

Jetty 的Streaming Comet与Long Polling实现的配置:

 

 

 

web.xml:


    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">

    Welcome to testcomet
    
        Welcome to testcomet
     


    
        CometStreaming
        comet.first.JettyCometStreaming
    

    
        CometStreaming
        /stream
    

    
    
        CometLongPolling
        comet.second.JettyCometLongPolling
    

    
        CometLongPolling
        /longPoll
    

    
        CometNotify
        comet.second.JettyCometNotify
    

    
        CometNotify
        /notify
    

 

部署到jetty容器中。

 

1.Streaming方式:

D:/>curl http://127.0.0.1:8080/testcomet/stream

service begin Tue Sep 28 11:55:08 CST 2010, first... service begin Tue Sep 28 11:55:10 CST 2010, first... end!first...

 

第一次输出为:service begin Tue Sep 28 11:55:08 CST 2010, first...,也就是从service方法开始执行并不会执行suspend之后的代码。

之后输出为:service begin Tue Sep 28 11:55:10 CST 2010, first... end!first...,也就是从service方法开始执行并会执行suspend之后的代码。

 

2.Long Polling方式:

D:/>curl http://127.0.0.1:8080/testcomet/longPoll
RetryContinuation@9876930, get data: Tue Sep 28 11:57:04 CST 2010, it works

 

D:/>curl http://127.0.0.1:8080/testcomet/notify
RetryContinuation@9876930,pending,parked, resume:

 

先http://127.0.0.1:8080/testcomet/longPoll访问, 再访问http://127.0.0.1:8080/testcomet/notify。

 

 

学习参考资料:

TimYang的comet server之java实现:asyncweb,jetty,tomcat,http://hi.baidu.com/jabber/blog/item/f556c7fcbaa76286b801a042.html

Cometd & Jetty Continuations:http://geeklu.com/2010/07/cometd-jetty-continuations/

 

jetty javadoc: http://jetty.codehaus.org/jetty/jetty-6/apidocs/index.html

Comet (programming) - Wikipedia, the free encyclopedia:http://en.wikipedia.org/wiki/Comet_%28programming%29

Continuations - Jetty - Codehaus:http://docs.codehaus.org/display/JETTY/Continuations

Cometd (aka Bayeux) - Jetty - Codehaus:http://docs.codehaus.org/display/JETTY/Cometd+%28aka+Bayeux%29

Welcome to CometD Project @ The Dojo Foundation | cometd.org:http://www.cometd.org/

 

 

 

 

 

 

你可能感兴趣的:(java)