Day21
01-java事件监听机制
监听器

package cn.itcast.demo; import java.awt.Frame; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; public class Demo1 { public static void main(String[] args) { //这就是一个事件源 Frame f = new Frame(); f.setSize(400,400); f.setVisible(true); //将监听器注册到事件源上 f.addWindowListener(new MyListener()); } } //这个就是事件监听器,各个方法对应的是事件源上相应的操作 //对于想知道每个方法对应事件源上的那个操作我们可以通过查询java文档 class MyListener implements WindowListener{ public void windowActivated(WindowEvent e) { // TODO Auto-generated method stub } public void windowClosed(WindowEvent e) { // TODO Auto-generated method stub } //这个就是当点击关闭按钮对应的方法,这个传递了一个事件对象 public void windowClosing(WindowEvent e) { //通过事件对象拿到事件源 Frame f = (Frame) e.getSource(); //执行关闭 f.dispose(); } public void windowDeactivated(WindowEvent e) { // TODO Auto-generated method stub } //这个是对应最大化窗口的方法 public void windowDeiconified(WindowEvent e) { System.out.println("hahaha!"); } //这个对应事件源上的最小化 //我们这里操作当点击最小化按钮时就出现hahaha public void windowIconified(WindowEvent e) { System.out.println("hahaha!"); } public void windowOpened(WindowEvent e) { // TODO Auto-generated method stub } }
要想知道各个方法对应事件源的什么的操作,我们可以查找java文档


所以在面试的时候会有这样的题目:请描述一下java事件监听机制
首先我们必须描述java事件监听机制中涉及到几个组件,在回答几个组件之间的关系
java的事件监听机制涉及到三个组件:事件源,事件监听器和事件对象,这个三个组件的关系是
当事件源上发生操作时,它会调用事件监听器上响应的方法,并在调用这个方法时,会将事件对象
传递过来,事件监听器由开发人员编写,开发人员在事件监听器中,通过事件对象可以拿到事件源从而对事件源上
的操作处理。
*********************************************************************************
上面的监听的事件源都是SUN公司给我们设计好的,如果我们想要自己设计一个事件源,然后通过监听器监听
这个就是java中著名的观察者模式
/day21/src/cn/itcast/demo/Demo2.java
package cn.itcast.demo; //观察者设计模式(observer设计模式) //我们设计一个人对象,这个人对象能够被监听 //我们设计一个人对象,这个人对象有run和eat两个方法 //我们想要监听器监听这个两个方法 //首先一个对象要被监听就必须先接受一个监听器 //第二点,我们注册了一个监听器之后,这个监听器是由事件源调用的,事件源上发生动作就会调用监听器的方法 //第三点,我们设计的监听器要针对事件源的方法,所以要用接口,也就是说我这个事件源上那些方法想被监听,就 //通过监听接口暴露出来,从而达到被监听 ,只要我们去实现这个监听器接口就可以创建一个监听器 class Person{ //定义一个变量记录住监听器,以方便在事件源中调用监听器 private PersonListener listener; //这个人要想被监听就必须注册一个监听器 public void registerListener(PersonListener listener){ this.listener = listener; } public void run(){ //在执行这个run方法之前判断一下是否传递监听器,如果有监听器就先执行监听器中的方法 //另外还要注意,在监听机制中涉及到三个对象,事件源,事件对象和监听器,这里已经有了事件源和监听器 //我们这里就需要通过监听器的方法传递一个事件对象进去 if(listener!=null){ //在执行监听器方法之前先将事件对象准备好,事件对象将Person这个对象封装,也就是this Even even = new Even(this); this.listener.dorun(even); } //run方法中原来的代码 System.out.println("run!"); } public void eat(){ //在执行这个eat方法之前判断一下是否传递监听器,如果有监听器就先执行监听器中的方法 if(listener!=null){ Even e = new Even(this); this.listener.doeat(e); } //eat方法中原来的代码 System.out.println("eat!"); } } //监听器接口 interface PersonListener{ public void dorun(Even even); public void doeat(Even even); } //事件对象 //事件对象主要是用来封装事件源,所以这里的事件对象是对Person这个对象进行封装的 class Even{ private Person person; public Even() { super(); // TODO Auto-generated constructor stub } public Even(Person person) { super(); this.person = person; } public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } }
package cn.itcast.demo; //这边就测试监听Person public class Demo3 { public static void main(String[] args){ Person p = new Person(); p.registerListener(new MyListener1()); p.eat(); p.run(); } } class MyListener1 implements PersonListener{ public void doeat(Even even){ System.out.println(even.getPerson()+"吃起来"); } public void dorun(Even even){ System.out.println(even.getPerson()+"跑起来"); } }
观察者模式在点餐系统中可以很好的使用,假如有100张桌子共享一个电脑,电脑负责打印某张桌子的点餐,这个时候就可以做成监听模式
某个桌子点了餐,应该将点的菜保存到一个容器中,这个容器要同步,打印机每次从容器取出一条打印,也就是说我们在设计这个系统的时候,
要考虑两点,一是同步的问题,二是事件监听,100张桌子想容器中保存点的菜,电脑负责监听容器里是否有点的菜,如果容器中有点的彩就打印
然后交给厨房做菜
02-servlet监听三个域创建和销毁的监听器
Servle监听器




















然后我还可以查看到HttpSessionBindingListener,这个监听器是用来监听绑定到Session中对象的监听器

然后我们还可以查看到HttpSessionActivationListener


编写 Servlet 监听器
监听servletContext域对象创建和销毁
package cn.itcast.web.listener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; //这里我们创建了一个监听器,以前我们将监听器注册到事件源上是直接通过调用事件源的方法的 //现在这里我们却不能这么做了,我们现在必须将这个监听器告诉TomCat,TomCat会自动帮我们注册 //而凡是涉及到web资源的 配置,我们就找web.xml public class MyServletContextListener implements ServletContextListener { public void contextInitialized(ServletContextEvent arg0) { //当这个web应用一发布到服务器中,服务器启动时就会针对每个web应用产生ServletContext,在产生ServletContext //之前就会执行下面这段代码,也就是说在服务器启动的时候就会看见这句话的输出 System.out.println("ServletContext被创建了!"); } public void contextDestroyed(ServletContextEvent arg0) { //当服务器停掉的时候就会执行这句话 System.out.println("ServletContext被销毁了!"); } //我们可以这样理解监听ServletContext的创建和销毁实际上就相当于监听到web应用的启动和销毁 //如果有时候我们希望在web应用一初始化就执行一些资源,我们可以将初始化的代码写到contextInitialized这个方法中 //当web应用一启动就初始化了资源,比如后面会介绍的到定时器,我们希望在web应用一启动的时候就启动一些定时器去定时 //执行一些任务,所以我们可以将定时器的代码写到contextInitialized这个方法里面就可以了,还有就是我们稍后要学习的 //spring,我们希望在web应用一启动就希望这个spring框架启动起来,于是我们可以将spring的启动代码写到这个contextInitialized //方法里面,所以spring的作者就写好了这样的监听器,我们只需要在web.xml中将这个监听器配置就可以启动spring }
/day21/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- 这里告诉TomCat事件监听器,TomCat会自动将监听器注册到ServletContext上去 --> <listener> <listener-class>cn.itcast.web.listener.MyServletContextListener</listener-class> </listener> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
监听HttpSession域对象创建和销毁
/day21/src/cn/itcast/web/listener/MyServletContextListener.java
package cn.itcast.web.listener; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; //同样创建Session监听器也需要将监听器注册,这里我们只需要将监听器写入到web.xml中 //TomCat就会自动帮你完成注册 public class MyHttpSessionListener implements HttpSessionListener { //当用户访问index.jsp,jsp最终会翻译成servlet,翻译后的servlet默认会创建八大隐式对象,如果是直接访问的servlet,如果servlet中没有getSession()则也是不会出现下面这句话的 //如果你不想它自动创建八大隐式对象,这需要在jsp页面开头将session="false"添上 //<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1" session="false" %> //当用户一访问index.jsp,就产生了八大隐式对象,其中就包括Session,所以下面这句话就会打印 //当我把cookie禁用了,此时访问index.jsp必须是这样http://127.0.0.1:8080/day21/index.jsp //由于访问时没有带session的id所以服务器认为是另一个新的用户来了就会不断的产生新的Session,于是 //我们每次刷新都会出现下面这句话 public void sessionCreated(HttpSessionEvent arg0) { System.out.println("Session被创建了!"); } //由于session一旦被创建就会在服务器中保存30分钟,所以当关闭浏览器是看不见这句话的 public void sessionDestroyed(HttpSessionEvent arg0) { System.out.println("Session被销毁了!"); } }
/day21/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- 这里告诉TomCat事件监听器,TomCat会自动将监听器注册到ServletContext上去 <listener> <listener-class>cn.itcast.web.listener.MyServletContextListener</listener-class> </listener> --> <listener> <listener-class>cn.itcast.web.listener.MyHttpSessionListener</listener-class> </listener> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ServletDemo1</servlet-name> <servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class> </servlet> <!-- 这里表示设置session保存时间 为1分钟--> <session-config> <session-timeout>1</session-timeout> </session-config> <servlet-mapping> <servlet-name>ServletDemo1</servlet-name> <url-pattern>/servlet/ServletDemo1</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
/day21/WebRoot/index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> This is my JSP page. <br> </body> </html>
/day21/src/cn/itcast/web/servlet/ServletDemo1.java
package cn.itcast.web.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletDemo1 extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); } }
这个可以用于统计当前在线人数,一般每个用户都会开一个浏览器访问服务器,在服务器中产生一个session,我们就可以通过MyHttpSessionListener这个监听器监听session的创建
一旦创建一个session,就会将变量加1,这样就可以统计在线人数了,而一个session销毁就变量减1,但是这个值并不准,应为session要在30分钟之后才摧毁的,但是这里要区分
在线人数和在线用户,在线用户是根据登陆就加1,这个在线用户很准确。
监听HttpRequest域对象创建和销毁
/day21/src/cn/itcast/web/listener/MyServletRequstListener.java
package cn.itcast.web.listener; import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; //这个监听器监听Request,一旦有请求就会被监听,由于Request命很短,所以在一刷新就会将Request的创建和销毁监听到 //所以在刷新的时候就会同事出现下面两句话 //这个技术在开发中可以用来做网站访问统计,统计到每个小时,每天的访问量,而且我们可以得到方位地址,还可以 //得到访问的浏览器是什么类型的 public class MyServletRequstListener implements ServletRequestListener { public void requestDestroyed(ServletRequestEvent sre) { System.out.println("Request被销毁!"); //获取到请求地址 sre.getServletRequest().getRemoteAddr(); } public void requestInitialized(ServletRequestEvent sre) { System.out.println("Request被创建!"); } }
/day21/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- 这里告诉TomCat事件监听器,TomCat会自动将监听器注册到ServletContext上去 <listener> <listener-class>cn.itcast.web.listener.MyServletContextListener</listener-class> </listener> --> <listener> <listener-class>cn.itcast.web.listener.MyHttpSessionListener</listener-class> </listener> <listener> <listener-class>cn.itcast.web.listener.MyServletRequstListener</listener-class> </listener> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ServletDemo1</servlet-name> <servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class> </servlet> <!-- 这里表示设置session保存时间 为1分钟--> <session-config> <session-timeout>1</session-timeout> </session-config> <servlet-mapping> <servlet-name>ServletDemo1</servlet-name> <url-pattern>/servlet/ServletDemo1</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
————————————————————————————————————————————————————————————————————————————————————————————
03-统计当前在线用户
Servlet监听器在开发中的应用案例
package cn.itcast.web.listener.example; import javax.servlet.ServletContext; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; //这个就是统计当前在线人数的程序,这个统计只能大概统计,不能精确统计, //应为Session在30分钟有效,而且当用户开启多个浏览器访问时也会产生多个Session //这里通过事件对象获取到ServletContext,然后获取到ServletContext中的count, //如果没有就创建一个,当某个人访问网站则会产生一个Session,这个时候监听器就会监听到就将count加1, //然后存入到ServletContext中,当某个用户关闭浏览器,则监听器同样监听到则会将count减去1存入到ServletContext public class CountNumListener implements HttpSessionListener { public void sessionCreated(HttpSessionEvent se) { ServletContext sc = se.getSession().getServletContext(); Integer count = (Integer) sc.getAttribute("count"); if(count==null){ count = 1; sc.setAttribute("count", count); }else{ count++; sc.setAttribute("count", count); } } public void sessionDestroyed(HttpSessionEvent se) { ServletContext sc = se.getSession().getServletContext(); Integer count = (Integer) sc.getAttribute("count"); count--; sc.setAttribute("count", count); } }
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- 这里告诉TomCat事件监听器,TomCat会自动将监听器注册到ServletContext上去 <listener> <listener-class>cn.itcast.web.listener.MyServletContextListener</listener-class> </listener> --> <listener> <listener-class>cn.itcast.web.listener.MyHttpSessionListener</listener-class> </listener> <listener> <listener-class>cn.itcast.web.listener.MyServletRequstListener</listener-class> </listener> <listener> <listener-class>cn.itcast.web.listener.example.CountNumListener</listener-class> </listener> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ServletDemo1</servlet-name> <servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class> </servlet> <!-- 这里表示设置session保存时间 为1分钟--> <session-config> <session-timeout>1</session-timeout> </session-config> <servlet-mapping> <servlet-name>ServletDemo1</servlet-name> <url-pattern>/servlet/ServletDemo1</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
/day21/WebRoot/index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> </head> <body> <!-- applicationScope就是ServletContext域,这里就是获取ServletContext域中的count --> 当前在线人数${applicationScope.count}人 </body> </html>
04-自定义session扫描器


