Day21

01-java事件监听机制

监听器

l监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行。
 
在监听器里面就涉及到一个组件,这个组件叫做事件源 ,事件源也叫做被监听对象,想要对这个监听对象监听,开发人员必须写一个监听器,然后将这个编写的监听器
注册到监听对象上去,当这个监听对象被监听器监听之后,当某个哥们对这个事件源操作的时候,比如他调用了事件源的某个方法,或者改变了事件源的属性,当这个事件源
上发生操作,就会立马调用监听器对应的方法响应这个操作,同时在调用监听器的时候的方法的时候,会传递一个事件对象Even过去,这个时间对象里面通常封装了事件源和
动作,在监听器对象响应的方法里程序员拿到响应的事件对象,从而进行一些处理
 
在java事件监听机制中整个过程包含三个部分,事件源,监听对象和事件对象
 
 
 下面我们就用java中监听器典型案例:监听window窗口的事件监听器
 
 /day21/src/cn/itcast/demo/Demo1.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;
    }
    
}

 

 /day21/src/cn/itcast/demo/Demo3.java
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监听器

l在Servlet规范中定义了多种类型的监听器,它们用于监听的事件源分别为 ServletContext, HttpSession 和 ServletRequest 这三个域对象。
lServlet规范针对这三个对象上的操作,又把这多种类型的监听器划分为三种类型。
•监听三个域对象创建和销毁的事件监听器
•监听域对象中属性的增加和删除的事件监听器(也就是向域中保存或者删除数据的监听器)
•监听绑定到 HttpSession 域中的某个对象的状态的事件监听器。(查看Servlet API文档)
 
实现ServletContextListener就可以监听到监听到ServletContext的创建和销毁
 
同样我们可以找到对应的事件对象,通过事件对象我们可以知道到底是那个ServletContext对象创建或者销毁
 
同样我们可以查看到HttpSession的监听器接口,它负责监听session的创建和销毁
同样我们可以看到对应的事件对象
 
 
同样我们可以查看到ServletRequest的监听器
同样也可以看见相应的事件对象
 
以上就是监听三大域的监听器,以上就是第一类监听器,监听三个域对象创建和销毁的事件监听器
***********************************************************************
比如监听ServletContextAttribute中的属性的变化的监听器ServletContextAttributeListener
可以监听到ServletContextAttrubute中的属性的添加,删除以及替换
 
同样我们可以通过它的事件对象获取到那个事件源,以及向这个事件源中存入了数据的名称和值
 
同样的我们可以查看到监听ServletRequest中属性的的变化的监听器ServletRequestAttributeListener
这个监听器可以监听ServletRequest中属性属性的添加,删除以及替换
然后还可以查看到对应的事件对象ServletRequestAttributeEvent,通过这个事件对象可以知道
存入的数据的名称和值,以及获取到事件源ServletRequest或者ServletContext
 
同样我们可以查看到监听HttpSessionAttribute中属性的监听器HttpSessionAttributeListener
这个监听器可以监听到Session域中属性的变化
当然我们也可以查看到对应的事件对象HttpSessionBindingEvent
通过这个事件对象我们可以得到存入的数据的名称和值,还可以得到那个事件源Session等等
 
以上就是Servlet中的第二类监听器,监听域对象中属性的增加和删除的事件监听器
*******************************************************************

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

然后我们还可以查看到HttpSessionActivationListener

这个监听器可以监听到Session的活化和冻化,所谓的活化和冻化就是Session的在内存的中生命时间
我们知道Sission默认30分钟摧毁,而在实际开发中我们可以控制Sission的保存时间,如果在30分钟内
Sission没有人用了,我们就可以将Sission序列化到硬盘中去,这就是所谓的冻化,反过来将Sission从
硬盘中回复到内存中就是活化,那么这个监听器就可以监听到Sission的活化和冻化
 
*****************************************************************************
综上在Servlet规范里面提供了三大类八种监听器,监听javaweb开发中几个域对象
 
下面我们就可以做练习,练习这个几个域监听器,从而明白这几个监听器到底用在那些地方
 
 这里还要注意监听器属于web层,因为它监听Servlet嘛,所在在建包的时候要建立在web包中
 

编写 Servlet 监听器

