(1)监听器的相关概念(与JS中的事件监听机制类似)
事件源:被监听的对象 ----- 三个域对象 request , session , servletContext
监听器:监听事件源对象 事件源对象的状态的变化都会触发监听器 ---- 6+2
注册监听器:将监听器与事件源进行绑定
响应行为:监听器监听到事件源的状态变化时触发的行为
(2)监听器的种类
第一维度:按照被监听的对象划分:ServletRequest域 HttpSession域 ServletContext域
第二维度:监听的内容分:监听域对象的创建与销毁 监听域对象的属性变化
对于ServletContext域,可以监听ServletContext域中对象的创建与销毁(ServletContextListener)和监听ServletContext域中对象的属性变化(ServletContextAttributeListener);对于HttpSession域(具有HttpSessionListener和HttpSessionAttributeListener)和ServletRequest域(具有ServletRequestListener和ServletRequestAttributeListener),也是类似。
(3)以ServletContext域(一个web应用只有一个ServletContext域)的监听为例,学习监听器的写法
a.监听器的编写步骤:
- 编写一个监听器类(MyServletContextListener)去实现监听器接口(ServletContextListener)
- 覆盖监听器的方法(contextInitialized和contextDestroyed)
- 需要在web.xml中进行配置---注册
(b)MyServletContextListener.java
package cn.shu.create;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class MyServletContextListener implements ServletContextListener{
/*一个web应用只有一个servletContext对象*/
/*监听context对象的销毁*/
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("context销毁");
}
/*监听context对象的创建,服务器启动时执行该方法*/
@Override
public void contextInitialized(ServletContextEvent sce) {
/*通过参数可以获得被监听的对象*/
ServletContext servletContext = sce.getServletContext();
/*通过参数可以获得被监听的对象,通用的方法,返回Object对象,可对其进行强转
Object source = sce.getSource();
System.out.println("context创建");
}
}
以上已经继承了接口完成了方法的覆盖操作,接下里需要注册事件(在配置文件中进行配置)
(c)web.xml
<listener>
<listener-class>cn.shu.create.MyServletContextListener</listener-class>
</listener>
启动项目,console打印:
(4)ServletContextListener监听器的主要作用
- 初始化的工作:初始化对象 初始化数据 ---- 加载数据库驱动 连接池的初始 化
- 加载一些初始化的配置文件 --- spring的配置文件
- 任务调度----定时器----Timer/TimerTask
(a)初始化方法
/*监听context对象的创建,服务器启动时执行该方法*/
@Override
public void contextInitialized(ServletContextEvent sce) {
/*System.out.println("context创建");*/
/*通过参数可以获得被监听的对象*/
/* ServletContext servletContext = sce.getServletContext();
/*通过参数可以获得被监听的对象,通用的方法,返回Object对象,可对其进行强转
Object source = sce.getSource();
System.out.println("context创建");
开启一个计息任务,每天晚上12点计息一次
*/
Timer timer = new Timer();
/*
* timer.scheduleAtFixedRate(task,firstTime.period);
* task:任务 firstTime:第一次执行时间 period:间隔执行时间
* timerTask为一个接口,不可以直接new对象,但可以new匿名内部类*/
timer.schedule(new TimerTask(){
@Override
public void run() {
System.out.println("计息开始");
}}, new Date(), 30000);
}
启动项目,console打印:
(a)初始化方法中设置定时器
/*监听context对象的创建,服务器启动时执行该方法*/
@Override
public void contextInitialized(ServletContextEvent sce) {
开启一个计息任务,每天晚上12点计息一次
*/
Timer timer = new Timer();
/*
* timer.scheduleAtFixedRate(task,firstTime.period);
* task:任务 firstTime:第一次执行时间 period:间隔执行时间
* timerTask为一个接口,不可以直接new对象,但可以new匿名内部类*/
/* timer.schedule(new TimerTask(){
/*真正的银行计息业务,需修改两个地方
* 1.起始时间不是现在(new Date()),是晚上12点
*
* 2.间隔执行时间:24小时*/
SimpleDateFormat format = new SimpleDateFormat("YYYY-MM-DD HH:MM:SS");
String currentTime = "2018-08-20 00:00:00";
Date parse =null;
try {
parse = format.parse(currentTime);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
timer.schedule(new TimerTask(){
@Override
public void run() {
System.out.println("计息开始");
}},parse, 24*60*60*1000);
}
控制台打印:
(5)HttpSessionListener例子类似
package cn.shu.create;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class MyHttpSessionListener implements HttpSessionListener{
@Override
/*session对象创建时执行该方法,
* 何时创建:第一次调用request.getSession时创建
何时销毁:服务器关闭销毁 session过期 手动销毁*/
public void sessionCreated(HttpSessionEvent arg0) {
System.out.println("session创建"+arg0.getSession().getId());
}
@Override
public void sessionDestroyed(HttpSessionEvent arg0) {
System.out.println("session销毁");
}
}
当Session对象创建时就会执行上述的初始化方法,当然别忘了注册
<listener>
<listener-class>cn.shu.create.MyHttpSessionListener</listener-class>
</listener>
(6)以ServletContextAttributeListener为例示范监听域属性改变的方法
域对象的通用的方法:
setAttribute(name,value)(增,改)
--- 触发添加属性的监听器的方法
--- 触发修改属性的监听器的方法
getAttribute(name)(查,此处用不到)
removeAttribute(name) (删)
--- 触发删除属性的监听器的方法
(1)MyServletContextAttributeListener.Java
package cn.shu.attribute;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
public class MyServletContextAttributeListener implements ServletContextAttributeListener{
@Override
public void attributeAdded(ServletContextAttributeEvent arg0) {
/*监听放到域中的name和value
* */
System.out.println(arg0.getName());
System.out.println(arg0.getValue());
}
@Override
public void attributeRemoved(ServletContextAttributeEvent arg0) {
/*监听域中删除的name和value*/
System.out.println(arg0.getName());
System.out.println(arg0.getValue());
}
@Override
public void attributeReplaced(ServletContextAttributeEvent arg0) {
/*获得修改前的name和value值*/
System.out.println(arg0.getName());
System.out.println(arg0.getValue());
}
}
2.注册(web.xml配置)********重要,
<listener>
<listener-class>cn.shu.attribute.MyServletContextAttributeListener</listener-class>
</listener>
3,测试(改变域中的属性,查看监听器是否监听成功)
package cn.shu.attribute;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class TestServletContextAttributeListener
*/
public class TestServletContextAttributeListener extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public TestServletContextAttributeListener() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*获得域对象*/
ServletContext context = this.getServletContext();
/**向context域中存数据*/
context.setAttribute("name", "jack");
/**向context域中改数据*/
context.setAttribute("name", "rose");
/**向context域中删除数据*/
context.removeAttribute("name");
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
4.发布项目,在浏览器输入地址:http://localhost:8080/Listener/test1访问(会产生ServletContext对象)
说明监听成功。