Listener(监听器) 是一个实现特定接口的 java 程序,用于监听另一个 java 对象的方法调用或者属性改变。
自定义监听器
事件源:Person.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Person { private String name; private int weight; private PersonListener listener; public void addPersonListener (PersonListener listener) { this .listener = listener; } public void eat () { weight += 5 ; if (listener != null ) { PersonEvent event = new PersonEvent(this ); listener.personEating(event); } } }
监听内容 1 2 3 public interface PersonListener { public void personEating (PersonEvent event) ; }
事件类 1 2 3 public class PersonEvent { private Object source; }
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Test public void testName () { Person p = new Person(); p.setName("小明" ); p.setWeight(100 ); p.addPersonListener(new PersonListener() { @Override public void personEating (PersonEvent event) { System.out.println("有人在吃饭" ); Person p = (Person) event.getSource(); System.out.println(p.getName()); System.out.println(p.getWeight()); } }); p.eat(); }
Servlet 监听器
Servlet 定义了多种类型的监听器,监听的事件源是3个域对象 ServletContext
、HttpSession
、ServletRequest
。
Servlet规范针对3个域对象的操作,又把监听器划分为三类:
监听3个域对象的创建和销毁的事件监听器
监听3个域对象的属性的增加和删除的监听器
监听绑定到 httpSession 域中的某个对象的状态的监听器
编写 Servlet 监听器,
需要实现一个特定的接口,并针对相应动作覆盖接口中的响应方法。
和其他事件监听器不同的是,Servlet监听器的注册不是直接注册在事件源,而是由 web 容器负责,我们只需要在 web.xml 中使用 <listener>
标签配置好监听器, web 容器就会自动把监听器注册到事件源中
web.xml 文件可以配置多个 Servlet 事件监听器,web服务器按照它们在 web.xml 中注册的顺序来加载 Servlet 监听器:
1 2 3 4 5 <listener > <listener-class > cn.itcast.servlet.listener.MyServletContextListener</listener-class > </listener >
ServletContextListener
用于坚定 ServletContext 对象的创建和销毁事件
ServletContext 的作用
保存全局应用数据对象
加载框架配置文件
实现任务调度(定时器),启动定时程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 package cn.itcast.servlet.listener; import java.text.DateFormat;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask; import javax.servlet.ServletContext;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener; public class MyServletContextListener implements ServletContextListener { @Override public void contextDestroyed (ServletContextEvent sce) { System.out.println("监听ServletContext对象销毁了..." ); } @Override public void contextInitialized (ServletContextEvent sce) { System.out.println("监听ServletContext对象创建了..." ); ServletContext servletContext = sce.getServletContext(); final Timer timer = new Timer(); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss" ); try { Date first = dateFormat.parse("2012-08-07 10:42:00" ); timer.schedule(new TimerTask() { int i; @Override public void run () { i++; System.out.println("从10点40分开始启动程序,每隔3秒重复执行" ); if (i == 10 ) { timer.cancel(); } } }, first, 3000 ); } catch (ParseException e) { e.printStackTrace(); } } } ``` ## HttpSessionListener --- 监听 HttpSession 的创建和销毁 ```java package cn.itcast.servlet.listener; import javax.servlet.http.HttpSession;import javax.servlet.http.HttpSessionEvent;import javax.servlet.http.HttpSessionListener; public class MyHttpSessionListener implements HttpSessionListener { @Override public void sessionCreated (HttpSessionEvent se) { System.out.println("session被创建了" ); HttpSession session = se.getSession(); System.out.println("id:" + session.getId()); } @Override public void sessionDestroyed (HttpSessionEvent se) { System.out.println("session被销毁了" ); HttpSession session = se.getSession(); System.out.println("id:" + session.getId()); } }
统计在线人数
首先,初始化在线人数、根据前文,ServletContextListener 可以监听 ServletContext 对象的创建,新建一个实现监听器接口的类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package cn.itcast.servlet.listener.demo2; import javax.servlet.ServletContext;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener; public class OnlineCountServletContextListener implements ServletContextListener { @Override public void contextDestroyed (ServletContextEvent sce) { } @Override public void contextInitialized (ServletContextEvent sce) { ServletContext context = sce.getServletContext(); context.setAttribute("onlinenum" , 0 ); } }
利用 HttpSessionListenner 监听 HttpSession 对象的创建和销毁,可统计在线人数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package cn.itcast.servlet.listener.demo2; import javax.servlet.ServletContext;import javax.servlet.http.HttpSession;import javax.servlet.http.HttpSessionEvent;import javax.servlet.http.HttpSessionListener; public class OnlineCountHttpSessionListener implements HttpSessionListener { @Override public void sessionCreated (HttpSessionEvent se) { HttpSession session = se.getSession(); ServletContext context = session.getServletContext(); int onlinenum = (Integer) context.getAttribute("onlinenum" ); context.setAttribute("onlinenum" , onlinenum + 1 ); System.out.println(session.getId() + "被创建了..." ); } @Override public void sessionDestroyed (HttpSessionEvent se) { HttpSession session = se.getSession(); ServletContext context = session.getServletContext(); int onlinenum = (Integer) context.getAttribute("onlinenum" ); context.setAttribute("onlinenum" , onlinenum - 1 ); System.out.println(session.getId() + "被销毁了 ..." ); } }
xml 中需要配置
1 2 3 4 5 6 <listener > <listener-class > cn.itcast.servlet.listener.demo2.OnlineCountServletContextListener</listener-class > </listener > <listener > <listener-class > cn.itcast.servlet.listener.demo2.OnlineCountHttpSessionListener</listener-class > </listener >
jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <!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> <h1>显示在线人数</h1> ${applicationScope.onlinenum } </body> </html>
案例:统计在线人数
SannerServletContextListener 干了两件事:初始化List,启动定时器,每隔20秒执行一次
注意:
因为要从 List 中删除元素,循环用 Iterator 不用 foreach
在删除 Session 对象时,利用同步锁 解决 保证 Session 的 List 集合长度不能改变。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 package cn.itcast.servlet.listener.demo3; import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.Timer;import java.util.TimerTask; import javax.servlet.ServletContext;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import javax.servlet.http.HttpSession; public class ScannerServletContextListener implements ServletContextListener { @Override public void contextDestroyed (ServletContextEvent sce) { } @Override public void contextInitialized (ServletContextEvent sce) { final List<HttpSession> sessionList = new ArrayList<HttpSession>(); ServletContext servletContext = sce.getServletContext(); servletContext.setAttribute("sessionList" , sessionList); Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run () { System.out.println("定时session扫描器执行了...." ); synchronized (sessionList) { Iterator<HttpSession> iterator = sessionList.iterator(); while (iterator.hasNext()) { HttpSession session = iterator.next(); if (System.currentTimeMillis() - session.getLastAccessedTime() > 1000 * 60 ) { System.out.println(session.getId() + "对象已经1分钟没有使用,被销毁了..." ); session.invalidate(); iterator.remove(); } } } } }, 0 , 20000 ); } }
ScannerHttpSessionListener
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package cn.itcast.servlet.listener.demo3; import java.util.List; import javax.servlet.ServletContext;import javax.servlet.http.HttpSession;import javax.servlet.http.HttpSessionEvent;import javax.servlet.http.HttpSessionListener; public class ScannerHttpSessionListener implements HttpSessionListener { @Override public void sessionCreated (HttpSessionEvent se) { HttpSession httpSession = se.getSession(); ServletContext context = httpSession.getServletContext(); List<HttpSession> sessionList = (List<HttpSession>) context .getAttribute("sessionList" ); synchronized (sessionList) { sessionList.add(httpSession); } context.setAttribute("sessionList" , sessionList); System.out.println(httpSession.getId() + "被创建了..." ); } @Override public void sessionDestroyed (HttpSessionEvent se) { } }
web.xml
1 2 3 4 5 6 <listener > <listener-class > cn.itcast.servlet.listener.demo3.ScannerServletContextListener</listener-class > </listener > <listener > <listener-class > cn.itcast.servlet.listener.demo3.ScannerHttpSessionListener</listener-class > </listener >
监听三个域对象属性变化事件的监听器
这三个监听器接口分别是:
ServletContextAttributeListener
HttpSessionAttributeListener
ServletRequestAttributeListener
用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <!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> <% session.setAttribute("name" ,"张三" ); session.setAttribute("name" ,"李四" ); session.removeAttribute("name" ); %> </body> </html>==
MyHttpSessionAttributeListener
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 package cn.itcast.servlet.listener; import javax.servlet.http.HttpSession;import javax.servlet.http.HttpSessionAttributeListener;import javax.servlet.http.HttpSessionBindingEvent; public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener { @Override public void attributeAdded (HttpSessionBindingEvent se) { System.out.println("向session添加了一个属性..." ); HttpSession session = se.getSession(); System.out.println("属性名称:" + se.getName()); System.out.println("属性值:" + session.getAttribute(se.getName())); } @Override public void attributeRemoved (HttpSessionBindingEvent se) { System.out.println("从session移除了一个属性...." ); System.out.println("属性名称:" + se.getName()); } @Override public void attributeReplaced (HttpSessionBindingEvent se) { System.out.println("将session中一个属性值替换为其他值..." ); HttpSession session = se.getSession(); System.out.println("属性名称:" + se.getName()); System.out.println("属性值:" + session.getAttribute(se.getName())); } }
HttpSessionBindingListener接口
实现了 HttpSessionBindingListener 接口的 JavaBean 对象可以感知到自己被绑定到 Session 中和从 Session 中删除的事件。
demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package cn.itcast.domain; import javax.servlet.http.HttpSessionBindingEvent;import javax.servlet.http.HttpSessionBindingListener; public class Bean1 implements HttpSessionBindingListener { private int id; private String name; public int getId () { return id; } public void setId (int id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } @Override public void valueBound (HttpSessionBindingEvent event) { System.out.println("Bean1对象被绑定了..." ); System.out.println("绑定对象name:" + this .name); } @Override public void valueUnbound (HttpSessionBindingEvent event) { System.out.println("Bean1对象被解除绑定了..." ); System.out.println("解除绑定对象name:" + this .name); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <%@page import ="cn.itcast.domain.Bean1" %> <!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> <% Bean1 bean_Susan = new Bean1(); bean_Susan.setId(100 ); bean_Susan.setName("Susan" ); session.setAttribute("bean1" ,bean_Susan); Bean1 bean_Mary = new Bean1(); bean_Mary.setId(200 ); bean_Mary.setName("Mary" ); session.setAttribute("bean1" ,bean_Mary); %> ${bean1.name } </body> </html>
注意陷阱:当 Session 绑定的 JavaBean 对象替换时,会让新对象绑定,旧对象解绑
HttpSessionActivationListener接口
使用场景:Session保存数据,很长一段时间没用,但是不能销毁Session对象,又不想占用服务器内存资源 —– 钝化(将服务器内存中数据序列化硬盘上)
实现了HttpSessionActivationListener接口的 JavaBean 对象可以感知自己被活化和钝化的事件
当绑定到 HttpSession 对象中的 JavaBean 对象将要随 HttpSession 对象被钝化之前,web 服务器调用该 JavaBean 对象的 void sessionWillPassivate(HttpSessionBindingEvent event) 方法
当绑定到 HttpSession 对象中的 JavaBean 对象将要随 HttpSession 对象被活化之后,web 服务器调用该 JavaBean 对象的 void sessionDidActive(HttpSessionBindingEvent event) 方法
钝化和活化应该由 Tomcat 服务器 自动进行,所以应该配置 Tomcat :
1 2 3 4 5 6 7 <Context > <Manager className ="org.apache.catalina.session.PersistentManager" maxIdleSwap ="1" > <Store className ="org.apache.catalina.session.FileStore" directory ="it315" /> </Manager > </Context >
demo:
write.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <%@page import ="cn.itcast.domain.Bean2" %> <!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> <!-- 将javabean 对象保存Session中 --> <% Bean2 bean2 = new Bean2(); bean2.setName("联想笔记本" ); bean2.setPrice(5000 ); session.setAttribute("bean2" ,bean2); %> </body> </html>
read.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <!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> <!-- 读取javabean对象的数据 --> 读取bean2的数据: ${bean2.name } , ${bean2.price } </body> </html>
Bean2.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package cn.itcast.domain; import javax.servlet.http.HttpSessionActivationListener;import javax.servlet.http.HttpSessionEvent; public class Bean2 implements HttpSessionActivationListener { private String name; private double price; public String getName () { return name; } public void setName (String name) { this .name = name; } public double getPrice () { return price; } public void setPrice (double price) { this .price = price; } @Override public void sessionDidActivate (HttpSessionEvent se) { System.out.println("bean2对象被活化..." ); } @Override public void sessionWillPassivate (HttpSessionEvent se) { System.out.println("bean2对象被钝化..." ); } }
配置Tomcat后,开启服务器,打开write.jsp,等待一分钟,在这一分钟内,打开read.jsp是可以读取到bean2对象的。一分钟过后,read.jsp读取不到bean2对象了,同时控制台输出:
输出 bean2对象被钝化
这时候就实现了钝化的效果。好,接下来按照步骤走,钝化后it315目录在哪里? 在项目文件夹是找不到这个目录的,得去Tomcat服务器的目录去找:tomcat/work/Catalina/localhost/项目工程名/
在it315目录中的确可以看到一个XXXXXX.session的文件,其中XXXXXX就是SessionId,打开这个文件,却没有发现 JavaBean 的任何信息,这是为什么呢?
回顾JavaSE的知识,可以发现 JavaBean 没有序列化。Java对象如果想被序列化,必须实现Serializable接口 —- Bean2 实现该接口:
1 2 3 4 5 import java.io.Serializable;... public class Bean2 implements HttpSessionActivationListener , Serializable {... }
接下来,重启服务器,打开write.jsp,一分钟后,控制台照旧输出bean2对象被钝化的消息,再进去XXXXXX.session文件中,发现可以找到 JavaBean 对象的相关信息(虽然是乱码)。接下来再打开read.jsp,发现可以读取到 JavaBean 对象了,并且此时控制台输出:bean2对象被活化...
案例:在线用户列表和踢人功能
demo
MyServletContextListener
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package cn.itcast.listener; import java.util.HashMap;import java.util.Map; import javax.servlet.ServletContext;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import javax.servlet.http.HttpSession; import cn.itcast.domain.User; public class MyServletContextListener implements ServletContextListener { @Override public void contextDestroyed (ServletContextEvent sce) { } @Override public void contextInitialized (ServletContextEvent sce) { Map<User, HttpSession> map = new HashMap<User, HttpSession>(); ServletContext servletContext = sce.getServletContext(); servletContext.setAttribute("map" , map); } }
JavaBean:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 package cn.itcast.domain; 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 int id; private String username; private String password; private String role; public int getId () { return id; } public void setId (int id) { this .id = id; } public String getUsername () { return username; } public void setUsername (String username) { this .username = username; } public String getPassword () { return password; } public void setPassword (String password) { this .password = password; } public String getRole () { return role; } public void setRole (String role) { this .role = role; } @Override public void valueBound (HttpSessionBindingEvent event) { HttpSession session = event.getSession(); ServletContext servletContext = session.getServletContext(); Map<User, HttpSession> map = (Map<User, HttpSession>) servletContext .getAttribute("map" ); map.put(this , session); } @Override public void valueUnbound (HttpSessionBindingEvent event) { HttpSession session = event.getSession(); ServletContext servletContext = session.getServletContext(); Map<User, HttpSession> map = (Map<User, HttpSession>) servletContext .getAttribute("map" ); map.remove(this ); } }
LoginServlet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 package cn.itcast.servlet; import java.io.IOException;import java.sql.SQLException;import java.util.Map; import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession; import org.apache.commons.dbutils.QueryRunner;import org.apache.commons.dbutils.handlers.BeanHandler; import cn.itcast.domain.User;import cn.itcast.utils.JDBCUtils; public class LoginServlet extends HttpServlet { public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8" ); String username = request.getParameter("username" ); String password = request.getParameter("password" ); String sql = "select * from user where username = ? and password = ?" ; Object[] args = { username, password }; QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource()); try { User user = queryRunner.query(sql, new BeanHandler<User>(User.class), args); if (user == null ) { request.setAttribute("msg" , "用户名或者密码错误!" ); request.getRequestDispatcher("/login.jsp" ).forward(request, response); } else { request.getSession().invalidate(); Map<User, HttpSession> map = (Map<User, HttpSession>) getServletContext() .getAttribute("map" ); for (User hasLoginUser : map.keySet()) { if (hasLoginUser.getUsername().equals(user.getUsername())) { HttpSession hasLoginSession = map.get(hasLoginUser); hasLoginSession.invalidate(); break ; } } request.getSession().setAttribute("user" , user); response.sendRedirect("/day18kick/list.jsp" ); } } catch (SQLException e) { e.printStackTrace(); } } public void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
KickServlet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 package cn.itcast.servlet; import java.io.IOException;import java.util.Map; import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession; import cn.itcast.domain.User; public class KickServlet extends HttpServlet { public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String id = request.getParameter("id" ); Map<User, HttpSession> map = (Map<User, HttpSession>) getServletContext() .getAttribute("map" ); for (User hasLoginUser : map.keySet()) { if (hasLoginUser.getId() == Integer.parseInt(id)) { HttpSession hasLoginSession = map.get(hasLoginUser); hasLoginSession.invalidate(); break ; } } response.sendRedirect("/day18kick/list.jsp" ); } public void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
list.jsp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!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> <h1>在线用户列表</h1> <h2>当前用户 ${user.username }</h2> <!-- 将ServletContext中 map 数据显示出来 --> <c:forEach items="${map}" var ="entry" > <!-- 只有管理员可以踢人 --> <!-- 管理员不能被踢 --> ${entry.key.username } <c:if test="${user.role == 'admin' && entry.key.role != 'admin' }" > <a href="/day18kick/kick?id=${entry.key.id}">踢下线</a> </c:if> <br/> </c:forEach> </body> </html>
案例:服务器启动创建第一个管理员账号 –
不要忘记配置 xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @WebListener public class MyServletContextListener implements ServletContextListener { private IUserService service = new UserServiceImpl(); private IUserDAO dao = new UserDAOImpl(); public void contextInitialized (ServletContextEvent ev) { User u = dao.checkUsername("root" ); if (u == null ) { User user = new User(); user.setName("root" ); user.setPassword("admin" ); service.save(user); } } }