监听器(Listener)
Listener(监听器)——Servlet中的事件监听器(上)—第一类
Listener(监听器)——Servlet中的事件监听器(下)—第二类和第三类
什么是监听器
监听器的用途
用来监听其他对象的变化的。主要应用在图形化界面开发上。
Java中GUI、Android
监听器可以用来检测网站的在线人数,统计网站的访问量等等!
监听器的术语
监听器可以想象成现实生活中的例子:
汽车都有报警器,你踹一脚汽车,汽车的报警器就会报警,这就是监听。
监听器的入门
监听器典型案例——监听window窗口的事件监听器
首先创建一个窗口(事件源),然后再创建一个MyWindowListener类(监听器),再将事件源和监听器绑定,在MyWindowListener类中设置一个事件,程序中的事件是当关闭窗口的时候触发,所以在关闭窗口的时候就会执行事件类。
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.JFrame;
/**
* GUI的小窗口演示监听器
*
* @author 25858
*
*/
public class MyFrame extends JFrame {
public static void main(String[] args) {
// 1. 创建小窗口对象(被监听对象/事件源)
MyFrame myFrame = new MyFrame();//代表一个window窗口
// 设置窗口的宽高
myFrame.setBounds(0, 0, 200, 200);
// 2. 设置窗口显示
myFrame.setVisible(true);
// 在事件源上绑定监听器/事件源和监听器的绑定
myFrame.addWindowListener(new MyWindowListener());
}
}
/**
* 监听器对象/监听器
*
* @author 25858
*
*/
class MyWindowListener implements WindowListener {
@Override
// 事件
/*
* 当window窗体关闭时,MyWindowListener 这个监听器就会监听到,
* 监听器就会调用windowClosing方法处理window窗体关闭时的动作
*/
public void windowClosing(WindowEvent e) {
System.out.println("窗口关闭");
}
@Override
public void windowOpened(WindowEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void windowClosed(WindowEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void windowIconified(WindowEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void windowDeiconified(WindowEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void windowActivated(WindowEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void windowDeactivated(WindowEvent e) {
// TODO 自动生成的方法存根
}
}
运行结果:
在运行程序后再关闭程序,会触发事件,然后执行事件方法。
监听器的执行过程
Servlet中的监听器
Listener(监听器)——Servlet中的事件监听器(上)
Servlet中的监听器简介
在Servlet中定义了多种类型的监听器,它们用于监听的事件源分别是ServletContext、HttpSession和ServletReguest这三个域对象。
Servlet中的监听器分类
在Servlet规范中定义了多种类型的监听器,它们用于监听的事件源分别为ServletContext,HttpSession和ServletRequest这三个域对象。Servlet规范针对这三个对象上的操作,又把多种类型的监听器划分为三种类型:
ServletContextListener监听器
ServletContextListener监听器的作用
用来监听ServletContext 域对象的创建和销毁的监听器。
ServletContext对象创建和销毁
ServletContextListener监听器的方法
监听ServletContext对象的创建:
监听ServletContext对象的销毁:
编写监听器监听ServletContext对象创建和销毁
监听器类:
/**
* ServletContextListener监听器
*
* @author 25858
* * 事件源:ServletContext
* * 监听器:MyServletContextListener
* * 事件源和监听器绑定:通过配置方式(web.xml)绑定
*/
public class MyServletContextListener implements ServletContextListener {
@Override
// 监听ServletContext对象的创建
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("ServletContext对象销毁了");
}
@Override
// 监听ServletContext对象的销毁
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("ServletContext对象创建了");
}
}
通过配置方式(web.xml)绑定事件源和监听器:
直接在web.xml中添加全路径即可。
<listener>
<listener-class>com.wxw.listener.weblistener.MyServletContextListener</listener-class>
</listener>
运行:
ServletContext对象启动服务器时就会创建,监听器在监听到ServletContext对象的创建就会响应执行监听创建的方法,监听到ServletContext对象的销毁也会响应执行监听销毁的方法。
关闭服务器
ServletContextListener企业用途
HttpSessionListener监听器
HttpSessionListener监听器的作用
用来监听HttpSession对象的创建和销毁。
HttpSession对象创建和销毁
HTTPSessionListener监听器的方法
监听HTTPSession对象创建:
监听HTTPSession对象销毁:
编写监听器监听Httpession对象创建和销毁
监听器类:
/**
* 监听HttpSession对象创建和销毁的监听器
* * 事件源:HttpSession
* * 监听器:MyHttpSessionListener
* * 事件源和监听器绑定:通过配置方式(web.xml)绑定
* @author 25858
*
*/
public class MyHttpSessionListener implements HttpSessionListener {
@Override
// 监听HttpSession的创建
public void sessionCreated(HttpSessionEvent arg0) {
System.out.println("HttpSession创建了");
}
@Override
// 监听HttpSession的销毁
public void sessionDestroyed(HttpSessionEvent arg0) {
System.out.println("HttpSession销毁了");
}
}
web.xml
<listener>
<listener-class>com.wxw.listener.weblistener.MyHttpSessionListener</listener-class>
</listener>
问题
访问HTML是否创建Session:不会
访问JSP是否创建Session:会(JSP会被翻译成Servlet,在Servlet中已经默认调用了getSession方法了)
访问Servlet是否创建Session:不会(默认没有调用getSession方法)
Session对象怎么销毁?
直接关闭服务器是不会销毁的,而是会序列化到本地,再次运行时就会反序列化到服务器。
关闭服务器:
点击红色按钮关闭服务器
再次开启:
非正常关闭服务器
直接点击控制台的红色方块按钮,相当于直接拔掉电源,属于非正常关闭,因为是非正常关闭,所以也不会触发监听器。
设置存活时间销毁Session:
<session-config>
<session-timeout>1</session-timeout><!-- 一分钟的存活时间 -->
</session-config>
一分钟后httpSession销毁了
ServletRequestListener监听器
ServletRequestListener监听器作用
用户监听ServletReguest对象的创建和销毁
ServletRequest对象创建和销毁
ServletRequestListener监听器的方法
监听ServletRequest对象的创建:
监听ServletRequest对象的销毁:
编写监听器监听ServletRequest对象创建和销毁
监听类:
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
/**
* 监听ServletRequest对象创建和销毁的监听器
* * 事件源:ServletRequest
* * 监听器:MyServletRequestListener
* * 事件源和监听器绑定:通过配置方式(web.xml)绑定
* @author 25858
*
*/
public class MyServletRequestListener implements ServletRequestListener {
@Override
// 监听ServletRequest对象的销毁
public void requestDestroyed(ServletRequestEvent arg0) {
System.out.println("ServletRequest对象销毁了");
}
@Override
// 监听ServletRequest对象的创建
public void requestInitialized(ServletRequestEvent arg0) {
System.out.println("ServletRequest对象创建了");
}
}
web.xml
<listener>
<listener-class>com.wxw.listener.weblistener.MyServletRequestListener</listener-class>
</listener>
问题
因为无论访问HTML、JSP、Servlet,他们都叫请求。
统计当前在线人数的案例
案例分析
监听ServletContext对象,在其创建时就初始化一个值为0,代表在线人数,然后监听HttpSession对象,当用户上线时触发创建事件,初始值+1,用户下线时触发销毁事件,初始值-1。
ServletContext对象在启动浏览器是就会创建,HTTPSession对象在用户访问时就会创建,关闭浏览器时销毁。
代码实现
创建ServletContextListener进行初始化
向ServletContext中添加一个值,代表在线人数。
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class OnliCountServletContextListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent arg0) {
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
// 在服务器启动的时候初始化一个值为0
// 还需要将这个值存 入到ServletContext中
arg0.getServletContext().setAttribute("count", 0);
}
}
创建HttpSessionListener
监听HttpSession的创建和销毁,创建代表在线人数加一,销毁代表在线人数减一。
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class OnliCountHttpSessiontListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent arg0) {
// 上线了
HttpSession session = arg0.getSession();
System.out.println(session.getId() + "上线了");
// 获得ServletContext中的值
Integer count = (Integer) session.getServletContext().getAttribute("count");
count++;
session.getServletContext().setAttribute("count", count);
}
@Override
public void sessionDestroyed(HttpSessionEvent arg0) {
// 离线了
HttpSession session = arg0.getSession();
System.out.println(session.getId() + "上线了");
// 获得ServletContext中的值
Integer count = (Integer) session.getServletContext().getAttribute("count");
count--;
session.getServletContext().setAttribute("count", count);
}
}
绑定监听器
<listener>
<listener-class>com.wxw.listener.onlinecount.OnliCountServletContextListener</listener-class>
</listener>
<listener>
<listener-class>com.wxw.listener.onlinecount.OnliCountHttpSessiontListener</listener-class>
</listener>
创建JSP的页面
<body>
在线人数:${ count }
</body>
运行结果:
更换浏览器
监听三个域对象的属性变更的监听器
Listener(监听器)——Servlet中的事件监听器(下)
ServletContextAttributeListener
监听ServletContext对象中的属性变更 (属性添加,移除,替换) 的监听器
HttpSessionAttributeIistener
监听HttpSession对象中的属性变更 (属性添加,移除,替换) 的监听器
ServletRequestAttributeListener
监听ServletReguest对象中的属性变更 (属性添加,移除,替换) 的监听器
演示第二类监听器
这里我们只演示HttpSessionAttributeIisteners,其他的监听器使用方式类似。
代码编写:
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
public class MyHttpSessionAttributeIistener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent arg0) {
System.out.println("在session中添加了属性");
}
@Override
public void attributeRemoved(HttpSessionBindingEvent arg0) {
System.out.println("在session中移除了属性");
}
@Override
public void attributeReplaced(HttpSessionBindingEvent arg0) {
System.out.println("在session中替换了属性");
}
}
绑定监听器:
<listener>
<listener-class>com.wxw.listener.weblistener.MyHttpSessionAttributeIistener</listener-class>
</listener>
编写JSP页面:
<body>
<%
session.setAttribute("name", "aaa"); //属性添加
session.setAttribute("name", "bbb"); //属性替换
session.removeAttribute("name"); //属性移除
%>
</body>
运行:
监听Httpsession中java类状态改变的类监听器
概述
保存在Session域中的Java类可以有多种状态:
绑定到session中;
从session中解除绑定;
随session对象持久化到一个存储设备中(钝化);
随session对象从一个存储设备中恢复(活化)。
Servlet对方中定义了两个特殊的监听的接口来帮助Java类了解自己在Session域中的状态:
HttpSessionBindingListener接口
HttpSessionActivationListener接口,
实现这两个接口的类不需要在web.xml中进行配置
HttpSessionBindingListener监听器
监听Java类在HttpSession中的绑定和解除绑定的状态的监听器:
测试代码:
监听器
/**
* 监听HttpSession中java类的绑定与解除绑定的监听器
*
* @author 25858
*
*/
public class Bean1 implements HttpSessionBindingListener {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void valueBound(HttpSessionBindingEvent arg0) {
System.out.println("Bean1与session绑定了");
}
@Override
public void valueUnbound(HttpSessionBindingEvent arg0) {
System.out.println("Bean1与session解除绑定了");
}
}
JSP页面:
<body>
<%
Bean1 bean = new Bean1();
bean.setName("张三");
session.setAttribute("name", bean);//绑定,绑定必须是JavaBean才可以。
session.removeAttribute("name");//解除绑定
%>
</body>
结果:
运行JSP页面
HttpSessionActivationListener监听器
监听HttpSession 中Java类的钝化(序列化)和活化(反序列化)监听器。
编写一个类实现HttpSessionActivationListener接口,因为要实现序列化,所以也要实现Serializable接口。
import java.io.Serializable;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
/**
* 监听HttpSession对象的活化和钝化的监听器
*
* @author 25858
*
*/
public class Bean2 implements HttpSessionActivationListener, Serializable {
/**
*
*/
private static final long serialVersionUID = 3701139672745359244L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void sessionDidActivate(HttpSessionEvent arg0) {
System.out.println("JavaBean随着session活化了,也就是随着session从硬盘回到内存了!!");
}
@Override
public void sessionWillPassivate(HttpSessionEvent arg0) {
System.out.println("JavaBean随着session钝化了,也就是到硬盘中去了!!");
}
}
为了观察绑定到HttpSession对象中的JavaBean对象随HttpSession对象一起被钝化到硬盘上和从硬盘上重新活化回到内存中的的过程,我们需要借助Tomcat服务器帮助我们完成HttpSession对象的钝化和活化过程,具体做法如下:
首先,在WebRoot\META-INF文件夹下创建一个context.xml文件,如下图所示:
context.xml文件的内容如下:
<Context>
<Manager
className="org.apache.catalina.session.PersistentManager"
maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore"
directory="wxw" />
</Manager>
</Context>
在context.xml文件中配置了session一分钟没人用了,就将HttpSession对象和JavaBean对象钝化到本地硬盘的一个wxw文件夹中。
然后,编写一个jsp页面进行测试。
<body>
一访问JSP页面,HttpSession就创建了,创建好的Session的Id是:${pageContext.session.id}
<%
session.setAttribute("bean", new Bean2()); //当session一分钟没人用,session就和bean一起到硬盘中去了
%>
</body>
最后,访问这个jsp页面,服务器就会马上创建一个HttpSession对象,然后将实现了HttpSessionActivationListener接口的JavaBean对象绑定到session对象中,这个jsp页面在等待1分钟之后没有人再次访问,那么服务器就会自动将这个HttpSession对象钝化(序列化)到硬盘上。
访问JSP页面无操作一分钟后:
我们可以在Tomcat服务器的work\Catalina\localhost\web05\wxw文件夹下找到序列化到本地存储的session,如下图所示:
当再次访问这个jsp页面时,服务器又会自动将已经钝化(序列化)到硬盘上的HttpSession对象重新活化(反序列化)回到内存中。运行结果如下:
JavaWeb开发技术中的监听器技术的内容就这么多了,在平时的工作中,监听器技术在JavaWeb项目开发中用得是比较多的,因此必须掌握这门技术。