JavaWeb-Listener

话说:

亲们!又见面了!前面总结了Servlet、Filter;这里为保持一贯性,自然少不了Listener。
这里内容稍微有点多,但是也不便分开来写,所以就辛苦读者,也辛苦自己了。

目录:


案例一、感性认识一下什么是监听器
案例二、测试HttpSessionListener
案例三、测试HttpSessionBindingListener
案例四、测试ServletContextListener
案例五、测试ServletContextAttributeListener
案例六、测试HttpSessionActivationListener


案例一、感性认识一下什么是监听器

先看一下整体工程架构图吧,读者如果有耐心看完,请把每一个案例对照这个图来创建:

JavaWeb-Listener_第1张图片

我们用Java写一个窗口,对窗口操作,Window的监听器就会监听到

TestFrame.

package com.hmc.listener;
import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

/**
 * User:Meice
 * 2017/10/7
 */
public class TestFrame {
    public static void main(String[] args) {
        //创建一个窗体对象,对监听器有个感性的认知
       Frame frame = new Frame();
       frame.setTitle("Meice的窗口");
       frame.setSize(300,300);
       frame.setLocation(200,200);
       frame.setVisible(true);

       //要想监听到我们对窗口的事件(操作),需要这样一个对象,以下创建的是匿名对象,所以至直接重写了方法
        frame.addWindowListener(new WindowListener() {
            @Override
            public void windowOpened(WindowEvent e) {
                System.out.println("窗口打开了....");
            }

            @Override
            public void windowClosing(WindowEvent e) {
                System.out.println("窗口正在关闭....");
                //窗口直接无法关闭,只有关闭猫
                //用事件源来关闭
             Frame f =(Frame) e.getSource();
             f.dispose();
            }

            @Override
            public void windowClosed(WindowEvent e) {
                System.out.println("窗口关闭了....");
            }

            @Override
            public void windowIconified(WindowEvent e) {
                //iconify   n. 图符化;图标化
                System.out.println("窗口最小化了....");
            }

            @Override
            public void windowDeiconified(WindowEvent e) {
                System.out.println("窗口最大化了....");
            }

            @Override
            public void windowActivated(WindowEvent e) {
                System.out.println("窗口处于激活状态....");
            }

            @Override
            public void windowDeactivated(WindowEvent e) {
                System.out.println("窗口未处于激活状态....");
            }
        });


    }

}

效果是这样的:

JavaWeb-Listener_第2张图片

Java的事件机制这篇博客可以参考
http://blog.csdn.net/crazysusu/article/details/50731991

案例二、测试HttpSessionListene


1) 如何创建呢?跟Servlet、Filter类似,先创建一个类,实现HttpSessionListener接口
2)配置web.xml,然后访问页面即可。
3)这里的页面,我们就直接用index.jsp做测试
后面的几个案例创建流程都和这个类似,不在赘述。


1) 如何创建呢?跟Servlet、Filter类似,先创建一个类,实现HttpSessionListener接口

package com.hmc.listener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * User:Meice
 * 2017/10/7
 */
public class TestHttpSessionListener implements HttpSessionListener {


    @Override
    public void sessionCreated(HttpSessionEvent e) {
        HttpSession session = e.getSession();
        System.out.println("session创建了,sessionID为:"+session.getId());

    }

    @Override
    public void sessionDestroyed(HttpSessionEvent e) {

        System.out.println("session已销毁....");
    }
}

2)配置web.xml,然后访问页面即可。


<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    
    <listener>
        <listener-class> com.hmc.listener.TestHttpSessionListenerlistener-class>
    listener>
    
    
    <session-config>
        <session-timeout>1session-timeout>
    session-config>
web-app>

3)index.jsp:

<%--
  User: Meice
  Date: 2017/10/7
  Time: 15:40
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$title>
  head>
  <body>
  我是JavaWeb_Listener
  <%--
    这里也完全符合session的工作原理。同义词会话中,之创建一个sessionID,关掉会话,不会自动销毁
    前面说过,销毁session有2中方法,这里采用第2中sesssion.invalidat()
    这样,关闭整个浏览器,就会答应输出session销毁这句话了
  --%>
  <%
      session.invalidate();
  %>

  body>
html>

测试后,页面输出效果如图:

JavaWeb-Listener_第3张图片

总结:


1、销毁一个session有两种方法,法1:调用session.invalidate()方法
法2:设置session-timeout,原谅俺不能写尖括号,页面不支持;
2、关闭页面不会自动销毁session,而需要通过以上两种方法来销毁。
3、HttpSessionListener监听的是整个Web应用(也就是你web工程)下的所有sessiion,web下面的其他页面也都是可以监听到的。


