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);         }     } }