public void schedule(TimerTask task,Date time) //这个方法表示在指定的时间去执行任务
public void schedule(TimerTask task,Date firstTime,long period) //这个表示在指定的时间第一次执行任务,然后每经过多少事件执行一次任务
public void schedule(TimerTask task,long delay) //这个表示延迟多少时间去执行任务
public void schedule(TimerTask task,long delay,long period) //这个表示延迟多少时间,然后每隔多少时间去执行一次任务
public void scheduleAtFixedRate(TimerTask task,Date firstTime,long period) //这个是带自动矫正的定时器,因为在在线程中第一次执行任务的时候,CPU没有及时的跳转过来执行定时器,这个方法就可以矫正时间差
public void scheduleAtFixedRate(TimerTask task,long delay,long period) //这个也是到自动矫正的定时器
接着是任务这个类,这个类是一个抽象类,它的run()方法是一个抽象类,需要重写,这个run方法内部就是写需要执行的任务




package cn.itcast.web.listener.example; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Timer; import java.util.TimerTask; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; //这里我们要做一个扫描器,定时扫描Session,如果Session30秒内没有被用就将其摧毁 //这里我们要管理Session就得到它,并将它存入到一个集合中,又因为这里集合设计增删 //所以我们需用LinkedList, //然后我们要定义一个定时器,由于定时器要在web应用一启动就去执行,所以我们将它放在 //监听ServletContext建立的方法,也就相当于服务器一启动就会执行定时器 public class SessionScanner implements HttpSessionListener, ServletContextListener { //由于有多个用户公用这个里集合,要保证线程同步必须将这个list集合整成同步的, //在集合帮助类Collections中有个方法synchronizedList(List list),只要传递给它 //一个集合,就会给你返回一个同步的集合 List<HttpSession> list = Collections.synchronizedList(new LinkedList<HttpSession>()); //定义一个旗标锁 Object lock = new Object(); public void contextInitialized(ServletContextEvent arg0) { Timer timer = new Timer(); //定时器,从0秒开始后每30秒检查一次 //这里需要传递一个旗标锁,方便在myTask中用 timer.schedule(new myTask(list,lock), 0, 30*1000); } public void sessionCreated(HttpSessionEvent hse) { HttpSession session = hse.getSession(); //这里想集合中添加session时也需要保证线程同步,因为假如当定时器在扫描集合中的session时 //恰好这时有用户访问,则会在扫描器操作集合的同时想集合存session,这也会导致报线程并发修改异常 //所以我们需要将向list集合中添加session和扫描集合中的session做成同步线程,共享一个集合 //当扫描器在扫描集合中的session时,用户不能向集合中存入session,当用户在向list中存入 //session时,同样扫描器也不能扫描集合,所以我们这里需要提供一个旗标锁,来同步这两个地方 synchronized(lock){ list.add(session); System.out.println("Session创建添加成功!"); } } public void sessionDestroyed(HttpSessionEvent hse) { System.out.println("Session销毁成功!"); } public void contextDestroyed(ServletContextEvent arg0) { } } class myTask extends TimerTask{ private List<HttpSession> list; private Object lock; public myTask(List<HttpSession> list,Object ob) { super(); this.list = list; this.lock = ob; } public void run() { //这里扫描器扫描集合和用户添加session到集合要同步 synchronized(this.lock){ System.out.println("扫描器开始执行!"); //这里必须要用listIterator,这样才能在迭代中删除集合中的元素,如果用的是iterator则会报线程并发修改异常 ListIterator li =list.listIterator(); while(li.hasNext()){ HttpSession session = (HttpSession) li.next(); //这里表示如果Session的时间超过30秒没有人用则销毁 if((System.currentTimeMillis()-session.getLastAccessedTime())>30*1000){ li.remove(); } } } } }
/day21/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- 这里告诉TomCat事件监听器,TomCat会自动将监听器注册到ServletContext上去 <listener> <listener-class>cn.itcast.web.listener.MyServletContextListener</listener-class> </listener> --> <!-- <listener> <listener-class>cn.itcast.web.listener.MyHttpSessionListener</listener-class> </listener> <listener> <listener-class>cn.itcast.web.listener.MyServletRequstListener</listener-class> </listener> <listener> <listener-class>cn.itcast.web.listener.example.CountNumListener</listener-class> </listener> --> <listener> <listener-class>cn.itcast.web.listener.example.SessionScanner</listener-class> </listener> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ServletDemo1</servlet-name> <servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class> </servlet> <!-- 这里表示设置session保存时间 为1分钟--> <session-config> <session-timeout>1</session-timeout> </session-config> <servlet-mapping> <servlet-name>ServletDemo1</servlet-name> <url-pattern>/servlet/ServletDemo1</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> </head> <body> <!-- applicationScope就是ServletContext域,这里就是获取ServletContext域中的count --> 当前在线人数${applicationScope.count}人 </body> </html>
——————————————————————————————————————————————————————————————————————————————————————————————
05-定时发邮件
/day21/src/cn/itcast/web/listener/example/SessionScanner.java
package cn.itcast.web.listener.example; import java.util.Calendar; import java.util.Timer; import java.util.TimerTask; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; //这个程序是写一个定时器来发送邮件,比如定时到午夜12:00:00发邮件给某某人 //但是注意的是这个程序在实际开发中并不能用,因为涉及到要重启服务器,这个是不允许了,所以 //在实际开发中实际的做法是在数据库中创建任务表,并在网站启动时就创建一个定时扫描器,每隔一段时间扫描 //数据库中的任务表,当任务表中有任务时就执行,我们只需要在数据库中添加任务就可以了 public class SendMailTimer implements ServletContextListener { public void contextInitialized(ServletContextEvent sce) { //定义一个定时器 Timer timer = new Timer(); //定义一个具体时间,当我们去查找Date的时,发现它创建一个具体时间的构造方法已经过时了, //被Calendar代替了,我们需要获取到Calendar的实例,通过它是set方法设置一个具体时间 //由于Calendar的构造方法是protected,只有在本类或者同一个包中可以使用,所以 //这里想获取到它的实例就只能用getInstance()方法,然后通过它的set方法设置一个具体时间 Calendar time = Calendar.getInstance(); time.set(2013, 10, 26, 15, 17, 00); timer.schedule(new TimerTask(){ public void run() { System.out.println("执行发邮件!"); } //这里需要一个Date,所以将time转成Date }, time.getTime()); } public void contextDestroyed(ServletContextEvent sce) { } }
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- 这里告诉TomCat事件监听器,TomCat会自动将监听器注册到ServletContext上去 <listener> <listener-class>cn.itcast.web.listener.MyServletContextListener</listener-class> </listener> --> <!-- <listener> <listener-class>cn.itcast.web.listener.MyHttpSessionListener</listener-class> </listener> <listener> <listener-class>cn.itcast.web.listener.MyServletRequstListener</listener-class> </listener> <listener> <listener-class>cn.itcast.web.listener.example.CountNumListener</listener-class> </listener> <listener> <listener-class>cn.itcast.web.listener.example.SessionScanner</listener-class> </listener> --> <listener> <listener-class>cn.itcast.web.listener.example.SendMailTimer</listener-class> </listener> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ServletDemo1</servlet-name> <servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class> </servlet> <!-- 这里表示设置session保存时间 为1分钟--> <session-config> <session-timeout>1</session-timeout> </session-config> <servlet-mapping> <servlet-name>ServletDemo1</servlet-name> <url-pattern>/servlet/ServletDemo1</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
当我们想设置一个具体的时间时,我们去查找Date这个类,返现设置具体时间的方法已经过时,被Calendar代替了

