本节我们利用 Servlet 监听器接口,完成一个统计网站在线人数的案例。当一个用户登录后,显示欢迎信息,同时显示出当前在线人数和用户名单。当用户退出登录或 Session 过期时,从在线用户名单中删除该用户,同时将在线人数减 1。

本案例可以通过如下 2 种方案实现:

  1. 使用 HttpSessionListener 和 HttpSessionAttributeListener 实现;
  2. 使用 HttpSessionBindingListener 实现。

使用 HttpSessionListener 和 HttpSessionAttributeListener 实现

1. 创建一个名称为 listennerDemo 的工程,并分别创建 net.biancheng.www.listener 和 net.biancheng.www.servlet 两个包。

2. 在 WebContent 中,创建 login.html,代码如下。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="/listennerDemo/LoginServlet" method="GET">
<table border="1" width="50%">
<tr>
<td colspan="2" align="center">编程帮wwww.biancheng.net</td>
</tr>
<tr>
<td>账号</td>
<td><input type="text" name="username" /></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="提交" />
</td>
</tr>
</table>
</form>
</body>
</html>

3. 在 net.biancheng.www.servlet  包中,创建名称为 LoginServlet  的 Servlet 类,代码如下。

package net.biancheng.www.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 登录校验
* @author 编程帮 www.biancheng.net
*/
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@SuppressWarnings("unchecked")
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置页面输出格式
response.setContentType("text/html;charset=UTF-8");
//修改request缓冲区的字符集为UTF-8
request.setCharacterEncoding("utf-8");
PrintWriter writer = response.getWriter();
// 获取表单数据
String username = request.getParameter("username");
// 查看当前会话是否已有账号登录
String logined = (String) request.getSession().getAttribute("username");
// 当前会话已有账号登录
if ("".equals(username) || username == null) {
System.out.println("非法操作,您没有输入用户名");
response.sendRedirect("/listennerDemo/login.html");
} else {
if (!"".equals(logined) && logined != null) {
System.out.println("您已经登录,重复登录无效,请先退出当前账号重新登录!");
writer.write("<h1>编程帮 www.biancheng.net</h1>"
+ "<h3>您好,您已经登录了账户:" + logined + "</h3>"
+ "如要登录其他账号,请先退出当前账号重新登录!");
// 登陆页面为填写内容
} else {// 将当前账号加入会话中
request.getSession().setAttribute("username", username);
writer.write("<h1>编程帮 www.biancheng.net</h1>"
+ "<h3>" + username + ": 欢迎您的到来</h3>");
}
// 从上下文中获取已经登录账号的集合
List<String> onLineUserList = (List<String>) request.getServletContext().getAttribute("onLineUserList");
if (onLineUserList != null) {
// 向页面输出结果
writer.write(
"<h3> 当前在线人数为:" + onLineUserList.size() + "</h3>" + "<table border=\"1\" width=\"50%\">");
for (int i = 0; i < onLineUserList.size(); i++) {
writer.write("<tr>\r\n" + "<td align=\"center\">" + onLineUserList.get(i) + " </td>\r\n" + "</tr>");
}
}
writer.write("</table><br/>" + "<a href=\"/listennerDemo/LogoutServlet\">退出登录</a>");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

4. 在 net.biancheng.www. listener 包中,创建名称为 MySessionListener 的监听器类,代码如下。

package net.biancheng.www.listener;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* 监听器
* @author 编程帮 www.bianchengbang.net
*
*/
@WebListener
public class MySessionListener implements HttpSessionListener,HttpSessionAttributeListener{
@SuppressWarnings("unchecked")
@Override
public void attributeAdded(HttpSessionBindingEvent se) {
System.out.println("HttpSessionAttributeListener****attributeAdded()方法开始工作*******************");
//从上下文中获取已经登录账号的集合
List<String> onLineUserList = (List<String>) se.getSession().getServletContext().getAttribute("onLineUserList");
//在上下文中没有登陆用户
if(onLineUserList==null || onLineUserList.size()==0) {
onLineUserList = new ArrayList<String>();
} String username =(String) se.getSession().getAttribute("username");
//向已登录集合中添加当前账号
onLineUserList.add(username);
System.out.println("用户:"+username+" 成功加入在线用户列表");
for(int i= 0;i<onLineUserList.size();i++) {
System.out.println(onLineUserList.get(i));
}
se.getSession().getServletContext().setAttribute("onLineUserList", onLineUserList);
}
public MySessionListener() {
}
@SuppressWarnings("unchecked")
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession session = se.getSession();
ServletContext application = session.getServletContext();
List<String> onlineUserList = (List<String>) application.getAttribute("onLineUserList");
// 取得登录的用户名
String username = (String) session.getAttribute("username");
if(!"".equals(username) && username!=null && onlineUserList!=null && onlineUserList.size()>0 ) {
// 从在线列表中删除用户名
onlineUserList.remove(username);
System.out.println(username+"已经退出!");
System.out.println("当前在线人数为"+onlineUserList.size());
}else {
System.out.println("会话已经销毁!");
}
}
}

5. 在 net.biancheng.www.servlet 包中,创建名称为 LogoutServlet 的 Servlet 类,代码如下。

