本节我们利用 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. UDP&串口调试助手用法(4)

    接收配置用法 概览 保存文件 可将数据保存到文件和文件夹 如果选择的时文件,则需要自己手动选择保存的文件. 如果选择的时文件夹,则需要指定文件夹的类型和文件的后缀 支持保存文件类型: 文本文件和二进制 ...

  2. 【LeetCode】109. Convert Sorted List to Binary Search Tree 解题报告(Python)

    [LeetCode]109. Convert Sorted List to Binary Search Tree 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id ...

  3. World is Exploding(hdu5792)

    World is Exploding Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Other ...

  4. 警惕!PHP、Node、Ruby 和 Python 应用,漏洞还没结束!

    12 月 10 日凌晨,Apache 开源项目 Log4j2 的远程代码执行漏洞细节被公开,作为当前全球使用最广泛的 java 日志框架之一.该漏洞影响着很多全球使用量前列的开源组件,如 Apache ...

  5. Chapter 9 Measurement Bias

    目录 9.1 Measurement Error The structure of measurement error 9.3 Mismeasured confounders 9.4 Intentio ...

  6. CS5216 DP转HDMI 1080P方案|CS5216参数|CS5216中文规格书

    Capstone CS5216是一款单端口/中继器,具有重新定时功能.它支持交流和直流耦合3.0-Gbps操作,可编程均衡和抖动清除.它包括DP电缆适配器寄存器,可用于识别电缆适配器的功能.这个抖动清 ...

  7. Java+HTML5 试题 云南农业职业技术学院 - 互联网技术学院

    摸底测试 100题_共100.00分_及格60.00分  第1题 [单选题][1.00分][概念理解] 执行完下面程序片段后, ( )的结论是正确的. int a, b, c; a = 1; b = ...

  8. frontend-maven-plugin插件问题解决

    1.插件介绍 frontend-maven-plugin为项目本地下载/安装Node和NPM,运行npm install命令 . 它适用于Windows,OS X和Linux. 这个插件也可以下载No ...

  9. 初识python 之 兔子生崽(小练习)

    题目:有一对兔子,从出生后第三个月起每个月都生一对小兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子不死,每个月的兔子总数为多少?思路分析: 月份 兔子数 规律1 2 2**12 2 2**13 ...

  10. 原型模式(python)

    原型模式也叫克隆模式,通过拷贝自身的属性来创建一个新的对象,基本方法就是调用copy模块下的 (浅拷贝)copy() 和(深拷贝)deepcopy() #!/usr/bin/env python3 # ...