Servlet 监听器案例

目录

使用 HttpSessionListener 和 HttpSessionAttributeListener 实现

使用 HttpSessionBindingListener 实现


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

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

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

使用 HttpSessionListener 和 HttpSessionAttributeListener 实现

创建 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="/web/LoginServlet" method="GET">
    <table border="1" width="50%">
        <tr>
            <td colspan="2" align="center">欢迎登录 LoginServlet !</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>

创建名称为 LoginServlet  的 Servlet 类,代码如下。

package swadian.servlet.listener;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

/**
 * @author swadian
 * @date 2022/2/14
 * @Version 1.0
 */
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    @SuppressWarnings("unchecked")
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws 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("/web/login.html");
        } else {
            if (!"".equals(logined) && logined != null) {
                System.out.println("您已经登录,重复登录无效,请先退出当前账号重新登录!");
                writer.write("<h1>LoginServlet 提醒您!</h1>"
                        + "<h3>您好,您已经登录了账户:" + logined + "</h3>"
                        + "如要登录其他账号,请先退出当前账号重新登录!");
            } else {// 将当前账号加入会话中
                request.getSession().setAttribute("username", username);
                writer.write("<h1>LoginServlet</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=\"/web/LogoutServlet\">退出登录</a>");
        }
    }

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

当有对象添加到session中时,session.setAttribute("object",other)触发attributeAdded事件,当该对象从session移除时,session.removeAttribute("object")触发attriubteRemoved事件,当该属性的值发生变化时, session.replaceAttribute("object",another)触发attributeRepalced事件。

注意:只要有对象保存到session中或从session中移除或改变属性的值都会触发相应事件,不论该对象是否实现了AttributeListener

创建名称为 MySessionListener 的监听器类,代码如下。

package swadian.servlet.listener;

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;
import java.util.ArrayList;
import java.util.List;

/**
 * @author swadian
 * @date 2022/2/15
 * @Version 1.0
 * @Description 监听器
 */
@WebListener
public class MySessionListener implements HttpSessionListener, HttpSessionAttributeListener {
    @SuppressWarnings("unchecked")
    @Override//向Session添加属性时立即执行:LoginServlet->MySessionListener->LoginServlet
    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);
    }

    @SuppressWarnings("unchecked")//Session销毁时执行
    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("会话已经销毁!");
        }
    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {

    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {

    }

    public MySessionListener() {
    }

    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {

    }
}

创建名称为 LogoutServlet 的 Servlet 类,代码如下。

package swadian.servlet.listener;

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 java.io.IOException;

/**
 * @author swadian
 * @date 2022/2/15
 * @Version 1.0
 */
@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("/web/login.html");
    }

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

}

启动 Tomcat,在谷歌浏览器地址栏输入“http://localhost:8080/web/login.html”,访问 login.html,结果如下图。

 输入账号信息后,点击提交,结果如下图。// 登陆前已经使用其他浏览器登录了一个账号

 

在相同的浏览器,再次登录susan账号,点击提交,结果如下图。

使用 HttpSessionBindingListener 实现

// 登录页 login.html 保持不变

创建名称为 MyBindingListener 的监听器类,代码如下。

package swadian.servlet.listener_servlet;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import java.util.ArrayList;
import java.util.List;

/**
 * @author swadian
 * @date 2022/2/17
 * @Version 1.0
 */
public class MyBindingListener implements HttpSessionBindingListener {
    private String username;

    public MyBindingListener(String username) {
        super();
        this.username = username;
    }

    public String getUsername() {
        return username;
    }

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

    public MyBindingListener() {
    }

    @SuppressWarnings("unchecked")
    public void valueBound(HttpSessionBindingEvent event) {
        HttpSession session = event.getSession();
        ServletContext application = session.getServletContext();
        // 把用户名放入在线列表
        List<String> onlineUserList = (List) application.getAttribute("onlineUserList");
        // 第一次使用前,需要初始化
        if (onlineUserList == null) {
            onlineUserList = new ArrayList<String>();
        }
        onlineUserList.add(this.username);
        application.setAttribute("onlineUserList", onlineUserList);
        System.out.println("*******用户:" + this.username + "  已经成功加入在线用户列表");
    }