案例三、测试HttpSessionBindingListener

为什么要测试它?因为它和HttpSessionListener不同啊!想一想,这个HttpSessionListener监听了全局的sesssion,实际运用中,当然要精细化操作,我们怎么实现对我想要监听的页面来监听呢?或者选择我要监听的部分来监听呢?监听所有,累不累啊?
HttpSessionBindingListener是一个接口,当然也要实现其中方法,只有两个方法。
HttpSessionBindingListener必须实例化后javaBean放入某一个session中,才能监听。
这句话要好好体会,表示你要写一个类,这里我们写User类,然后实现这个接口并实现其中的方法,同时要实例化这个类,并且把这个类存放到session中。还是不明白?ok,实践出真知。

1)创建一个User类,实现这个BindingListener借口

package com.hmc.listener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;

/**
 * User:Meice
 * 2017/10/7
 */
public class User implements HttpSessionBindingListener {
    private String name;
    public User(){}
    public  User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void valueBound(HttpSessionBindingEvent httpSessionBindingEvent) {

        System.out.println("加入了一个用户:"+name);
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) {

        System.out.println(name+"用户离开了....");
    }


}

2)配置web.xml

 
    
    

认真想一想,这个是没必要配置的。因为我们在访问UserCont.jsp的时候,该页面已经实例化这个类了,而且存放到了session中.Listener配置web.xml的本质意义在哪里?不就是找到这个类,后台给你存到session中,然后调用其中的方法?

3)写页面UserCount.jsp做测试

<%@ page import="com.hmc.listener.User" %><%--
  User: Meice
  Date: 2017/10/7
  Time: 18:08
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Titletitle>
head>
<body>
    <%
        User user = new User("宝玉哥哥");
        session.setAttribute("user",user);
    %>
body>
html>

ok!开始测试。当你一访问页面UserCount.jsp的时候,就调用了这个session,自然就执行了其中的方法。结果如下:


session创建了,sessionID为:BEA668C14C7A044A4516CB9656259A98
加入了一个用户:宝玉哥哥
session已销毁….
宝玉哥哥用户离开了….


到这里,我们就可以精细化根据不同的Listener来设计监听页面访问人数啦。也就是大数据相关的类似PV、UV的东东。

案例四、测试ServletContextListener

ServletContext表示的就是服务器,还记得之前的request.getContextPath()方法嘛?获取的就是上下文,也就是我们建立的Web工程的路径呢。对应这个工程就是”/JavaWeb_Listener”这个路径。所以这里针对的就是JSP的内置对象application
因此,只有整个服务器启动或者关闭的时候,才会调用这个session,对吧!

1) 编写类TestServletContextListener,实现ServletContextListener接口

package com.hmc.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
 * User:Meice
 * 2017/10/7
 */
public class TestServletContextListener implements ServletContextListener {
    /**
     *
     *在应用服务器启动时
     */

    @Override
    public void contextInitialized(ServletContextEvent e) {
        System.out.println("初始化application.....");
    }
    /**
     * 在应用服务器停止的时候
     *
     */
    @Override
    public void contextDestroyed(ServletContextEvent e) {
        System.out.println("销毁application。。。。。");

    }
}

2)配置web.xml


    <listener>
        <listener-class>com.hmc.listener.TestServletContextListenerlistener-class>
    listener>

3) 设置页面test_app.jsp

<%--
  User: Meice
  Date: 2017/10/7
  Time: 19:03
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Titletitle>
head>
<body>
    <%
        application.setAttribute("count",1);

    %>
body>
html>

测试效果是这样的:


信息: Stopping service Catalina
销毁application。。。。。
十月 07, 2017 7:05:10 下午 org.apache.coyote.AbstractProtocol stop
信息: Stopping ProtocolHandler [“http-apr-8080”]
十月 07, 2017 7:05:10 下午 org.apache.coyote.AbstractProtocol stop
信息: Destroying ProtocolHandler [“ajp-apr-8009”]
Disconnected from server


总结:
所以,JSP内置的9大对象,明白各自作用域很重要,对于这样的监听,就很容易测试和掌握。

案例五、测试ServletContextAttributeListener

