Servlet监听器统计网站在线人数
本节我们利用 Servlet 监听器接口,完成一个统计网站在线人数的案例。当一个用户登录后,显示欢迎信息,同时显示出当前在线人数和用户名单。当用户退出登录或 Session 过期时,从在线用户名单中删除该用户,同时将在线人数减 1。
本案例可以通过如下 2 种方案实现:
2. 在 WebContent 中,创建 login.html,代码如下。
3. 在 net.biancheng.www.servlet 包中,创建名称为 LoginServlet 的 Servlet 类,代码如下。
4. 在 net.biancheng.www. listener 包中,创建名称为 MySessionListener 的监听器类,代码如下。
5. 在 net.biancheng.www.servlet 包中,创建名称为 LogoutServlet 的 Servlet 类,代码如下。
6. 启动 Tomcat,在谷歌浏览器地址栏输入“http://localhost:8080/listennerDemo/login.html”,访问 login.html,结果如下图。
7. 输入账号信息后,点击提交,结果如下图。
8. 打开火狐浏览器,访问 login.html,填写账号信息,结果如下图。
9. 点击提交,结果如下图。
10. 在谷歌浏览器点击退出登录,回到登录首页,切换到火狐浏览器刷新页面,结果如图。
2 .在 WebContent 中,创建 login.html,代码如下。
3. 在 net.biancheng.www.servlet 包中,创建名称为 LoginServlet 的 Servlet 类,代码如下。
4. 在 net.biancheng.www.servlet 包中,创建名称为 LogoutServlet 的 Servlet 类,代码如下。
5. 在 net.biancheng.www. listener 包中创建名称为 MyBindingListener 的监听器类,代码如下。
6. 启动 Tomcat,在谷歌浏览器地址栏输入“http://localhost:8080/sessionBindingDemo/login.html”,访问 login.html,结果如下图。
7. 输入账号信息后,点击提交,结果如下图。
8. 火狐浏览器,访问 login.html,填写账号信息,结果如下图。
9. 点击提交,结果如下图。
10. 在谷歌浏览器点击退出登录,切换到火狐浏览器刷新页面,结果如图。
本案例可以通过如下 2 种方案实现:
- 使用 HttpSessionListener 和 HttpSessionAttributeListener 实现;
- 使用 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); } }
6. 启动 Tomcat,在谷歌浏览器地址栏输入“http://localhost:8080/listennerDemo/login.html”,访问 login.html,结果如下图。
7. 输入账号信息后,点击提交,结果如下图。
8. 打开火狐浏览器,访问 login.html,填写账号信息,结果如下图。
9. 点击提交,结果如下图。
10. 在谷歌浏览器点击退出登录,回到登录首页,切换到火狐浏览器刷新页面,结果如图。
使用 HttpSessionBindingListener 实现
1. 创建一个名称为 sessionBindingDemo 的工程,并分别创建 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.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.biancheng.www.listener.MyBindingListener; /** * 登录 * * @author 编程帮 www.bianchengbang.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.setCharacterEncoding("utf-8"); PrintWriter writer = response.getWriter(); //获取表单数据 String username = request.getParameter("username"); // 查看当前会话是否已有账号登录 MyBindingListener loginedDemo = (MyBindingListener) request.getSession().getAttribute("onlineUserBindingListener"); //当前会话已有账号登录 if ("".equals(username) || username == null) { System.out.println("非法操作,您没有输入用户名"); response.sendRedirect("/sessionBindingDemo/login.html"); } else { if (loginedDemo != null) { String logined = loginedDemo.getUsername(); System.out.println("您已经登录,重复登录无效,请先退出当前账号重新登录!"); writer.write("<h1>编程帮 www.biancheng.net</h1>" + "<h3>您好,您已经登录了账户:" + logined + "</h3>" + "如要登录其他账号,请先退出当前账号重新登录!"); // 登陆页面为填写内容 } else { //将当前账号加入会话中 request.getSession().setAttribute("onlineUserBindingListener", new MyBindingListener(username)); writer.write("<h1>编程帮 www.biancheng.net</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=\"/sessionBindingDemo/LogoutServlet\">退出登录</a>"); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
4. 在 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); } }
5. 在 net.biancheng.www. listener 包中创建名称为 MyBindingListener 的监听器类,代码如下。
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.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionBindingListener; /** * 使用MyBindingListener监听 * * @author 编程帮 www.bianchengbang.net */ 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()); } }
6. 启动 Tomcat,在谷歌浏览器地址栏输入“http://localhost:8080/sessionBindingDemo/login.html”,访问 login.html,结果如下图。
7. 输入账号信息后,点击提交,结果如下图。
8. 火狐浏览器,访问 login.html,填写账号信息,结果如下图。
9. 点击提交,结果如下图。
10. 在谷歌浏览器点击退出登录,切换到火狐浏览器刷新页面,结果如图。