posts - 19, comments - 1, trackbacks - 0, articles - 0
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
          這個(gè)題目含有許多需要解釋的概念,最容易說(shuō)明的是“站內(nèi)消息”,這是很多論壇都有的功能,可以通過(guò)web向其他的在線用戶發(fā)送消息,很多用戶都使用過(guò)。站內(nèi)消息的第一個(gè)好處是大家都不需要安裝客戶端,你不用知道對(duì)方的MSN或者QQ,就能與他聯(lián)系,稱(chēng)贊他的觀點(diǎn)或者是給他一頓臭罵。第二個(gè)好處是客戶管理方便,利用session來(lái)維護(hù)在線名單,各種腳本都已經(jīng)把session操作封裝得很易用了,不用像其他無(wú)狀態(tài)的即時(shí)通信工具(比如使用UDP通信的工具)一樣,要費(fèi)一些腦細(xì)胞來(lái)解決在線名單的問(wèn)題。缺點(diǎn)嘛,就是實(shí)時(shí)性不好,一般是在用戶跳轉(zhuǎn)或者刷新頁(yè)面才能探測(cè)消息、更新在線名單。

            Session監(jiān)聽(tīng)嘛,沒(méi)什么好解釋的,java提供了很靈活的事件機(jī)制來(lái)監(jiān)聽(tīng)session,可以監(jiān)聽(tīng)session的創(chuàng)建和銷(xiāo)毀,監(jiān)控session所攜帶數(shù)據(jù)的創(chuàng)建、變化和銷(xiāo)毀,可以監(jiān)聽(tīng)session的銳化和鈍化(了解對(duì)象序列化的兄弟應(yīng)該知道這個(gè)),其他的平臺(tái)是個(gè)什么情況我不太清楚,估計(jì)也差不多吧。如果能夠?qū)λ锌蛻舻膕ession進(jìn)行監(jiān)控,就不用再去操作麻煩而危險(xiǎn)的Application了。

            Xmlhttp是MS推的一項(xiàng)技術(shù),功能很復(fù)雜,可以做很多事情,比如客戶端可以在簡(jiǎn)單的HTML中打開(kāi)HTTP連接,主動(dòng)向server請(qǐng)求數(shù)據(jù)并獲得返回?cái)?shù)據(jù),是DOM技術(shù)一個(gè)非常重要的應(yīng)用,利用它來(lái)寫(xiě)無(wú)刷新的動(dòng)態(tài)頁(yè)面簡(jiǎn)直是so?easy,做過(guò)web開(kāi)發(fā)的兄弟應(yīng)該明白它的意義有多么重大。

          一、?session監(jiān)聽(tīng)

            servlet中對(duì)session的監(jiān)聽(tīng)有很多接口,功能很靈活,最常用的是監(jiān)聽(tīng)Session和Attribute。這里要澄清一下概念,servlet中的session監(jiān)聽(tīng)和Attribute監(jiān)聽(tīng)含義有差別,session監(jiān)聽(tīng)指的不是我們一般所理解的放置一個(gè)session或者銷(xiāo)毀一個(gè)session,這是Attribute監(jiān)聽(tīng)的功能,因?yàn)閟ervlet中放置session的語(yǔ)法是session.setAttribute(“session名”,要放入的對(duì)象)。而session監(jiān)聽(tīng),監(jiān)聽(tīng)的是HTTP連接,只要有用戶與server連接,就算連接的是一個(gè)空白的jsp頁(yè)面,也會(huì)觸發(fā)session事件,所以此處的session實(shí)際上指的是connection,用來(lái)統(tǒng)計(jì)當(dāng)前在線用戶數(shù)最合適了。不知道我說(shuō)清楚了沒(méi)有。下面分別講解這兩種監(jiān)聽(tīng)方式。

          1、?session監(jiān)聽(tīng)

            首先編寫(xiě)一個(gè)session監(jiān)聽(tīng)類(lèi),實(shí)作HttpSessionListener接口,它的作用是計(jì)算當(dāng)前有多少個(gè)在線用戶:

          1. /**
          2. *@Author?bromon
          3. *2004-6-12
          4. */
          5. package?org.bromon.test;
          6. import?javax.servlet.*;
          7. import?javax.servlet.http.*;
          8. public?class?SessionCount?implements?HttpSessionListener
          9. {
          10. ????private?static?int?count=0;
          11. ????public?void?sessionCreated(HttpSessionEvent?se)
          12. ????{
          13. ????????count++;
          14. ????????System.out.println(“session創(chuàng)建:”+new?java.util.Date());
          15. ????}
          16. ????public?void?sessionDestroyed(HttpSessionEvent?se)
          17. ????{
          18. ???????count--;
          19. ???????System.out.println(“session銷(xiāo)毀:”+new?java.util.Date());
          20. ????}
          21. ????public?static?int?getCount()
          22. ????{
          23. ???????return(count);
          24. ?????}
          25. }



            怎么樣,是不是一目了然?count被定義為static,是因?yàn)橐WC整個(gè)系統(tǒng)只有這一個(gè)count。如果你實(shí)在不放心,可以把它寫(xiě)成一個(gè)單例類(lèi)。

            然后在web.xml中聲明這個(gè)監(jiān)聽(tīng)器:
          <listener>
          <listener-class>
          org.bromon.test.SessionCount
          </listener-class>
          </listener>

            編寫(xiě)一個(gè)測(cè)試頁(yè)面test.jsp,內(nèi)容是獲得count:
          <%
          int?count=org.bromon.test.SessionCount.getCount();
          out.println(count);
          %>

            需要注意的是,這里根本不涉及任何session的操作。重啟動(dòng)App?server,試著連接test.jsp,可以看到監(jiān)聽(tīng)器已經(jīng)開(kāi)始工作。

          2、?Attribute監(jiān)聽(tīng)
            作為一個(gè)站內(nèi)消息系統(tǒng),肯定要獲得所有登陸者的ID,才有可能互發(fā)消息。這就涉及Attribute監(jiān)聽(tīng)。假設(shè)我們寫(xiě)了個(gè)用戶登陸的模塊,用戶通過(guò)身份驗(yàn)證之后會(huì)產(chǎn)生一個(gè)session,保存它的相關(guān)信息,比如:
          1. //check.jsp
          2. <%
          3. ????String?name=request.getParameter(“name”);
          4. ????Name=new?String(name.getBytes(“ISO8859-1”));
          5. ????session.setAttribute(“user”,name);
          6. %>


            做過(guò)jsp的兄弟應(yīng)該對(duì)這段代碼再熟悉不過(guò)了,下面寫(xiě)個(gè)監(jiān)聽(tīng)器來(lái)監(jiān)聽(tīng)用戶登陸,把所有用戶的ID保存到一個(gè)List當(dāng)中,這個(gè)監(jiān)聽(tīng)器實(shí)作HttpSessionAttributeListener接口:

          1. /**
          2. *@Author?bromon
          3. *2004-6-12
          4. */
          5. package?org.bromon.test;
          6. import?javax.servlet.*;
          7. import?javax.servlet.http.*;
          8. import?java.util.*;
          9. public?class?OnlineList?implements?HttpSessionAttributeListener
          10. {
          11. ????private?static?List?list=new?ArrayList();
          12. ????public?void?attributeAdded(HttpSessionBindingEvent?se)
          13. ????{
          14. ????????if(“user”.equals(se.getName()))
          15. ????????{
          16. ????????????list.add(se.getValue());
          17. ?????????}
          18. ????}
          19. ????public?void?attributeRemoved(HttpSessionBindingEvent?se)
          20. ????{
          21. ?????????if(“user”.equals(se.getName()))
          22. ?????????{
          23. ????????????list.remove(se.getValue());
          24. ?????????}
          25. ????}
          26. ????public?void?attributeReplaced(HttpSessionBindingEvent?se){}
          27. ????public?static?List?getList()
          28. ????{
          29. ?????????return(list);
          30. ?????}
          31. }


          寫(xiě)個(gè)簡(jiǎn)單的jsp來(lái)得到用戶列表:
          <%
          ????java.util.List?list=org.bromon.test.OnlineList.getList();
          ????out.println(“共有”+list.size()+”名用戶已登陸:”);
          ????for(int?I=0;I<lise.size();i++)
          ????{
          ????????out.println(list.get(i));
          ????}
          %>

          也許你說(shuō),這有什么神奇呢,監(jiān)聽(tīng)session而已,不著急,看看xmlhttp。

          二、?XMLHTTP

            XMLHTTP的用處很多,這里只說(shuō)我們需要的,就是無(wú)刷新的與server通信,看這段代碼:

          1. <script?language="javascript">?
          2. xml?=?new?ActiveXObject("Microsoft.XMLHTTP");?
          3. var?post="?";//構(gòu)造要攜帶的數(shù)據(jù)?
          4. xml.open("POST","http://localhost:7001/TestWL/index.jsp",false);//使用POST方法打開(kāi)一個(gè)到服務(wù)器的連接,以異步方式通信?
          5. xml.setrequestheader("content-length",post.length);?
          6. xml.setrequestheader("content-type","application/x-www-form-urlencoded");?
          7. xml.send(post);//發(fā)送數(shù)據(jù)?
          8. var?res?=?xml.responseText;//接收服務(wù)器返回的數(shù)據(jù)?
          9. document.write(res);?
          10. </script>



            豁然開(kāi)朗,這段代碼就是打開(kāi)一個(gè)HTTP連接,以標(biāo)準(zhǔn)的HTTP格式傳遞數(shù)據(jù),如果你喜歡,可以用XML的格式來(lái)傳遞。更改一下xml對(duì)象的構(gòu)造方式就可以兼容Mozilla和Netscape。下面來(lái)寫(xiě)一個(gè)輪詢,每隔一段時(shí)間刷新一次用戶列表,當(dāng)然,是不需要刷新頁(yè)面的:

          1. <html>
          2. <head><title>探測(cè)器</title>
          3. <script?language="javascript">
          4. function?detect()
          5. {
          6. xml?=?new?ActiveXObject("Microsoft.XMLHTTP");?
          7. var?post="?";//構(gòu)造要攜帶的數(shù)據(jù)?
          8. xml.open("POST","http://localhost:7001/TestWL/index.jsp",false);//使用POST方法打開(kāi)一個(gè)到服務(wù)器的連接,以異步方式通信?
          9. xml.setrequestheader("content-length",post.length);?
          10. xml.setrequestheader("content-type","application/x-www-form-urlencoded");?
          11. xml.send(post);//發(fā)送數(shù)據(jù)?
          12. var?res?=?xml.responseText;//接收服務(wù)器返回的數(shù)據(jù)?
          13. list.innerText=res;
          14. setTimeout(“detect()”,5000);//每隔5秒鐘輪詢一次
          15. }?
          16. </script>
          17. <body?onload=”detect()”>
          18. <a?id=”list”></a>
          19. </body>
          20. </html>
          21. 這樣的通信方式數(shù)據(jù)量很小,不用重新傳遞整個(gè)頁(yè)面,5秒鐘輪一次,普通PC也能承受較大的在線數(shù)。構(gòu)造一個(gè)探測(cè)器來(lái)監(jiān)聽(tīng)在線列表和消息,效果是很好的,即使你的客戶坐在電腦前袖手旁觀,鍵鼠都不碰一下,也能保證數(shù)據(jù)即時(shí)傳遞,頁(yè)面也不會(huì)發(fā)生跳轉(zhuǎn)和刷新。

              Session監(jiān)聽(tīng)加上XMLHTTP通信,開(kāi)發(fā)一個(gè)較為完善的站內(nèi)消息系統(tǒng)實(shí)在易如反掌

          評(píng)論

          # re: 使用xmlhttp和Java session監(jiān)聽(tīng)改善站內(nèi)消息系統(tǒng)( 轉(zhuǎn))  回復(fù)  更多評(píng)論   

          2010-08-31 11:23 by 生活快樂(lè)
          好!!!!

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 银川市| 油尖旺区| 土默特左旗| 鄱阳县| 保亭| 邢台县| 喀喇| 中西区| 双柏县| 团风县| 柏乡县| 汕头市| 宁城县| 施秉县| 登封市| 定州市| 绥阳县| 东海县| 九龙县| 搜索| 新野县| 西充县| 托克逊县| 吉林省| 荆州市| 镇安县| 屏边| 黎城县| 富裕县| 盘锦市| 五原县| 齐齐哈尔市| 广宁县| 义马市| 绩溪县| 绥滨县| 大宁县| 富宁县| 屏山县| 南通市| 兰州市|