l和编写其它事件监听器一样,编写servlet监听器也需要实现一个特定的接口,并针对相应动作覆盖接口中的相应方法。
l和其它事件监听器略有不同的是,servlet监听器的注册不是直接注册在事件源上,而是由WEB容器负责注册,开发人员只需在web.xml文件中使用<listener>标签配置好监听器,web容器就会自动把监听器注册到事件源中。
一个 web.xml 文件中可以配置多个 Servlet事件监听器,web 服务器按照它们在 web.xml 文件中的注册顺序来加载和注册这些 Serlvet事件监听器

监听servletContext域对象创建和销毁

lServletContextListener接口用于监听 ServletContext对象的创建和销毁事件。
lServletContext对象被创建时,激发contextInitialized (ServletContextEventsce)方法
lServletContext对象被销毁时,激发contextDestroyed(ServletContextEventsce)方法。
 
l提问,servletContext域对象何时创建和销毁:
•创建:服务器启动针对每一个web应用创建servletcontext
•销毁:服务器关闭前先关闭代表每一个web应用的servletContext
 /day21/src/cn/itcast/web/listener/MyServletContextListener.java
 
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域对象创建和销毁

lHttpSessionListener接口用于监听HttpSession的创建和销毁
l创建一个Session时,sessionCreated(HttpSessionEvent se) 方法将会被调用。
l销毁一个Session时,sessionDestroyed (HttpSessionEvent se) 方法将会被调用。
 
l(此处复习session对象,写多个servlet都去getSession,看session的创建)
lSession域对象创建和销毁的时机创建:用户每一次访问时,服务器创建session
•销毁:如果用户的session 30分钟没有使用,服务器就会销毁session,我们在web.xml里面也可以配置session失效时间

 /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域对象创建和销毁

lServletRequestListener 接口用于监听ServletRequest 对象的创建和销毁。
lRequest 对象被创建时,监听器的requestInitialized方法将会被调用。
lRequest对象被销毁时,监听器的requestDestroyed方法将会被调用。
l
l
l(此处复习request对象,在浏览器窗口中多次刷新访问servlet,看request对象的创建和销毁,并写一个servlet,然后用sendRedirect、forward方式跳转到其它servlet,查看request对象的创建和消耗)
lservletRequest域对象创建和销毁的时机:
•创建:用户每一次访问,都会创建一个reqeust
•销毁:当前访问结束,request对象就会销毁

 

/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监听器在开发中的应用案例

l统计当前在线人数
/day21/src/cn/itcast/web/listener/example/CountNumListener.java
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);
    }

}

 

 /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>
    
  <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扫描器

 我们要自己写一个扫描器扫描内存中的session,如果扫描到那个session在五分钟没有用就将其摧毁
既然我们要自己管理session,我们就必须写一个监听器监听session的创建,如果一个session创建了就将其保存到一个容器里面
如果这里session在30秒后无人使用则就将其从集合中删除,
这里设计到定时器还设计到线程同步的问题
定时器我们可以在JDK中查找到,它有很多中方法,还有自动矫正的定时器
说明:
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方法内部就是写需要执行的任务

 
然后这里的程序还涉及到同步,也就是多个线程操作同一个集合,所以我们需要将集合设置成同步的
在集合帮助类Collections中有方法将一个集合传入,返给你的是一个同步集合
 
 
下面就是代码
/day21/src/cn/itcast/web/listener/example/SessionScanner.java
 
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>

 

 /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>

 ——————————————————————————————————————————————————————————————————————————————————————————————

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

}

 

 /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>
    
  <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规范的其它几种监听器

监听三个域对象属性变化

lServlet规范定义了监听 ServletContext, HttpSession, HttpServletRequest这三个对象中的属性变更信息事件的监听器。
l这三个监听器接口分别是ServletContextAttributeListener, HttpSessionAttributeListenerServletRequestAttributeListener
l这三个接口中都定义了三个方法来处理被监听对象中的属性的增加,删除和替换的事件,同一个事件在这三个接口中对应的方法名称完全相同,只是接受的参数类型不同。 
 
 attributeAdded 方法