于是我们找到Calendar,发现它的构造方法趋势受保护的,只有本类和一个包中的类可以使用,要想得到它的实例只能通过
它的方法getInstance()获取


获取到Calendar对象之后我们可以通过它的set方法设置一个具体的时间

———————————————————————————————————————————————————————————————————————————————————————————
06-servlet规范的其它几种监听器
监听三个域对象属性变化
ServletContextAttributeListene
package cn.itcast.web.listener; import javax.servlet.ServletContextAttributeEvent; import javax.servlet.ServletContextAttributeListener; public class MyServletContextAttributeListener implements ServletContextAttributeListener { public void attributeAdded(ServletContextAttributeEvent sca) { System.out.println("向ServletContext中存入了:"+sca.getName()+"值为:"+sca.getValue()); } public void attributeRemoved(ServletContextAttributeEvent sca) { System.out.println("从ServletContext中删除了:"+sca.getName()); } public void attributeReplaced(ServletContextAttributeEvent sca) { System.out.println("ServletContext中的"+sca.getName()+"替换成了"+sca.getValue()); } }
/day21/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- 这里告诉TomCat事件监听器,TomCat会自动将监听器注册到ServletContext上去 <listener> <listener-class>cn.itcast.web.listener.MyServletContextListener</listener-class> </listener> --> <!-- <listener> <listener-class>cn.itcast.web.listener.MyHttpSessionListener</listener-class> </listener> <listener> <listener-class>cn.itcast.web.listener.MyServletRequstListener</listener-class> </listener> <listener> <listener-class>cn.itcast.web.listener.example.CountNumListener</listener-class> </listener> <listener> <listener-class>cn.itcast.web.listener.example.SessionScanner</listener-class> </listener> <listener> <listener-class>cn.itcast.web.listener.example.SendMailTimer</listener-class> </listener> --> <listener> <listener-class>cn.itcast.web.listener.MyServletContextAttributeListener</listener-class> </listener> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ServletDemo1</servlet-name> <servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class> </servlet> <!-- 这里表示设置session保存时间 为1分钟--> <session-config> <session-timeout>1</session-timeout> </session-config> <servlet-mapping> <servlet-name>ServletDemo1</servlet-name> <url-pattern>/servlet/ServletDemo1</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'index.jsp' starting page</title> </head> <body> <!-- applicationScope就是ServletContext域,这里就是获取ServletContext域中的count 当前在线人数${applicationScope.count}人 --> <% application.setAttribute("name","张三"); application.setAttribute("name","李四"); application.removeAttribute("name"); %> </body> </html>
HttpSessionAttributeListener
ServletRequestAttributeListener
package cn.itcast.web.listener; import javax.servlet.ServletRequestAttributeEvent; import javax.servlet.ServletRequestAttributeListener; import javax.servlet.http.HttpSessionAttributeListener; import javax.servlet.http.HttpSessionBindingEvent; //注意这个类同事实现了两个接口ServletRequestAttributeListener和HttpSessionAttributeListener //一个是向ServletRequest中存入删除和替换数据,另一个是想HttpSession中存入,删除和替换数据 //这里的监听session中的值有些用,可以显示当前登陆用户,其实每个用户登陆就是向session中加一个user //我们可以在后天显示登陆的用户T人,监听request元素的不知道有什么用,有还是要给方老大报告 public class HttpSessionAndServletRequestAttributeListener implements HttpSessionAttributeListener,ServletRequestAttributeListener { public void attributeAdded(HttpSessionBindingEvent se) { System.out.println("向session中加入了数据!"); } public void attributeRemoved(HttpSessionBindingEvent se) { System.out.println("向session中删除了东西!"); } public void attributeReplaced(HttpSessionBindingEvent se) { System.out.println("把session中的属性替换了!"); } public void attributeAdded(ServletRequestAttributeEvent srae) { System.out.println("向request中加入了数据!"); } public void attributeRemoved(ServletRequestAttributeEvent srae) { System.out.println("向session中删除了东西!"); } public void attributeReplaced(ServletRequestAttributeEvent srae) { System.out.println("把session中的属性替换了!"); } }
/day21/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- 这里告诉TomCat事件监听器,TomCat会自动将监听器注册到ServletContext上去 <listener> <listener-class>cn.itcast.web.listener.MyServletContextListener</listener-class> </listener> --> <!-- <listener> <listener-class>cn.itcast.web.listener.MyHttpSessionListener</listener-class> </listener> <listener> <listener-class>cn.itcast.web.listener.MyServletRequstListener</listener-class> </listener> <listener> <listener-class>cn.itcast.web.listener.example.CountNumListener</listener-class> </listener> <listener> <listener-class>cn.itcast.web.listener.example.SessionScanner</listener-class> </listener> <listener> <listener-class>cn.itcast.web.listener.example.SendMailTimer</listener-class> </listener> <listener> <listener-class>cn.itcast.web.listener.MyServletContextAttributeListener</listener-class> </listener> --> <listener> <listener-class>cn.itcast.web.listener.HttpSessionAndServletRequestAttributeListener</listener-class> </listener> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ServletDemo1</servlet-name> <servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class> </servlet> <!-- 这里表示设置session保存时间 为1分钟--> <session-config> <session-timeout>1</session-timeout> </session-config> <servlet-mapping> <servlet-name>ServletDemo1</servlet-name> <url-pattern>/servlet/ServletDemo1</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'index.jsp' starting page</title> </head> <body> <!-- applicationScope就是ServletContext域,这里就是获取ServletContext域中的count 当前在线人数${applicationScope.count}人 --> <% session.setAttribute("name","张三"); session.setAttribute("name","李四"); session.removeAttribute("name"); request.setAttribute("user","aaa"); request.setAttribute("user","bbb"); request.removeAttribute("user"); %> </body> </html>
感知 Session 绑定的事件监听器
HttpSessionBindingListener接口
这个接口可以用于统计在线会员数,当有一个人访问则将用户存入到session中
package cn.itcast.domain; import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionBindingListener; //注意,这个HttpSessionBindingListener不需要在web.xml中注册 //因为这个User即是监听器又是事件源 public class User implements HttpSessionBindingListener { public void valueBound(HttpSessionBindingEvent arg0) { System.out.println("User对象被绑定到Session中"); } public void valueUnbound(HttpSessionBindingEvent arg0) { System.out.println("User对象从Session中解除"); } }
/day21/WebRoot/index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %> <%@page import="cn.itcast.domain.User"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'index.jsp' starting page</title> </head> <body> <!-- applicationScope就是ServletContext域,这里就是获取ServletContext域中的count 当前在线人数${applicationScope.count}人 --> <% /*session.setAttribute("name","张三"); session.setAttribute("name","李四"); session.removeAttribute("name"); request.setAttribute("user","aaa"); request.setAttribute("user","bbb"); request.removeAttribute("user"); */ session.setAttribute("user",new User()); session.removeAttribute("user"); %> </body> </html>

