编写程序,使用
Servlet
监听器统计在线用户,要求:
(1)
通过
ServletContext
监听初始化一个
application
对象,保存在线用户列表;
(2)
通过
Session
监听当用户登录成功设置
Session
属性时将用户名保存在列表中;
(3)
通过
Session
监听当用户注销登录时将用户名从列表中删除。
程序完成后,启动
Tomcat
,在地址栏输入
onlinelistener.jsp,
假设已有用户按
user1
登录,
此时准备用
user2
登录
有两种方式去实现:
- 使用 HttpSessionListener 和 HttpSessionAttributeListener 实现;
- 使用 HttpSessionBindingListener 实现。(我们这里使用这个监听器)
我们在做这个的时候要考虑到session和cookie,在做的时候难免会出现session被覆盖从而产生无法添加新的用户,我这里使用的是个人的方法,可能不够完美或者不够简洁,或者在我理解的思维程度上和实际有所偏差,
希望各位在学习知识时要跳出思维的定势,仅供参考
以下是基本框架:
![](https://img-blog.csdnimg.cn/d15f2b33f74d46bbacf6cb30c0c923b3.png)
了解session能让更快理解这篇文章,我们通过session添加是会被覆盖掉的,因此不要用固定的思维去思考,我们可以使用通过servlet的req,resp来调用session里的方法,这样就不会让session被覆盖掉,从而实现多用户登录的情况(
以上纯属个人理解)
我们直接上代码吧。
这个是xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 配置监听器 -->
<listener>
<listener-class>com.chen.listener.OnlineListener</listener-class>
</listener>
<!-- 配置servlet -->
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.chen.listener.LoginServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>ExitServlet</servlet-name>
<servlet-class>com.chen.listener.ExitServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/logindo</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ExitServlet</servlet-name>
<url-pattern>/exitdo</url-pattern>
</servlet-mapping>
</web-app>
这个是index.jsp
<%@ page import="java.util.Vector" %>
<%@ page import="com.chen.listener.UserList" %><%--
Created by IntelliJ IDEA.
User: 32358
Date: 2023/5/26
Time: 0:53
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form method="get" action="logindo">
<center>
<h2>用户登录</h2>
<hr />
<br /> 用户名: <input type="text" name="userName" /> <br />
<input type="submit" value="登录" />
</center>
</form>
<%
Vector onlineUsers = UserList.getVector(); //获取存储在线用户名的vector对象
%>
<center>
<br />
<br />
<h2>登录成功</h2>
<hr />
<br /> 欢迎你 <span style="color:red;"> <%=session.getAttribute("userName")%>
</span> <a href="exitdo">注销</a> <br />
<br /> 当前在线人数:<span style="color:red;"> <%=UserList.getUserCount()%>人</span>
<br />
<br> 在线用户名单 : <br /> <select multiple="multiple" name="list"
style="width:200px;height:250px">
<%
for (int i = 0; i < onlineUsers.size(); i++) {
out.write("<option>" + onlineUsers.get(i) + "</option>");
}
%>
</select>
</center>
</body>
</html>
我们这里使用的是Vector相当于List,但是比List好用
这个是UserList.java
package com.chen.listener;
import java.util.Vector;
public class UserList {
//Vector
//java.util.vector提供了向量类(Vector)以实现类似动态数组的功能。
//创建了一个向量类的对象后,可以往其中随意插入不同类的对象,即不需顾及类型也不需预先选定向量的容量,并可以方便地进行查找。
private static Vector online = new Vector();
//添加在线人数
public static void addUser(String userName){
online.addElement(userName);
}
//移除在线人数
public static void removeUser(String userName){
online.removeElement(userName);
}
//获取在线用户数量
public static int getUserCount(){
return online.size();
}
public static Vector getVector(){
return online;
}
}
这个是OnlineListener.java
package com.chen.listener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class OnlineListener implements HttpSessionListener,HttpSessionAttributeListener{
//监听Http会话中的属性添加
public void attributeAdded(HttpSessionBindingEvent se) {
UserList.addUser(String.valueOf(se.getValue()));//增加一个用户
}
//监听Http会话中的属性移除
public void attributeRemoved(HttpSessionBindingEvent se) {
UserList.removeUser(String.valueOf(se.getValue()));
}
//监听Http会话中的属性更改操作
public void attributeReplaced(HttpSessionBindingEvent se) {
String oldValue=String.valueOf(se.getValue());//旧的属性
String newValue=String.valueOf(se.getSession().getAttribute(se.getName()));//新的属性
UserList.addUser(newValue);//增加新的属性
}
public void sessionCreated(HttpSessionEvent se) {
System.out.println("会话已创建!");
}
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("会话已销毁!");
}
}
这个是LoginServlet.java
package com.chen.listener;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String userName=req.getParameter("userName");//获取前台传来的userName属性
HttpSession session = req.getSession();
session.setAttribute("userName", userName);//将属性保存到session会话中
resp.sendRedirect("index.jsp");//重定向到index.jsp页面
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
这个是ExitServlet.java
package com.chen.listener;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ExitServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
req.getSession().removeAttribute("userName");//从session中移除对象
resp.sendRedirect("index.jsp");//重定向到用户登录页面
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(req, resp);
}
}
运行结果展示
可以添加多个登录用户,而且也能退出相应的账户,只不过要重新进去
根据我这个框架也可以实现下图效果,博主懒得改