l当向被监听器对象中增加一个属性时,web容器就调用事件监听器的 attributeAdded 方法进行相应,这个方法接受一个事件类型的参数,监听器可以通过这个参数来获得正在增加属性的域对象和被保存到域中的属性对象
l各个域属性监听器中的完整语法定义为:
•public void attributeAdded(ServletContextAttributeEvent scae)
•public void attributeAdded(HttpSessionBindingEvent  hsbe)
•public void attributeAdded(ServletRequestAttributeEvent srae)
 
attributeRemoved 方法
l当删除被监听对象中的一个属性时,web 容器调用事件监听器的这个方法进行相应
l各个域属性监听器中的完整语法定义为:
•public void attributeRemoved(ServletContextAttributeEvent scae)
•public void attributeRemoved (HttpSessionBindingEvent  hsbe)
•public void attributeRemoved (ServletRequestAttributeEvent srae)
 
attributeReplaced 方法
l当监听器的域对象中的某个属性被替换时,web容器调用事件监听器的这个方法进行相应
l各个域属性监听器中的完整语法定义为:
•public void attributeReplaced(ServletContextAttributeEvent scae)
•public void attributeReplaced (HttpSessionBindingEvent  hsbe)
•public void attributeReplaced (ServletRequestAttributeEvent srae)
 
 

ServletContextAttributeListene

 这个技术不知道用在什么地方,以后用到报告给方老大
 /day21/src/cn/itcast/web/listener/MyServletContextAttributeListener.java
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>

 

 /day21/WebRoot/index.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 '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

 /day21/src/cn/itcast/web/listener/HttpSessionAndServletRequestAttributeListener.java
 
 
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>

 

 /day21/WebRoot/index.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 '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 绑定的事件监听器

l保存在 Session 域中的对象可以有多种状态:绑定到  Session 中;从 Session 域中解除绑定;随 Session 对象持久化到一个存储设备中;随 Session 对象从一个存储设备中恢复
lServlet 规范中定义了两个特殊的监听器接口来帮助 JavaBean 对象了解自己在 Session 域中的这些状态:HttpSessionBindingListener接口和HttpSessionActivationListener接口 ,实现这两个接口的类不需要 web.xml 文件中进行注册
 

 HttpSessionBindingListener接口

这个接口可以用于统计在线会员数,当有一个人访问则将用户存入到session中

l实现了HttpSessionBindingListener接口的 JavaBean对象可以感知自己被绑定到 Session 中和从 Session 中删除的事件
l当对象被绑定到 HttpSession对象中时,web 服务器调用该对象的  void valueBound(HttpSessionBindingEvent event)方法
l当对象从 HttpSession对象中解除绑定时,web 服务器调用该对象的 void valueUnbound(HttpSessionBindingEvent event)方法
 /day21/src/cn/itcast/domain/User.java
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>

 

 
 之所以User没有在web.xml中注册就可以被调用,原因是在Session的setAttribute方法在判断传递进来的值和键之后会将值存入
 
 
 
 

HttpSessionActivationListener接口

l实现了HttpSessionActivationListener接口的 JavaBean对象可以感知自己被活化和钝化的事件
l当绑定到 HttpSession对象中的对象将要随 HttpSession对象被钝化之前,web 服务器调用如下方法sessionWillPassivate(HttpSessionBindingEvent event) 方法
l当绑定到 HttpSession对象中的对象将要随 HttpSession对象被活化之后,web 服务器调用该对象的 void sessionDidActive(HttpSessionBindingEvent event)方法
 
/day21/src/cn/itcast/domain/MyBean.java
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>

 

/day21/WebRoot/META-INF/context.xml
这个是给服务器配置的一个session管理器,为了就是将session存入到硬盘中
<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>

 

 ______________________________________________________________________________________________________________________________________________
下面就是一个踢人的程序
/day21_kick/src/cn/itcast/domain/User.java
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
        
    }

    

}

 

 /day21_kick/src/cn/itcast/web/servlet/KickServlet.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;
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);
    }

}

 

 /day21_kick/src/cn/itcast/web/servlet/LoginServlet.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;

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>

 

 /day21_kick/WebRoot/listuser.jsp
 
 
<%@ 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>

 

 
 ————————————————————————————————————————————————————————————————————————————————————————————
 
 
 
 
 
 
 
 
 
 
 
 
 
posted @ 2013-11-25 14:21  ysfox  阅读(174)  评论(0)    收藏  举报