必威体育Betway必威体育官网
当前位置:首页 > IT技术

统计用户在线人数

时间:2019-10-05 06:15:23来源:IT技术作者:seo实验室小编阅读:66次「手机版」
 

人数统计

统计用户在线人数

  • 统计用户在线人数
    • 错误的统计办法
    • 正确的统计方法
    • 最完美的代码
      • Servlet域中添加Map

统计用户在线人数

在统计用户在人数的时候,我们用到了监听器,监听器大致分为以下三种:

  1. ServletRequestListener
用于监听请求的监听接口
  1. HttpSessionListener
用于监听会话的监听接口
  1. ServletcontextListener
用于监听应用的回话接口

错误的统计办法

监听Request域

这种统计办法是错误的认为每次刷新页面后进行进行一次的count++运算

import javax.servlet.*;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSessionBindingEvent;

@WebListener()
public class MyRequestListener implements ServletRequestListener{
    private ServletContext sc;
    private integer count;
    @Override
    //请求被初始化 Request
    public void requestInitialized(ServletRequestEvent sre) {
        //获取全局域
        sc = sre.getServletContext();
        //将count从全局域中获取出来
        count = (Integer) sc.getAttribute("count");
        System.out.println(count);
        count++;
        System.out.println(count);
        sc.setAttribute("count",count);
    }
}
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSessionBindingEvent;

@WebListener()
public class MyServletContextListener implements ServletContextListener{
    private ServletContext sc;
    @Override
    //APPlication被初始化的时候创建
    public void contextInitialized(ServletContextEvent sce) {
        Integer count = 0;
        //获取全局域
        sc = sce.getServletContext();
        //将count放入到全局域中
        sc.setAttribute("count",count);
    }
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <center><h1>You are the ${applicationScope.count} customer to visit. </h1></center>
  </body>
</html>

这种错误地做法导致的是每刷新一次页面 就会导致count进行累加操作,最终产生错误的在线人数,所以此时想到不应该监听Request域,而应该监听Session域。

监听Session域

在第二次监听Session域之后,发现每次刷新页面后不改变count但是在启动不同的浏览器count++会实现,但是,这样做并不是我们要统计的在线人数,所以此种做法错误。由于代码只是将原来写在Request监听器中的代码转移到Session监听器中,所以其他没变的代码将不重复。

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSessionBindingEvent;

@WebListener()
public class MySessionListener implements HttpSessionListener{

    private ServletContext sc;
    private Integer count;

    @Override
    //当对话产生时激活此方法
    public void sessionCreated(HttpSessionEvent se) {
        sc = se.getSession().getServletContext();
        count = (Integer) sc.getAttribute("count");
        count++;
        sc.setAttribute("count",count);
    }
}

这时我们发现对于在线人数的统计,不是网页访问的次数,也不是浏览器打开的个数,对需求的理解的错误理解。所以正确的做法是统计其IP的数量,这样的话,不管你在一台电脑上开启多少客户端,都会只有一个。

正确的统计方法

统计其IP的数量,将IP的数量作为当前的在线人数,那么如何统计IP的数量呢?这样将会导出以下问题:

  1. 如何获取用户的IP?
  2. IP将如何存储?
  3. 如何判断IP之前已经存在?

现在来解决这些问题:

  1. 只能从请求中获取
  2. 通过2、3问题,我们想到了集合(List),因为集合不仅可以存储任何字符串,还可以通过遍历来判断之前是否有重复的IP出现。

到了这里又冒出来一个问题集合(List)放到哪个域里呢?

ServletContext域
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSessionBindingEvent;
import java.util.ArrayList;
import java.util.List;

@WebListener()
public class MyServletContextListener implements ServletContextListener{
    private ServletContext sc;

    @Override
    //Application被初始化的时候创建
    public void contextInitialized(ServletContextEvent sce) {
        //创建一个链表来存储IP
        List<String> ips = new ArrayList<>();
        sc = sce.getServletContext();
        //将创建好的链表对象,放到Application域中
        sc.setAttribute("ips",ips);
    }
}

由于IP只能在Request域中获取,所以遍历判断在Request域中进行。

import javax.servlet.*;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.*;
import java.util.List;

@WebListener()
public class MyRequestListener implements ServletRequestListener{

