管理员踢除用户
分析需求
管理员要想踢出用户:
首先,得获取到用户名,一个用户对应一个Session,所以这里用到了HttpSessionBindingListener接口。
其次,对于用户名和Session的对应应该以Map的形式存放,所以要使用Map,但是,此map应该何时产生呢?答案应该是在应用一产生就会创建,所以放在ServletContext域中,使用ServletContext监听器,在初始化的时候直接创建。
最后,在进行踢除(Kick
)的时候,要从全局域中获取map,在map中读取到用户的session使其失效。
该程序的执行顺序,可以简单的如下图:
核心处理代码
用于初始化的时候直接创建Map
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.*;
import java.util.HashMap;
import java.util.Map;
@WebListener()
public class MyServletContextListener implements ServletContextListener{
private ServletContext sc;
@Override
public void contextInitialized(ServletContextEvent sce) {
//应用启动的时候创建个Map
//Key 为用户名,Value为当前用户的Session对象
Map<String, HttpSession> map = new HashMap<>();
sc = sce.getServletContext();
sc.setAttribute("map",map);
}
}
先分析HttpSessionBindingListener,该接口用于监听SessionJavaBean对象绑定到HttpSession对象和从HttpSession对象解绑事件,public void valueBound(HttpSessionBindingEvent event)
当对象被绑定到HttpSession对象中,Web容器将调用对象的valueBound方法并传递一个HttpSessionBindingEvent类型的事件对象,程序可以通过这个事件对象来获得将要绑定的HttpSession对象。这里说的绑定,说的通俗点就是session.setAttribute()
。在此程序中,绑定指的是,用户登录的时候,将表单提交的name和age形成User类对象,存放于session中。
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import java.util.Map;
public class User implements HttpSessionBindingListener {
//使用HttpSessionBindingListener监听器,HttpSessionBindingListener内有两个方法
// valueBound(HttpSessionBindingEvent event)
// 和valueUnbound(HttpSessionBindingEvent event)
// 前者为数据绑定,后者为取消绑定
private String name;
private int age;
private HttpSession currentSession;
private ServletContext sc;
private Map<String,HttpSession> map;
public User(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public void valueBound(HttpSessionBindingEvent event) {
currentSession = event.getSession();
sc = currentSession.getServletContext();
//从全局域中获取Map
map = (Map<String, HttpSession>) sc.getAttribute("map");
//将用户名和Session放入到Map
map.put(name,currentSession);
}
}
在登录后,将获取到参数传递个Session域
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 = "LoginServlet",urlPatterns = "/loginServlet")
public class LoginServlet extends HttpServlet {
private String name;
private String ageStr;
private Integer age;
private HttpSession session;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取用户提交的请求参数
request.setCharacterEncoding("UTF-8");
name = request.getParameter("name");
ageStr = request.getParameter("age");
age = Integer.valueOf(ageStr);
//创建User对象user
User user = new User(name,age);
//获取当前请求对应的Session
session = request.getSession();
//将创建好的user对象放入到session域中
session.setAttribute("user",user);
//然后页面重定向到welcome页面
response.sendRedirect(request.getContextPath()+"/welcome.jsp");
}
}
用户的Kick处理
import javax.servlet.ServletContext;
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;
import java.util.Map;
@WebServlet(name = "KickServlet",urlPatterns = "/kickServlet")
public class KickServlet extends HttpServlet {
private ServletContext sc;
private Map<String, HttpSession> map;
private String name;
private HttpSession session;
//当用户点击踢出后的操作
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//Kick使Map中的Session失效
//首先得获取到全局域
sc = request.getSession().getServletContext();
//然后获取到其map map是之前域一初始化的时候就创建的
map = (Map<String, HttpSession>) sc.getAttribute("map");
//获取要Kick的用户名请求参数
name = request.getParameter("name");
session = map.get(name);
session.invalidate();
//将该用户对应的Entry从Map中移除
map.remove(name);
//请求的转发
request.getRequestDispatcher("/index.jsp").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
页面
index.jsp页面用于管理员的管理当前在线客户
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<center>
<table border="1">
<caption>已登录的用户</caption>
<tr>
<th>用户名</th>
<th>Session</th>
<th>Kick</th>
</tr>
<c:forEach items="${map }" var="entry">
<tr>
<td>${entry.key}</td>
<td>${entry.value}</td>
//传递的是session的name,而并不是全局变量中name
<td> <a href="${pageContext.request.contextPath}/kickServlet?name=${entry.key}">Kick </a> </td>
</tr>
</c:forEach>
</table>
</center>
</body>
</html>
login.jsp页面用于用户的登录
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/loginServlet" method="post">
用户名<input type="text" name="name"/>
年龄<input type="text" name="age"/>
<input type="submit" value="Login"/>
</form>
</body>
</html>
welcome.jsp页面用于展示用户登录
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<center>
<h1>Welcome!!!</h1>
</center>
</body>
</html>