案例:使用监听器踢出在线用户

使用监听器管理在线用户

网站的管理员对于一些不守规矩的登录用户可以进行踢出,即使用户强制下线,这里要完成的就是这个功能。思路如下:
当有用户登录时,将用户的信息放到session里面,之后将这个session放到一个map的value中,使用用户名作为key,一般网站在注册用户名时是不能重复的,所以这里可以保证用户名的唯一性,即key不会重复。这里使用HttpSessionBindingListener监听器,一旦User对象与session发生绑定时就将其放到map中,map存储在ServletContext中。如果要踢出用户时,只需要根据用户名去map中找到相应的session,将session失效即可。

踢出在线用户分析

1.创建登录页面login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<form action="/login">
    用户名:<input type="text" name="username">
    <input type="submit" value="登录">
</form>

</body>
</html>

2.定义ServletContext监听器,在ServletContext创建时创建map对象,在web.xml文件中注册监听器:

package com.monkey1024.listener;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSession;

public class MyServletContextListener implements ServletContextListener {

    /*
     * 监听ServletContext 初始化时创建一个Map对象
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {

        //map的key存放用户名,value存放该用户生成的session对象
        Map<String,HttpSession> map = new HashMap<>();
        ServletContext sc = sce.getServletContext();
        //将创建好的map对象放到ServletContext域中
        sc.setAttribute("map", map);
    }


}

3.创建javabean User并实现HttpSessionBindingListener重写里面的方法,当与session发生绑定时,将用户名和产生的session对象放到map中:

package com.monkey1024.bean;

import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;

/**
 * 用户
 *
 */
public class User implements HttpSessionBindingListener{

    private String username;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        ServletContext sc = event.getSession().getServletContext();
        //获取ServletContext中的map
        Map<String,HttpSession> map = (Map<String, HttpSession>) sc.getAttribute("map");
        //将用户信息放到map中
        map.put(username, event.getSession());
    }


}
  1. 创建处理用户登录的LoginServlet用来接收客户端提交的数据并将User对象与session绑定。
package com.monkey1024.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.monkey1024.bean.User;

/**
 * 用户登录
 */
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        //将获取用户名并user信息放到session中
        User u = new User();
        u.setUsername(request.getParameter("username"));
        request.getSession().setAttribute("user", u);

        //重定向到登录成功页面
        response.sendRedirect("/login_success.jsp");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

5.创建展示所有登录用户信息的jsp页面:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
    <table border="1">
        <tr>
            <td>序号</td>
            <td>用户</td>
            <td>操作</td>
        </tr>
        <c:forEach items="${applicationScope.map }" var="m" varStatus="obj">
            <tr style="background-color: ${obj.index % 2 == 0?'orange':'red'}">
                <td>${obj.count }</td>
                <td>${m.key }</td>
                <td><a href="/deleteUser?username=${m.key}">删除</a></td>
            </tr>
        </c:forEach>
    </table>
</body>
</html>

6.创建servlet用来踢出在线用户

package com.monkey1024.servlet;

import java.io.IOException;
import java.util.Map;

import javax.servlet.ServletContext;
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 DeleteServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        //获取浏览器提交的数据,即要被踢出的用户名
        String username = request.getParameter("username");
        HttpSession currentSession = request.getSession();
        ServletContext sc = currentSession.getServletContext();
        //从ServletContext获取map
        Map<String,HttpSession> map = (Map<String,HttpSession>)sc.getAttribute("map");

        //获取要删除用户的session
        HttpSession session = map.get(username);
        //将该用户的session失效并从map中删除
        if(session != null){
            session.invalidate();
            map.remove(username);
        }

        response.sendRedirect("/userlist.jsp");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}