HttpSessionActivationListener接口
package cn.itcast.domain; import java.io.Serializable; import javax.servlet.http.HttpSessionActivationListener; import javax.servlet.http.HttpSessionEvent; //由于这个MyBean对象会随着Session存储到硬盘当中去,所以它必须实现序列化接口,不然不能存入到的硬盘中 public class MyBean implements HttpSessionActivationListener,Serializable { //活化方法 public void sessionDidActivate(HttpSessionEvent arg0) { System.out.println("javabean随着session从硬盘回到内存了"); } //钝化方法 public void sessionWillPassivate(HttpSessionEvent arg0) { System.out.println("javabean随着session到硬盘中去了"); } }
/day21/WebRoot/index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %> <%@page import="cn.itcast.domain.User"%> <%@page import="cn.itcast.domain.MyBean"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'index.jsp' starting page</title> </head> <body> <!-- applicationScope就是ServletContext域,这里就是获取ServletContext域中的count 当前在线人数${applicationScope.count}人 --> <% /*session.setAttribute("name","张三"); session.setAttribute("name","李四"); session.removeAttribute("name"); request.setAttribute("user","aaa"); request.setAttribute("user","bbb"); request.removeAttribute("user"); */ //session.setAttribute("user",new User()); //session.removeAttribute("user"); session.setAttribute("bean",new MyBean()); %> </body> </html>
<Context> <!-- 下面这句话表示为session配置一个管理器PersistentManager,这个session管理器的最大空闲事件是1分钟 当这个session一分钟没有用的话就使用这个FileStore文件存储类将session存入到it315的文件上去 --> <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1"> <Store className="org.apache.catalina.session.FileStore" directory="it315"/> </Manager> </Context>
package cn.itcast.domain; public class User { private String username; private String password; 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; } }
/day21_kick/src/cn/itcast/web/listener/UserListener.java
package cn.itcast.web.listener; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpSessionAttributeListener; import javax.servlet.http.HttpSessionBindingEvent; import cn.itcast.domain.User; public class UserListener implements HttpSessionAttributeListener { public void attributeAdded(HttpSessionBindingEvent se) { Map map = (Map) se.getSession().getServletContext().getAttribute("map"); if(map==null){ map = new HashMap(); se.getSession().getServletContext().setAttribute("map", map); } Object object = se.getValue(); if(object instanceof User){ User user = (User) object; map.put(user.getUsername(), se.getSession()); } } public void attributeRemoved(HttpSessionBindingEvent se) { // TODO Auto-generated method stub } public void attributeReplaced(HttpSessionBindingEvent se) { // TODO Auto-generated method stub } }
package cn.itcast.web.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; public class KickServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); username = new String(username.getBytes("iso8859-1"),"UTF-8"); Map map = (Map) this.getServletContext().getAttribute("map"); HttpSession session = (HttpSession) map.get(username); if(session!=null){ session.invalidate(); map.remove(username); } response.sendRedirect("/day21_kick/listuser.jsp"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
/day21_kick/src/cn/itcast/web/servlet/ListUserServlet.java
package cn.itcast.web.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; public class ListUserServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getRequestDispatcher("/listuser.jsp").forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
package cn.itcast.web.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 cn.itcast.domain.User; 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"); User user = new User(); user.setPassword(password); user.setUsername(username); request.getSession().setAttribute("user", user); response.sendRedirect("/day21_kick/index.jsp"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
/day21_kick/WebRoot/index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <html> <head> <title>My JSP 'index.jsp' starting page</title> </head> <body> 欢迎您:${user.username } </body> </html>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'listuser.jsp' starting page</title> </head> <body> 所有登陆用户为:<br/> <c:forEach var="entry" items="${applicationScope.map}"> <c:url var="url" value="/servlet/KickServlet"> <c:param name="username" value="${entry.key}"></c:param> </c:url> ${entry.key } <a href="${url }">踢死你</a><br/> </c:forEach> </body> </html>(
/day21_kick/WebRoot/login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'login.jsp' starting page</title> </head> <body> <form action="${pageContext.request.contextPath }/servlet/LoginServlet" method="post"> 用户名:<input type="text" name="username"><br/> 密码:<input type="password" name="password"><br/> <input type="submit" value="登陆"> </form> </body> </html>

浙公网安备 33010602011771号