国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

監(jiān)聽器應(yīng)用【統(tǒng)計網(wǎng)站人數(shù)、自定義session掃描器、踢人小案例】

Awbeci / 2935人閱讀

摘要:現(xiàn)在,我們想要統(tǒng)計的是網(wǎng)站的在線人數(shù)。隔一段時間去做某事,這肯定是定時器的任務(wù)呀。定時器應(yīng)該在服務(wù)器一啟動的時候,就應(yīng)該被創(chuàng)建了。定時器掃描容器的時候,可能是獲取不到所有的的。

從第一篇已經(jīng)講解過了監(jiān)聽器的基本概念,以及Servlet各種的監(jiān)聽器。這篇博文主要講解的是監(jiān)聽器的應(yīng)用。

統(tǒng)計網(wǎng)站在線人數(shù) 分析

我們在網(wǎng)站中一般使用Session來標(biāo)識某用戶是否登陸了,如果登陸了,就在Session域中保存相對應(yīng)的屬性。如果沒有登陸,那么Session的屬性就應(yīng)該為空。

現(xiàn)在,我們想要統(tǒng)計的是網(wǎng)站的在線人數(shù)。我們應(yīng)該這樣做:我們監(jiān)聽是否有新的Session創(chuàng)建了,如果新創(chuàng)建了Sesssion,那么在線人數(shù)就應(yīng)該+1。這個在線人數(shù)是整個站點(diǎn)的,所以應(yīng)該有Context對象保存。

大致思路:

監(jiān)聽Session是否被創(chuàng)建了

如果Session被創(chuàng)建了,那么在Context的域?qū)ο蟮闹稻蛻?yīng)該+1

如果Session從內(nèi)存中移除了,那么在Context的域?qū)ο蟮闹稻蛻?yīng)該-1.

代碼

監(jiān)聽器代碼:

    public class CountOnline implements HttpSessionListener {
    
        public void sessionCreated(HttpSessionEvent se) {
    
            //獲取得到Context對象,使用Context域?qū)ο蟊4嬗脩粼诰€的個數(shù)
            ServletContext context = se.getSession().getServletContext();
            
            //直接判斷Context對象是否存在這個域,如果存在就人數(shù)+1,如果不存在,那么就將屬性設(shè)置到Context域中
            Integer num = (Integer) context.getAttribute("num");
            
            if (num == null) {
                context.setAttribute("num", 1);
            } else {
                num++;
                context.setAttribute("num", num);
            }
        }
        public void sessionDestroyed(HttpSessionEvent se) {
    
            ServletContext context = se.getSession().getServletContext();
            Integer num = (Integer) se.getSession().getAttribute("num");
    
            if (num == null) {
                context.setAttribute("num", 1);
            } else {
                num--;
                context.setAttribute("num", num);
            }
        }
    }

顯示頁面代碼:

在線人數(shù):${num}
測試

我們每使用一個瀏覽器訪問服務(wù)器,都會新創(chuàng)建一個Session。那么網(wǎng)站的在線人數(shù)就會+1。

使用同一個頁面刷新,還是使用的是那個Sesssion,所以網(wǎng)站的在線人數(shù)是不會變的。

自定義Session掃描器

我們都知道Session是保存在內(nèi)存中的,如果Session過多,服務(wù)器的壓力就會非常大。

但是呢,Session的默認(rèn)失效時間是30分鐘(30分鐘沒人用才會失效),這造成Seesion可能會過多(沒人用也存在內(nèi)存中,這不是明顯浪費(fèi)嗎?)

當(dāng)然啦,我們可以在web.xml文件中配置Session的生命周期。但是呢,這是由服務(wù)器來做的,我嫌它的時間不夠準(zhǔn)確。(有時候我配置了3分鐘,它用4分鐘才幫我移除掉Session)

所以,我決定自己用程序手工移除那些長時間沒人用的Session。

分析

要想移除長時間沒人用的Session,肯定要先拿到全部的Session啦。所以我們使用一個容器來裝載站點(diǎn)所有的Session。。

只要Sesssion一創(chuàng)建了,就把Session添加到容器里邊。毫無疑問的,我們需要監(jiān)聽Session了。

接著,我們要做的就是隔一段時間就去掃描一下全部Session,如果有Session長時間沒使用了,我們就把它從內(nèi)存中移除。隔一段時間去做某事,這肯定是定時器的任務(wù)呀。

定時器應(yīng)該在服務(wù)器一啟動的時候,就應(yīng)該被創(chuàng)建了。因此還需要監(jiān)聽Context

最后,我們還要考慮到并發(fā)的問題,如果有人同時訪問站點(diǎn),那么監(jiān)聽Session創(chuàng)建的方法就會被并發(fā)訪問了定時器掃描容器的時候,可能是獲取不到所有的Session的

這需要我們做同步

于是乎,我們已經(jīng)有大致的思路了

監(jiān)聽Session和Context的創(chuàng)建

使用一個容器來裝載Session

定時去掃描Session,如果它長時間沒有使用到了,就把該Session從內(nèi)存中移除。