根据名字知道,这是监听application设置的属性值
1)创建TestServletContextAttributeListener

    package com.hmc.listener;
    import javax.servlet.ServletContextAttributeEvent;
    import javax.servlet.ServletContextAttributeListener;
    import java.text.MessageFormat;

    /**
     * User:Meice
     * 2017/10/7
     */
    public class TestServletContextAttributeListener implements ServletContextAttributeListener {
        @Override
        public void attributeAdded(ServletContextAttributeEvent e) {
            //法1 获取ServletContextAttribute
           String name = e.getName();
          String val =(String) e.getValue();
          System.out.println("添加了属性名:"+name+"属性值:"+val);

          //发2 在Java中还可以格式化字符串
           String msg = MessageFormat.format("添加了属性名:-{0},属性值-{1}",e.getName(),e.getValue());
            System.out.println(msg);
        }

        @Override
        public void attributeRemoved(ServletContextAttributeEvent e) {
          String msg =  MessageFormat.format("移除了属性名:-{0},属性值-{1}",e.getName(),e.getValue());
           System.out.println(msg);
        }

        @Override
        public void attributeReplaced(ServletContextAttributeEvent e) {
           String msg = MessageFormat.format("替换了属性名:-{0},属性值:-{1}",e.getName(),e.getValue());
            System.out.println(msg);
        }
    }

2)配置web.xml

  
    <listener>
        <listener-class>com.hmc.listener.TestServletContextAttributeListenerlistener-class>
    listener>

3) 页面设置application;这里测试还是用test_app.jsp页面

<%--
  User: Meice
  Date: 2017/10/7
  Time: 19:03
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Titletitle>
head>
<body>
    <%
        //以下测试ServletContextListener
        application.setAttribute("count",1);

        //以下测试ServletContextAttributeListener
        //applicattion的设置同样名字的属性就是replace
        application.setAttribute("name","林黛玉");
        application.setAttribute("name","黛玉妹妹");
        application.removeAttribute("name");

    %>
body>
html>

访问:localhost:8080/JavaWeb_Listener/test_app.jsp
结果如下:


session创建了,sessionID为:43C5B885B2F42D1EE059AF0AE98FCD4C
添加了属性名:name属性值:林黛玉
添加了属性名:-name,属性值-林黛玉
替换了属性名:-name,属性值:-林黛玉
移除了属性名:-name,属性值-黛玉妹妹


还有很多类似:ServletRequestAttributeListener 、ServletRequestListener 测试方法异曲同工。

案例六、测试HttpSessionActivationListener

实现该接口的对象,如果绑定到Session中,当Session被钝化(passivate)或者激活(activate)时,Servlet容器将通知该对象,位于javax.servlet.http包下
这里创建Student类,来实现这个监听。这个监听不用配置web.xml

student类

package com.hmc.listener;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
import java.io.Serializable;

/**
 * User:Meice
 * 2017/10/7
 */
public class Student implements Serializable, HttpSessionActivationListener {
    private String name;
    public Student (){}
    public Student (String name) {
        this.name=name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void sessionWillPassivate(HttpSessionEvent e) {
        //passivate是钝化的意思;表示session被钝化
        System.out.println(e.getSession().getId()+"被序列化");
    }

    @Override
    public void sessionDidActivate(HttpSessionEvent e) {
        //session被激活
        System.out.println(e.getSession().getId()+"被反序列化到内存中....");
    }
}

测试页面test_session.jsp

<%@ page import="com.hmc.listener.Student" %><%--
  User: Meice
  Date: 2017/10/7
  Time: 23:04
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>

head>
<body>
    <%
        if(session.getAttribute("user")==null){
            session.setAttribute("user",new Student("令狐少侠"));
        }
        out.println(session.getId());

    %>

body>
html>

测试效果如下:


信息: Stopping service Catalina
6FB687AB8C4332E017D934729A80B9CF被序列化
销毁application。。。。。
十月 07, 2017 11:11:56 下午 org.apache.coyote.AbstractProtocol stop
信息: Stopping ProtocolHandler [“http-apr-8080”]


总结


1、Listener和Servlet、Filter非常类似,作用就是对各种时间进行监听,像一个小侦探;

2、创建流程基本都是:新建一个类,实现对应接口并其方法–》配置web.xml–》配置页面进行测试;

3、格式化字符串输出是一个很好的方式.MessageFormat,对比字符串拼接,后者麻烦多了。不过看这个API有点累;

4、案例6因为涉及到序列化与反序列化,所以也要实现Serializable接口。

5、我们需要深刻体会request、session、cookie、application等JSP几大内置对象的作用域和各自特性,才能不被纷繁复杂的接口搞晕乎。


好了,到这里,这部分内容总结完毕。哈哈,读者如果看到了这里,真是辛苦你了!个人觉得这篇更是对过去的总结。如果CSDN可以录制视频的话,笔者还是更加倾向于录制成视频,因为这些内容前后关联很大,而且细节繁多,仅仅看博客,可能不易理解。当然,如果是高手,就另当别论啦。

好啦,Good Night!

你可能感兴趣的:(Java)