亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

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

Awbeci / 3068人閱讀

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

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

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

我們?cè)诰W(wǎng)站中一般使用Session來(lái)標(biāo)識(shí)某用戶是否登陸了,如果登陸了,就在Session域中保存相對(duì)應(yīng)的屬性。如果沒(méi)有登陸,那么Session的屬性就應(yīng)該為空。

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

大致思路:

監(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對(duì)象,使用Context域?qū)ο蟊4嬗脩粼诰€的個(gè)數(shù)
            ServletContext context = se.getSession().getServletContext();
            
            //直接判斷Context對(duì)象是否存在這個(gè)域,如果存在就人數(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);
            }
        }
    }

顯示頁(yè)面代碼:

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

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

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

自定義Session掃描器

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

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

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

所以,我決定自己用程序手工移除那些長(zhǎng)時(shí)間沒(méi)人用的Session。

分析

要想移除長(zhǎng)時(shí)間沒(méi)人用的Session,肯定要先拿到全部的Session啦。所以我們使用一個(gè)容器來(lái)裝載站點(diǎn)所有的Session。。

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

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

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

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

這需要我們做同步

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

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

使用一個(gè)容器來(lái)裝載Session

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

并發(fā)訪問(wèn)的問(wèn)題

代碼

監(jiān)聽器代碼:

    public class Listener1 implements ServletContextListener,
            HttpSessionListener {
    
    
    
        //服務(wù)器一啟動(dòng),就應(yīng)該創(chuàng)建容器。我們使用的是LinkList(涉及到增刪)。容器也應(yīng)該是線程安全的。
        List list = Collections.synchronizedList(new LinkedList());
    
        //定義一把鎖(Session添加到容器和掃描容器這兩個(gè)操作應(yīng)該同步起來(lái))
        private Object lock = 1;
    
        public void contextInitialized(ServletContextEvent sce) {
    
    
            Timer timer = new Timer();
            //執(zhí)行我想要的任務(wù),0秒延時(shí),每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)來(lái)了。
    *
    * 要想得到在監(jiān)聽器上的鎖,也只能是傳遞進(jìn)來(lái)
    *
    * */
    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秒沒(méi)人使用,我就移除它啦
                    if (System.currentTimeMillis() - session.getLastAccessedTime() > (1000 * 15)) {
                        session.invalidate();
                        sessions.remove(session);
                    }
    
                }
            }
        }
    }

測(cè)試:

15秒如果Session沒(méi)有活躍,那么就被刪除!

使用集合來(lái)裝載我們所有的Session

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

關(guān)于并發(fā)訪問(wèn)的問(wèn)題,我們?cè)趻呙韬蜋z測(cè)session添加的時(shí)候,同步起來(lái)就好了【當(dāng)然,定時(shí)器的鎖也是要外面?zhèn)鬟f進(jìn)來(lái)的】

踢人小案列

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

分析

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

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

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

思路:

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

寫簡(jiǎn)單的登陸頁(yè)面。

列出所有的在線用戶

實(shí)現(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對(duì)象,看看context對(duì)象是否有容器裝載Session
        ServletContext context = sbe.getSession().getServletContext();

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

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

        //判斷屬性的內(nèi)容是否是User對(duì)象
        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.
      */
    }
}

登陸頁(yè)面

用戶名:

處理登陸Servlet

        //得到傳遞過(guò)來(lái)的數(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");

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

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

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

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

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

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

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

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/70978.html

相關(guān)文章

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

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

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

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

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

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

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

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

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

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

    terro 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<