并發(fā)訪問的問題

代碼

監(jiān)聽器代碼:

    public class Listener1 implements ServletContextListener,
            HttpSessionListener {
    
    
    
        //服務(wù)器一啟動,就應(yīng)該創(chuàng)建容器。我們使用的是LinkList(涉及到增刪)。容器也應(yīng)該是線程安全的。
        List list = Collections.synchronizedList(new LinkedList());
    
        //定義一把鎖(Session添加到容器和掃描容器這兩個操作應(yīng)該同步起來)
        private Object lock = 1;
    
        public void contextInitialized(ServletContextEvent sce) {
    
    
            Timer timer = new Timer();
            //執(zhí)行我想要的任務(wù),0秒延時,每10秒執(zhí)行一次
            timer.schedule(new MyTask(list, lock), 0, 10 * 1000);
    
        }
        public void sessionCreated(HttpSessionEvent se) {
    
            //只要Session一創(chuàng)建了,就應(yīng)該添加到容器中
            synchronized (lock) {
                list.add(se.getSession());
            }
            System.out.println("Session被創(chuàng)建啦");
    
        }
    
        public void sessionDestroyed(HttpSessionEvent se) {
            System.out.println("Session被銷毀啦。");
        }
        public void contextDestroyed(ServletContextEvent sce) {
    
        }
    }

任務(wù)代碼:



    /*
    * 在任務(wù)中應(yīng)該掃描容器,容器在監(jiān)聽器上,只能傳遞進(jìn)來了。
    *
    * 要想得到在監(jiān)聽器上的鎖,也只能是傳遞進(jìn)來
    *
    * */
    class MyTask extends TimerTask {
    
        private List sessions;
        private Object lock;
    
        public MyTask(List sessions, Object lock) {
            this.sessions = sessions;
            this.lock = lock;
        }
    
        @Override
        public void run() {
    
            synchronized (lock) {
                //遍歷容器
                for (HttpSession session : sessions) {
    
                    //只要15秒沒人使用,我就移除它啦
                    if (System.currentTimeMillis() - session.getLastAccessedTime() > (1000 * 15)) {
                        session.invalidate();
                        sessions.remove(session);
                    }
    
                }
            }
        }
    }

測試:

15秒如果Session沒有活躍,那么就被刪除!

使用集合來裝載我們所有的Session

使用定時器來掃描session的聲明周期【由于定時器沒有session,我們傳進(jìn)去就好了】

關(guān)于并發(fā)訪問的問題,我們在掃描和檢測session添加的時候,同步起來就好了【當(dāng)然,定時器的鎖也是要外面?zhèn)鬟f進(jìn)來的】

踢人小案列

列出所有的在線用戶,后臺管理者擁有踢人的權(quán)利,點(diǎn)擊踢人的超鏈接,該用戶就被注銷了。

分析

首先,怎么能列出所有的在線用戶呢??一般我們在線用戶都是用Session來標(biāo)記的,所有的在線用戶就應(yīng)該用一個容器來裝載所有的Session。。

我們監(jiān)聽Session的是否有屬性添加(監(jiān)聽Session的屬性有添加、修改、刪除三個方法。如果監(jiān)聽到Session添加了,那么這個肯定是個在線用戶!)。

裝載Session的容器應(yīng)該是在Context里邊的【屬于全站點(diǎn)】,并且容器應(yīng)該使用Map集合【待會還要通過用戶的名字來把用戶踢了】

思路:

寫監(jiān)聽器,監(jiān)聽是否有屬性添加在Session里邊了

寫簡單的登陸頁面。

列出所有的在線用戶

實現(xiàn)踢人功能(也就是摧毀Session)

代碼

監(jiān)聽器


public class KickPerson implements HttpSessionAttributeListener {

    // Public constructor is required by servlet spec
    public KickPerson() {
    }

    public void attributeAdded(HttpSessionBindingEvent sbe) {

        //得到context對象,看看context對象是否有容器裝載Session
        ServletContext context = sbe.getSession().getServletContext();

        //如果沒有,就創(chuàng)建一個唄
        Map map = (Map) context.getAttribute("map");
        if (map == null) {
            map = new HashMap();
            context.setAttribute("map", map);
        }

        //---------------------------------------------------------------------------------------
        
        //得到Session屬性的值
        Object o = sbe.getValue();

        //判斷屬性的內(nèi)容是否是User對象
        if (o instanceof User) {
            User user = (User) o;
            map.put(user.getUsername(), sbe.getSession());
        }
    }

    public void attributeRemoved(HttpSessionBindingEvent sbe) {
      /* This method is called when an attribute
         is removed from a session.
      */
    }

    public void attributeReplaced(HttpSessionBindingEvent sbe) {
      /* This method is invoked when an attibute
         is replaced in a session.
      */
    }
}

登陸頁面

用戶名:

