当前位置: 首页 > news >正文

JSP+Servlet + Tomcat实现用户登录(五)使用listener实现在线(游客)人数统计【JavaWeb、无数据库】

1.创建一个监听类,添加注解

添加@WebListener

用于声明类为监听器,至少一个下方接口

  • ServletContextListener
  • ServletContextAttributeListener
  • ServletRequestListener
  • ServletRequestAttributeListener
  • HttpSessionListener
  • HttpSessionAttributeListener

下面是@WebListener的属性列表。

NameTypeRequiredDescription
valueStringOptionalDescription of the listener.

实现HttpSessionListener接口

HttpSessionListener:用于监听HttpSession域中对象的创建销毁


为什么选择监听Session就可以实现监听在线人数呢?

我们知道在servlet中有以下三个对象可以监听

  • request——ServletRequestListener
  • session——HttpSessionListener
  • servletContext——ServletContextListener

request会对所有请求进行监听,但是无法区分用户,因此无法做到对在线人数的监听

servlet 仅仅只会服务器开启和关闭进行监听,无法做到对用户的监听

因此就只剩下session

在服务器第一次接受一个用户请求就会为分配一个sessionId,在有效期结束或者用户主动关闭一段时间,session就会被销毁(session默认有效时间30分钟)

实现ServletContextListener接口

我们需要在servlet创建时,将在线人数的变量设置进入servlet的上下文中

2.实现接口方法

ctrl+o对接口中的方法进行实现

这里可以不实现contextDestroyed方法

请添加图片描述

package com.example.Login;

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

@WebListener
public class OnlineCount implements HttpSessionListener, ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {

    }

    @Override
    public void sessionCreated(HttpSessionEvent se) {

    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {

    }
}

3.处理servlet创建逻辑

我们需要在servlet服务器开启后,对变量进行赋值初始化

  • 获取servlet上下文
  • 定义表示变量的名字——不可更改
  • 设置初始值(0)
public final static String cntName = "onlineCnt";
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        context = sce.getServletContext();
        context.setAttribute(cntName,0);
    }

4.处理创建session逻辑

首先获取此时servlet上下文对象

获取session数目

判断是否存在

  • 存在——自增
  • 不存在——赋值为1

并将值设置进入servlet上下文中

@Override
    public void sessionCreated(HttpSessionEvent se) {
//        获取上下文对象
        ServletContext context = se.getServletContext();
//        获取sessionId
        String sessionId = se.getSession().getId();
//        获取session数目
        Integer count = (Integer) context.getAttribute(sessionId);
	context.setAttribute(cntName , ++count);
    }

5.处理销毁session逻辑

与创建session逻辑基本一致,只需对count减少即可

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
//        获取上下文对象
        ServletContext context = se.getServletContext();
//        获取session数目
        Integer count = (Integer) context.getAttribute(cntName);
        context.setAttribute(cntName , --count);
      
    }

6.优化代码,封装逻辑

我们发现创建和销毁session的步骤基本一致

  • 获取session数目

所以,可对这两者进行逻辑封装

公有变量 + 方法

公有变量

    private ServletContext context;
    private Integer count;

获取方法

    //    获取session数目
    private void getSessionCount(){
        count = (Integer) context.getAttribute(cntName);
    }

7.显示人数

index.jsp中显示在线人数

<p>
        <span>在线人数:</span>
        <span>${onlineCnt}</span>
    </p>

这里的onlineCnt与类中的cntName相对应

阶段成果

请添加图片描述

问题解决

为什么会开始就会出现两次呢?

我是通过内置tomcat运行的,默认的配置就是idea会代替我们打开浏览器

在idea打开页面时,也会与页面建立起一个session

解决办法

请添加图片描述

勾选掉After launch

然后,手动打开网址即可

请添加图片描述


OK,完整的登录功能就已经完成了