    @SuppressWarnings("unchecked")
    public void valueUnbound(HttpSessionBindingEvent event) {
        HttpSession session = event.getSession();
        ServletContext application = session.getServletContext();
        // 从在线列表中删除用户名
        List<String> onlineUserList = (List<String>) application.getAttribute("onlineUserList");
        onlineUserList.remove(this.getUsername());
        application.setAttribute("onlineUserList", onlineUserList);
        System.out.println(this.username + "退出。");
        System.out.println("当前在线人数:" + onlineUserList.size());
    }

}

创建名称为 LoginServlet 的 Servlet 类,代码如下。

//HttpSessionBindingListener方式有代码入侵,需要使用 new MyBindingListener(username)

注意:只有当该监听器(MyBindingListener)保存到session中或从session移除时才会触发事件,其他没有实现该listener对象保存到session时不会触发该事件。

package swadian.servlet.listener_servlet;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

/**
 * @author swadian
 * @date 2022/2/17
 * @Version 1.0
 */
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    @SuppressWarnings("unchecked")
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //设置页面输出格式
        response.setContentType("text/html;charset=UTF-8");
        request.setCharacterEncoding("utf-8");
        PrintWriter writer = response.getWriter();
        //获取表单数据->乱码处理
        String username = request.getParameter("username");
        username = new String(username.getBytes("ISO-8859-1"), "utf-8");
        //查看当前会话是否已有账号登录
        MyBindingListener loginedDemo = (MyBindingListener) request.getSession().getAttribute("onlineUserBindingListener");
        //当前会话已有账号登录
        if ("".equals(username) || username == null) {
            System.out.println("非法操作,您没有输入用户名");
            response.sendRedirect("/web/login.html");
        } else {
            if (loginedDemo != null) {
                String logined = loginedDemo.getUsername();
                System.out.println("您已经登录,重复登录无效,请先退出当前账号重新登录!");
                writer.write("<h1>LoginServlet 提醒您 !</h1>"
                        + "<h3>您好,您已经登录了账户:" + logined + "</h3>"
                        + "如要登录其他账号,请先退出当前账号重新登录!");
                // 登陆页面为填写内容
            } else {
                //将当前账号加入会话中
                request.getSession().setAttribute("onlineUserBindingListener", new MyBindingListener(username));
                writer.write("<h1>LoginServlet 欢迎您!</h1>"
                        + "<h3>" + username + ":   欢迎您的到来</h3>");
            }
            //向页面输出结果
            //从上下文中获取已经登录账号的集合
            List<String> onLineUserList = (List<String>) request.getServletContext().getAttribute("onlineUserList");
            System.out.println("当前在线用户为:");
            if (onLineUserList != null) {
                for (int i = 0; i < onLineUserList.size(); i++) {
                    System.out.println(onLineUserList.get(i));
                }
            }
            System.out.println("********************************");
            writer.write("<h1>   当前在线人数为:" + onLineUserList.size() + "</h1>"
                    + "<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=\"/web/LogoutServlet\">退出登录</a>");
        }
    }

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

创建名称为 LogoutServlet 的 Servlet 类,代码如下。

package swadian.servlet.listener_servlet;

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 java.io.IOException;

/**
 * @author swadian
 * @date 2022/2/17
 * @Version 1.0
 */
@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("/web/login.html");
    }

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

启动 Tomcat,在谷歌浏览器地址栏输入“http://localhost:8080/web/login.html”,访问 login.html,结果如下图。

输入账号信息后,点击提交,结果如下图。

HttpSessionBindingListener和HttpSessionAttributeListener区别

HttpSessionBindingListener和HttpSessionAttributeListener区别_fjkxyl的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:深蓝海洋 设计师:CSDN官方博客 返回首页
评论

打赏作者

swadian2008

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值