<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    小菜毛毛技術(shù)分享

    與大家共同成長

      BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
      164 Posts :: 141 Stories :: 94 Comments :: 0 Trackbacks
    http://homelink.javaeye.com/blog/293328#comments
    參考文檔 http://www.ibm.com/developerworks/cn/web/wa-lo-comet/

            comet是HTTP長連接,就是在HTTP發(fā)送請求時(shí),服務(wù)器不立刻發(fā)送響應(yīng)信息給客戶端, 而是保持著連接,等待一定情況發(fā)生后才把數(shù)據(jù)發(fā)送回去給客戶端。所以用comet可以實(shí)現(xiàn)服務(wù)器端的數(shù)據(jù)實(shí)時(shí)地發(fā)送給客戶端。

            本文主要是用java和js來簡單地實(shí)現(xiàn)comet,最后附上源碼和使用例子。

            在客戶端用XMLRequest發(fā)送請求到服務(wù)器,在服務(wù)器端用一個(gè)servlet來接收XMLRequest的請求,當(dāng)接收到請 求時(shí),并不立刻響應(yīng)客戶端,而是把該servlet線程阻塞,等到一定事件發(fā)生后,再響應(yīng)客戶端。當(dāng)客戶端接收到服務(wù)端的響應(yīng)后,調(diào)用自定義的回調(diào)函數(shù)來 處理服務(wù)器發(fā)送回來的數(shù)據(jù),處理完成后,再發(fā)送一個(gè)XMLRequest請求到服務(wù)端,這樣循環(huán)下去,就可以實(shí)現(xiàn)數(shù)據(jù)的實(shí)時(shí)更新,又不必要在客戶端不斷地 輪循(polling)。

             利用該comet的實(shí)現(xiàn)(以后簡稱為keeper)時(shí),只要在客戶端注冊事件和寫一個(gè)處理返回?cái)?shù)據(jù)的回調(diào)函數(shù),然后在服務(wù)端實(shí)現(xiàn) keeper中的EventListener接口,調(diào)用Controller.action(eventListener,eventType)就可以 了。

            keeper分成兩大部分,第一部分為客戶端的javascript,第二部分是服務(wù)端的servlet和事件處理。

            一.客戶端

            建立一個(gè)XMLRequest對象池,每發(fā)送一次請求,從對象池中取一個(gè)XMLRequest對象,如果沒有可用的對象,則創(chuàng)建一 個(gè),把它加入到對象池中。這部分的代碼來自于網(wǎng)絡(luò)。

            為了使用方便,再添加一些方法,用來注冊事件。這樣只要調(diào)用注冊函數(shù)來注冊事件,并且把回調(diào)函數(shù)傳給注冊事件函數(shù)就行了,處理數(shù)據(jù) 的事情,交給回調(diào)函數(shù),并由用戶來實(shí)現(xiàn)。

            keeper為了方便使用,把客戶端的javascript代碼集成在servlet中,當(dāng)配置好keeper的servlet, 啟動HTTP服務(wù)器時(shí),keeper會根據(jù)用戶的配置,在相應(yīng)的目錄下生成客戶端的javascript代碼。

        二.服務(wù)端

            服務(wù)端的servlet初始化時(shí),根據(jù)配置來生成相應(yīng)的客戶端javascript代碼。

            servlet的入口由keeper.servlet.Keeper.java中的doGet進(jìn)入。在Keeper的doGet 中,從請求中獲取用戶注冊事件的名稱(字符串類型),然后根據(jù)事件的名稱,構(gòu)造一個(gè)事件(Event類型),再把它注冊到NameRegister中,注 冊完成后,該servlet線程調(diào)用wait(),把自已停止。等待該servlet線程被喚醒后,從Event中調(diào)用事件的EventListener 接口的process(request,response)來處理客戶端的請求。

    1.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    2.         String eventName = request.getParameter("event");
    3.         NameRegister reg = NameRegister.getInstance();
    4.         Event event = null;
    5.         try {
    6.             event = reg.getEvent(eventName);
    7.             if(event == null) {
    8.                 event = new Event(eventName,this);
    9.                 reg.registeEvent(eventName, event);
    10.             }
    11.             if(event.getServlet() == null) {
    12.                 event.setServlet(this);
    13.             }
    14.             
    15.         } catch (RegistException e1) {
    16.             e1.printStackTrace();
    17.         }
    18.         synchronized(this) {
    19.             while(!event.isProcess()) {
    20.                 try {
    21.                     wait();
    22.                 } catch (InterruptedException e) {
    23.                     e.printStackTrace();
    24.                 }
    25.             }
    26.         }
    27.         EventListener listener = event.getListener();
    28.         if(listener != null) {
    29.            listener.process(request,response);
    30.         }   
    31.     }

            在服務(wù)端處理事件時(shí),調(diào)用了keeper.control.Controller中的靜態(tài)方法 action(EventListener listener,String eventName)來處理。如下所示。

    1.     public static boolean action(EventListener listener,String eventName){
    2.         NameRegister reg = NameRegister.getInstance();
    3.         HttpServlet servlet = null;
    4.         Event e = null;
    5.         try {
    6.             e = reg.getEvent(eventName,true);
    7.             if(e == null) {
    8.                 return false;
    9.             }
    10.             e.setListener(listener);
    11.             servlet = e.getServlet();
    12.             e.setProcess(true);
    13.             synchronized(servlet) {
    14.                 servlet.notifyAll();
    15.             }
    16.         } catch (RegistException ex) {
    17.             ex.printStackTrace();
    18.             }
    19.         if(servlet != null && e != null) {
    20.             e = null;
    21.             return true;
    22.         } else {
    23.             return false;
    24.         }
    25.     }

    下面開始用keeper來寫一個(gè)簡單的網(wǎng)頁聊天程序和基于服務(wù)端的時(shí)間。

        1.客戶端設(shè)置

            注冊兩個(gè)事件,一個(gè)用于是時(shí)間事件,一個(gè)是消息事件。同時(shí)還要寫兩個(gè)回調(diào)函數(shù),用于處理服務(wù) 端返回的時(shí)間和聊天消息。如下所于:

    1. <script type="text/javascript">
    2.     Keeper.addListener('timer',showTime);//注冊時(shí)間事件
    3.     function showTime(obj){ //時(shí)間處理回調(diào)函數(shù)
    4.         var sp = document.getElementById("dateTime");
    5.         if(sp){
    6.             sp.innerHTML = obj.responseText;
    7.         }
    8.     }
    9.     function startOrStop(obj){
    10.         var btn = document.getElementById("controlBtn")
    11.         btn.value=obj.responseText;
    12.     }
    13.     Keeper.addListener('msg',showMsg,"GBK");//注冊消息事 件,最后一個(gè)參數(shù)是
    14. //字符串編碼
    15.     function showMsg(obj){//處理消息的回調(diào)函數(shù)
    16.         var msg = document.getElementById("msg");
    17.         if(msg){
    18.             
    19.                 msg.value = obj.responseText+""n"+msg.value;
    20.             
    21.         }
    22.     }
    23.     function sendMsg() {
    24.         var msg = document.getElementById("sendMsg");
    25.         if(msg){
    26.             var d = "msg="+msg.value;
    27.             sendReq('POST','./demo',d,startOrStop);
    28.             msg.value = "";
    29.         }
    30.     }
    31.     
    32. </script>

        2.配置服務(wù)端

        服務(wù)端的配置在 web.xml文件中,如下所示

    1.   <servlet>
    2.     <servlet-name>keeper</servlet-name>
    3.     <servlet-class>keeper.servlet.Keeper</servlet-class>
    4.     <init-param>
    5. <!--可選項(xiàng),設(shè)置生成客戶端的JavaScript路徑和名字,默認(rèn)置為 /keeper.js-->
    6.       <param-name>ScriptName</param-name>
    7.       <param-value>/keeperScript.js</param-value>
    8.     </init-param>
    9. <!--這個(gè)一定要設(shè)置,否則不能生成客戶端代碼-->
    10.     <load-on-startup>1</load-on-startup>
    11.   </servlet>
    12.   <servlet-mapping>
    13.     <servlet-name>keeper</servlet-name>
    14.     <url-pattern>/keeper</url-pattern>
    15.   </servlet-mapping>

            用<script type="text/javascript" src="./keeperScript.js"></script>在頁面包含JavaScript時(shí),這里的src一定要和上面配 置的一至。上面的設(shè)置除了<init-param></init-param>為可選的設(shè)置外,其他的都是必要的,而且不能改 變。

            3.編寫事件處理代碼,消息的處理代碼如下:
    1.     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    2.         System.out.println("Post..");
    3.         String msg = request.getParameter("msg");
    4.         Controller.action(new SendMsg(msg),"msg");
    5.     }
    1. class SendMsg implements EventListener{
    2.     private String msg;
    3.     public SendMsg(String msg) {
    4.         this.msg = msg;
    5.     }
    6.     @Override
    7.     public void process(HttpServletRequest request, HttpServletResponse response) {
    8.         response.setCharacterEncoding("UTF-8");
    9.         PrintWriter out = null;
    10.         try {
    11.             out = response.getWriter();
    12.             if(msg!=null){
    13.                 out.write(msg);
    14.             }
    15.         } catch (IOException e) {   
    16.             e.printStackTrace();
    17.         }
    18.         finally{
    19.             if(out != null) {
    20.                 out.close();
    21.             }
    22.         }       
    23.     }
    24. }

     到這時(shí),一個(gè)基本的keeper應(yīng)用就完成了。其它部分請參考附件中的例子源碼。

    • Keeper_KeeperDemo.rar (36 KB)
    • 描述: comet的實(shí)現(xiàn)和應(yīng)用例子
    • 下載次數(shù): 767

    posted on 2010-06-02 15:31 小菜毛毛 閱讀(3053) 評論(1)  編輯  收藏 所屬分類: java基礎(chǔ)運(yùn)用

    Feedback

    # re: 用java實(shí)現(xiàn)comet,基于 HTTP長連接的實(shí)現(xiàn),用于從服務(wù)端實(shí)時(shí)發(fā)送信息到客戶端 2014-06-10 10:42 趙迪生
    這不是掩耳盜鈴么  回復(fù)  更多評論
      

    主站蜘蛛池模板: 亚洲AⅤ永久无码精品AA| 亚洲精品美女久久7777777| 四虎影视免费永久在线观看| 久久免费福利视频| 一级做a爰片性色毛片免费网站| 亚洲视频网站在线观看| 亚洲精品成人片在线播放| 国产一区二区三区在线免费观看 | 亚洲AⅤ优女AV综合久久久| 毛片免费观看视频| 美丽的姑娘免费观看在线播放| a高清免费毛片久久| 国产成人亚洲精品蜜芽影院| 国产亚洲国产bv网站在线| 在线观看亚洲人成网站| 亚洲精品你懂的在线观看| 亚洲精品无码久久不卡| 日本特黄特色免费大片| 青娱乐免费在线视频| 亚洲第一网站免费视频| 99re视频精品全部免费| 免费网站看av片| 国产一精品一AV一免费| 在线观看肉片AV网站免费| 91av免费在线视频| 特级毛片aaaa免费观看| 日韩毛片一区视频免费| 免费视频成人国产精品网站| 美女黄频免费网站| 337P日本欧洲亚洲大胆精品| 亚洲高清国产拍精品熟女| 亚洲AV永久无码精品网站在线观看| 亚洲无mate20pro麻豆| 亚洲中文精品久久久久久不卡| 国产精品亚洲片在线va| 亚洲综合精品伊人久久| 亚洲日产乱码一二三区别| 亚洲综合精品伊人久久| 亚洲AV色无码乱码在线观看| 朝桐光亚洲专区在线中文字幕| 久久亚洲精品无码gv|