但是,其实这样对在线人数的监听是不精准的,因为我们打开不同的页面登录不同的账号也会算作一个不同的人,准确来说监听的是游客人数

若需要精细的对真实的用户进行监听登录,则可能需要创建多个用户进行实现

阶段代码

  • OnlineCount
package com.example.Login;

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

@WebListener
public class OnlineCount implements HttpSessionListener, ServletContextListener {
    public final static String cntName = "onlineCnt";

    private ServletContext context;
    private Integer count;

    //    获取session数目
    private void getSessionCount(){
        count = (Integer) context.getAttribute(cntName);
    }
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        context = sce.getServletContext();
        context.setAttribute(cntName,0);
    }

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        this.getSessionCount();
        context.setAttribute(cntName , ++count);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        this.getSessionCount();

        context.setAttribute(cntName , --count);
    }
}

  • index.jsp
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <title>登录成功</title>
</head>
<body>

<h1>
    Welcome,
    <span style="color: green">
        ${sessionScope.userName}
    </span>
    <p>
        <span>在线人数:</span>
        <span>${onlineCnt}</span>
    </p>
</h1>

<form action="logout">
    <input type="submit" value="退出登录" />
</form>

</body>
</html>

相关文章:

  • 【SpringBoot】抽取公共页面方法
  • 应急响应(个人总结,非专业
  • memcpy内存比较函数;memset内存设置函数
  • 【0基础学习mysql】之DQL-聚合函数、分组查询及排序查询
  • 【Redis】回顾下Redis基础知识点,还记得哪些?
  • redis五种数据类型内部构造
  • 基于Vue+Element UI+SSM+SpringCloud的员工管理系统
  • LeetCode刷题---二分查找巩固
  • 简单概述理解vue的MVVM模型
  • 24、Java——银行存款取款系统(对象+集合)
  • Python 集合
  • 【DS】5.二叉树大总结!
  • 攻防世界 web2
  • 机器人运动学标定:基于公垂线模型的指数积标定——减少标定参数,避免过度约束
  • 机器学习模型的集成方法总结:Bagging, Boosting, Stacking, Voting, Blending
  • Druid 在有赞的实践
  • ES学习笔记(12)--Symbol
  • Java教程_软件开发基础
  • Java深入 - 深入理解Java集合
  • overflow: hidden IE7无效
  • PermissionScope Swift4 兼容问题
  • scrapy学习之路4(itemloder的使用)
  • Solarized Scheme
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 文本多行溢出显示...之最后一行不到行尾的解决
  • 译米田引理
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • k8s使用glusterfs实现动态持久化存储
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • ​Spring Boot 分片上传文件
  • (NO.00004)iOS实现打砖块游戏(九):游戏中小球与反弹棒的碰撞
  • (补)B+树一些思想
  • (附源码)ssm失物招领系统 毕业设计 182317
  • (离散数学)逻辑连接词
  • (求助)用傲游上csdn博客时标签栏和网址栏一直显示袁萌 的头像
  • (四)c52学习之旅-流水LED灯
  • (五)MySQL的备份及恢复
  • (原创) cocos2dx使用Curl连接网络(客户端)
  • (转)Mysql的优化设置
  • (转)关于pipe()的详细解析
  • ****** 二 ******、软设笔记【数据结构】-KMP算法、树、二叉树
  • ***测试-HTTP方法
  • .360、.halo勒索病毒的最新威胁:如何恢复您的数据?
  • .gitignore
  • .NET Core日志内容详解,详解不同日志级别的区别和有关日志记录的实用工具和第三方库详解与示例
  • .net 程序 换成 java,NET程序员如何转行为J2EE之java基础上(9)
  • .NET 的程序集加载上下文
  • .NET中使用Redis (二)
  • .pyc文件是什么?
  • @KafkaListener注解详解(一)| 常用参数详解
  • [ element-ui:table ] 设置table中某些行数据禁止被选中,通过selectable 定义方法解决