    private HttpServletRequest sr;
    private String clientIp;
    private ServletContext sc;
    private List<String> ips;
    private HttpSession session;

    @Override
    //请求被初始化 Request
    public void requestInitialized(ServletRequestEvent sre) {
        //从请求域中获取IP
        sr = (HttpServletRequest) sre.getServletRequest();
        clientIp = sr.getRemoteAddr();
        session = sr.getSession();
        session.setattribute("clientIp",clientIp);

        //测试
        // System.out.println("clientIp = "+ clientIp);
        //获取Application域中的List
        sc = sre.getServletContext();
        ips = (List<String>) sc.getAttribute("ips");
        //遍历ips
        for (String ip :
                ips) {
            if (clientIp.equals(ip))
                return;
        }
        ips.add(clientIp);
        sc.setAttribute("ips",ips);
    }
}

因为要统计在线人数,所以要设置退出按钮,点击退出按钮之后,因为要从List域中移除,所以使用Session域监听器来判断session回话的关闭

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.*;
import java.util.List;

@WebListener()
public class MySessionListener implements HttpSessionListener{

    private ServletContext sc;
    private List<String> ips;
    private HttpSession session;
    private Object clientIp;

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        sc = se.getSession().getServletContext();
        ips = (List<String>) sc.getAttribute("ips");
        session = se.getSession();
        clientIp = session.getattribute("clientIp");
        //删除ip,如何获取IP,但是不可以从session获取到IP
        //因为Session获取不到Request
        //一个Session包含多个Request
        //一个Request只对应一个Session 所以获取不到,这时只能先从Request域中获取到的ips,放置到Session域
        //然后从Session 域中读取
        ips.remove(clientIp);
        // session一失效就马上将此IP从链表中移除是错误的
        //应该看此IP是否有另外的回话存在,如果有的话不能删除
    }
}

此处代码是页面点击关闭后,激活的退出方法

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletresponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet(name = "LogoutServlet",urlPatterns = "/logoutServlet")
public class LogoutServlet extends HttpServlet {

    private HttpSession session;

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //从域中获取一个session,设置为false 如果域中存在一个session,则直接获取,如果不存在,则返回一个空的session
        session = request.getSession(false);
        if (session != null){
            //使session失效
            session.invalidate();
            //失效后,需要进行的操作,List链表中需要减去,用到了Session域监听器
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);
    }
}

在jsp页面进行读取的时候,因为ips是以List链表的形式存在的,所以要想判断当前在线人数,所以必须要判断链表的长度,所以是applicationScope.ips.size()

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <center><h1>You are the ${applicationScope.ips.size()} customer to visit. </h1><br>
    <h3><a href="${pageContext.request.contextpath}/logoutServlet">
      安全退出
    </a></h3>
  </center>
  </body>
</html>

好了

相关阅读

subject 获取登录用户信息

shiro 管理登录,获取登录信息的方式常用的是: Subject sub = SecurityUtils.getSubject(); Object obj = sub.getPrincipal(); 这

Oracle创建用户并授权dba权限

很多时候我们用拥有DBA权限的用户 从oracle数据库导出数据,那么再导入新的数据库时就还得需要DBA权限的用户,下面是如何创建一个新

Spotify的发展史:拥有7000多万付费用户,他们是怎么做到

编者按:Spotify是现在最受欢迎的流媒体音乐服务提供商之一,截止2018年第一季度,拥有7000多万付费用户。与此同时,苹果音乐的用户才500

你真的了解用户吗?怎么样去进行准确的用户画像分析?

举个很简单的例子,学校旁边有家宾馆,每天晚上都要很多大学生入住,开宾馆的人就问“怎么晚了,怎么住宾馆呀?”,学生说要温习功课。然后开

最新浏览器市场份额统计-12月份

来自 Net Application的最新数据显示, Mozilla的火狐浏览器市场份额继续超过20%,与11月份的份额相比又有所上涨,已达21.34%,而微软的I

分享到:

栏目导航

推荐阅读

热门阅读