處理登陸Servlet

        //得到傳遞過來的數(shù)據(jù)
        String username = request.getParameter("username");

        User user = new User();
        user.setUsername(username);

        //標(biāo)記該用戶登陸了!
        request.getSession().setAttribute("user", user);

        //提供界面,告訴用戶登陸是否成功
        request.setAttribute("message", "恭喜你,登陸成功了!");
        request.getRequestDispatcher("/message.jsp").forward(request, response);

列出在線用戶




    ${me.key} 踢了他吧

    

處理踢人的Servlet


        String username = request.getParameter("username");

        //得到裝載所有的Session的容器
        Map map = (Map) this.getServletContext().getAttribute("map");

        //通過名字得到Session
        HttpSession httpSession = (HttpSession) map.get(username);
        httpSession.invalidate();
        map.remove(username);

        //摧毀完Session后,返回列出在線用戶頁面
        request.getRequestDispatcher("/listUser.jsp").forward(request, response);
測試

使用多個瀏覽器登陸來模擬在線用戶(同一個瀏覽器使用的都是同一個Session)

監(jiān)聽Seesion的創(chuàng)建和監(jiān)聽Session屬性的變化有啥區(qū)別???

Session的創(chuàng)建只代表著瀏覽器給服務(wù)器發(fā)送了請求。會話建立

Session屬性的變化就不一樣了,登記的是具體用戶是否做了某事(登陸、購買了某商品)

如果文章有錯的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章的同學(xué),可以關(guān)注微信公眾號:Java3y

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/70978.html

相關(guān)文章

  • Java3y文章目錄導(dǎo)航

    摘要:前言由于寫的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導(dǎo)航。 前言 由于寫的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導(dǎo)航。 由于更新比較頻繁,因此隔一段時間才會更新目錄導(dǎo)航哦~想要獲取最新原創(chuàng)的技術(shù)文章歡迎關(guān)注我的公眾號:Java3y Java3y文章目錄導(dǎo)航 Java基礎(chǔ) 泛型就這么簡單 注解就這么簡單 Druid數(shù)據(jù)庫連接池...

    KevinYan 評論0 收藏0
  • 過濾器監(jiān)聽器面試題都在這里

    摘要:中的異步處理指的是什么中的異步處理指的是什么答在中引入了一項新的技術(shù)可以讓異步處理請求。開啟異步處理代碼開啟異步支持啟動異步處理的上下文在此處添加異步處理的代碼如果文章有錯的地方歡迎指正,大家互相交流。 以下我是歸納的過濾器監(jiān)聽器知識點(diǎn)圖: showImg(https://segmentfault.com/img/remote/1460000013263166?w=3974&h=187...

    crelaber 評論0 收藏0
  • TOP100summit:【分享實錄-封宇】58到家多端消息整合之路

    摘要:封宇到家架構(gòu)師。主要負(fù)責(zé)到家消息系統(tǒng)以及門戶等公司戰(zhàn)略級產(chǎn)品研發(fā)。消息服務(wù)器收到拉取離線消息請求,表明端已經(jīng)收到之前的數(shù)據(jù)。統(tǒng)一消息推送通道,整合個推米推微信短信等消息推送方式,盡最大可能確保消息送達(dá)用戶。 本篇文章內(nèi)容來自2016年TOP100summit 58到家架構(gòu)師封宇的案例分享。編輯:Cynthia2017年11月9-12日北京國家會議中心第六屆TOP100summit,留言...

    googollee 評論0 收藏0
  • 監(jiān)聽器實栗 在線人數(shù)統(tǒng)計

    摘要:實現(xiàn)思路常見的流程是標(biāo)準(zhǔn)的即登錄表單用戶提交數(shù)據(jù)到登錄檢查若登錄檢查通過以后觸發(fā)事件保存進(jìn)入在線人員列表中頁面跳轉(zhuǎn)到在線用戶列表若用戶注銷從在線列表中刪除代碼如下使用集合即集合去重原因內(nèi)部存儲為的鍵值對為由于哈希表的特征即可去重項目結(jié)構(gòu) 實現(xiàn)思路 常見的流程是,標(biāo)準(zhǔn)的mvc 即 登錄表單,用戶提交數(shù)據(jù)到登錄檢查,若登錄檢查通過以后,觸發(fā)session事件,保存進(jìn)入在線人員列表中,頁面跳...

    CloudwiseAPM 評論0 收藏0
  • 消息推送異常重發(fā)需要注意的點(diǎn)(上篇)

    摘要:無證連接進(jìn)行異常記錄并關(guān)閉連接。離線消息檢測到上線立即推送這是消息推送需要實現(xiàn)的基本功能之一了,詳見代碼。主要功能協(xié)助進(jìn)行初始化,心跳包檢測,斷線自動重連消息推送的第二種方式在下篇中再編寫 消息重發(fā)中需要注意的問題 由于最近工作中接觸了比較多關(guān)閉消息推送以及異常重發(fā)機(jī)制的問題,終于得空總結(jié)一下經(jīng)驗 目前接觸的消息推送分為兩種 主動推送:一般為websocket建立長連接實現(xiàn),此處網(wǎng)上...

    terro 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<