package net.biancheng.www.servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 退出登录
* @author 编程帮 www.bianchengbang.net
*
*/
@WebServlet("/LogoutServlet")
public class LogoutServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//退出登录操作,将此次session进行销毁
//触发HttpSessionListener监听器的sessionDestroyed方法
request.getSession().invalidate();
//跳转回登录页面
response.sendRedirect("/listennerDemo/login.html");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

启动 Tomcat,在谷歌浏览器地址栏输入“http://localhost:8080/listennerDemo/login.html”

Servlet监听器统计网站在线人数的更多相关文章

  1. Servlet监听器统计在线人数

    监听器的作用是监听Web容器的有效事件,它由Servlet容器管理,利用Listener接口监听某个执行程序,并根据该程序的需求做出适应的响应. 例1 应用Servlet监听器统计在线人数. (1)创 ...

  2. springboot使用HttpSessionListener 监听器统计当前在线人数

    概括: request.getSession(true):若存在会话则返回该会话,否则新建一个会话. request.getSession(false):若存在会话则返回该会话,否则返回NULL ht ...

  3. java-web项目:用servlet监听器实现显示在线人数

    1.创建一个监听器 package com.listener; import javax.servlet.ServletContext; import javax.servlet.http.HttpS ...

  4. 监听器应用【统计网站人数、自定义session扫描器、踢人小案例】

    从第一篇已经讲解过了监听器的基本概念,以及Servlet各种的监听器.这篇博文主要讲解的是监听器的应用. 统计网站在线人数 分析 我们在网站中一般使用Session来标识某用户是否登陆了,如果登陆了, ...

  5. 【Servlet】1、Servlet监听器及相关接口

    Servlet监听器用于监听一些重要事件的发生,监听器对象可以在事情发生前.发生后可以做一些必要的处理. 接口: 目前Servlet2.4和JSP2.0总共有8个监听器接口和6个Event类,其中Ht ...

  6. Servlet监听器——实现在线登录人数统计小例子

    一.概念 servlet监听器的主要目的是给web应用增加事件处理机制,以便更好的监视和控制web应用的状态变化,从而在后台调用相应处理程序. 二.监听器的类型 1.根据监听对象的类型和范围,分为3类 ...

  7. Servlet监听器笔记总结

    监听器Listener的概念 监听器的概念很好理解,顾名思义,就是监视目标动作或状态的变化,目标一旦状态发生变化或者有动作,则立马做出反应. Servlet中的也有实现监听器的机制,就是Listene ...

  8. 【Servlet】Servlet监听器

    一.Servlet监听器的概念 Servlet监听器是Servlet规范中定义的一种特殊类,用于监听ServletContext.HttpSession和ServletRequest等域对象的创建与销 ...

  9. Java进阶(十三)servlet监听器

    servlet监听器 Listener是Servlet的监听器,它可以监听客户端的请求.服务端的操作等.通过监听器,可以自动激发一些操作,比如监听在线的用户的数量.当 增加一个HttpSession时 ...

随机推荐

  1. c++ vector释放概述

    这里仅为概述,具体的详情分析,可以Google下,会得到更详尽的解释. 1.函数clear和erase都将数组的size清空,但对应的空间并没有回收,而且,一直push_baclk, 对应的capac ...

  2. 【LeetCode】760. Find Anagram Mappings 解题报告

    [LeetCode]760. Find Anagram Mappings 解题报告 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/find ...

  3. 【LeetCode】424. 替换后的最长重复字符 Longest Repeating Character Replacement(Python)

    作者: 负雪明烛 id: fuxuemingzhu 公众号:每日算法题 本文关键词:LeetCode,力扣,算法,算法题,字符串,双指针,刷题群 目录 题目描述 题目大意 解题方法 双指针 代码 欢迎 ...

  4. 【剑指Offer】顺时针打印矩阵 解题报告(Python)

    [剑指Offer]顺时针打印矩阵 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interviews 题 ...

  5. 破解UltraEdit64 Version 28.20.0.92 技术分享。

    本文为原创作品,转载请注明出处,作者:Chris.xisaer E-mail:69920579@qq.com QQ群3244694 补丁程序下载地址:https://download.csdn.net ...

  6. HTMl+CSS 模仿京东网登录页面

    课后实践项目,仅页面效果,写博客纯属记录! 码云开源仓库地址:https://gitee.com/ynavc/jd 演示地址:https://ynavc.gitee.io/jd 效果图: 实现代码: ...

  7. 【MySQL作业】MySQL函数——美和易思字符串函数应用习题

    点击打开所使用到的数据库>>> 1.将所有客户的姓名与电话以"-"作为分隔符进行连接显示. 使用 concat(s1,s2,-) 函数将所有客户的姓名与电话以&q ...

  8. .net core的配置介绍(二):自定义配置(Zookeeper,数据库,Redis)

    上一篇介绍了.net core的配置原理已经系统提供的一些常用的配置,但有时我们的配置是存放在Zookeeper,DB,Redis中的,这就需要我们自己去实现集成了. 这里再介绍几个我们用的多的配置集 ...

  9. MATLAB m文件编译错误之错误使用slCharacterEncoding

    错误提示: 错误使用 slCharacterEncoding (line 51) Close all block diagrams (using 'bdclose all') before tryin ...

  10. Echart可视化学习(一)

    文档的源代码地址,需要的下载就可以了(访问密码:7567) https://url56.ctfile.com/f/34653256-527823386-04154f 正文: 创建需要的目录结构及文件 ...