4.5 侦听器
4.5.1 侦听器的工作原理
侦听器用于监听web容器中的事件,并触发响应的事件。从侦听对象的角度划分,用于侦听的事件源分别为Servlet、HttpSession、ServletRequest这三个域对象。
侦听器是基于观察者模式设计的,能够方便地从一个纵向维度控制程序和数据。目前,Servlet中提供了3类共计8种事件的观察者接口及对应的6种事件:
1、源于ServletContext域对象的侦听:主要是对web应用中上下文事件的侦听,以及基于上下文属性编辑动作的侦听。
1)ServletContextEvent接口表示上下文的事件,ServletContextListener接口用于侦听这些事件.
ServletContextListener接口的主要方法如下:
void contextInitialized(ServletContextEvent se):通知正在接收的对象,应用程序已经被加载及初始化
void contextDestroyed(ServletContextEvent se):通知正在接收的对象,应用程序已经被销毁
ServletContextEvent的主要方法如下:
ServletContext.getServletContext():取得当前的ServletContext对象
2)ServletContextAttributeEvent接口表示上下文中的属性事件,对应的ServletContextAttributeListener接口表示对这些属性的 侦听。
ServletContextAttributeListener接口的主要方法如下:
void attributeAdded(ServletContextAttributeEvent se):若有对象加入application的范围,通知正在收听的对象
void attributeRemoved(ServletContextAttributeEvent se):若有对象从application的范围移除,通知正在收听的对象
void attributeReplaced(ServletContextAttributeEvent se):若在application的范围有对象取代另一个对象时,通知正在收听的对象
ServletContextAttributeEvent接口的主要方法如下:
getName():返回属性名称
getValue():返回属性的值
2、源于HttpSession域对象的侦听,主要是针对session相关行为的侦听。
1)接口用于侦听session的生命周期,HttpSessionEvent接口代表session声明周期的事件。
HttpSessionListener接口的主要方法如下:
sessionCreated(HttpSessionEvent se):当一个session被创建时,该方法被调用
sessionDestroyed(HttpSessionEvent se):当一个session被销毁时,该方法被调用
2)HttpSessionAttributeListener接口是用来侦听session绑定属性的行为,HttpSessionAttributeBindingEvent接口代表了session中属性绑定行为的事件,另一个接口HttpSessionAttributeBindingListener代表侦听http会话中对象的绑定信息。
HttpSessionAttributeListener接口的主要方法如下:
void attributeAdded(HttpSessionAttributeBindingEvent se):监听http会话中的属性添加功能
void attributeRemoved(HttpSessionAttributeBindingEvent se):监听http会话中的属性移除功能
void attributeReplaced(HttpSessionAttributeBindingEvent se):监听http会话中的属性更改功能
HttpSessionBindingListener接口的主要方法如下:
getSession():获取session对象
getName():返回session增加、删除或替换的属性名称
getValue():返回session增加、删除或替换的属性值
3、源于ServletRequest域对象的侦听,主要用于对有关客户端发起请求的侦听。
1)ServletRequestListener接口用于监听客户端的请求初始化和销毁事件,ServletRequestEvent接口是指客户端发起的请求事件。
ServletRequestListener接口的主要方法如下:
requestInitialized(ServletRequestEvent):通知当前对象请求已经被加载及初始化
requestDestroyed(ServletRequestEvent):通知当前对象,请求已经被小柴胡
ServletRequestEvent的主要方法如下:
getServletRequest():获取ServletRequest对象
getServletContext():获取ServletContext对象
2)ServletRequestAttributeListener接口用于监听web应用属性改变的事件。ServletRequestAttributeEvent接口代表对属性进行编辑的事件。
ServletRequestAttributeListener接口的主要方法如下:
void attributeAdded(ServletRequestAttributeEvent se):向Request对象添加新属性
void attributeRemoved(ServletRequestAttributeEvent se):向Request对象删除属性
void attributeReplaced(ServletRequestAttributeEvent se):替换对象中现有的属性值
ServletRequestAttributeEvent接口的主要方法如下:
getName():返回Request增加、删除或替换的属性名称
getValue():返回Request增加、删除或替换的属性值
4.5.2 创建侦听器
项目右键-new-listener-填写包名和类名,这里填写的分别是cy.listener和Listener
接着选择需要的接口,本例中选择如下几个:
package cy.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
/**
* Application Lifecycle Listener implementation class Listener
*
*/
@WebListener
public class Listener implements ServletContextListener, HttpSessionAttributeListener {
/**
* Default constructor.
*/
public Listener() {
// TODO Auto-generated constructor stub
}
/**
* @see ServletContextListener#contextDestroyed(ServletContextEvent)
*/
public void contextDestroyed(ServletContextEvent arg0) {
// TODO Auto-generated method stub
}
/**
* @see HttpSessionAttributeListener#attributeAdded(HttpSessionBindingEvent)
*/
public void attributeAdded(HttpSessionBindingEvent event) {
// TODO Auto-generated method stub
//当侦听到一个session的属性发生绑定时,获取它的名称
String name=event.getName();
System.out.println("新建session属性:"+name+" 值为:"+event.getValue());
}
/**
* @see HttpSessionAttributeListener#attributeRemoved(HttpSessionBindingEvent)
*/
public void attributeRemoved(HttpSessionBindingEvent event) {
// TODO Auto-generated method stub
String name=event.getName();
System.out.println("删除session属性:"+name+" 值为:"+event.getValue());
}
/**
* @see HttpSessionAttributeListener#attributeReplaced(HttpSessionBindingEvent)
*/
public void attributeReplaced(HttpSessionBindingEvent event) {
// TODO Auto-generated method stub
//获取修改后的session值
HttpSession session=event.getSession();
String name=event.getName();
Object oldValue=event.getValue();
System.out.println("修改session属性:"+name+" 原值为:"+oldValue+" 新值为:"+session.getAttribute(name));
}
/**
* @see ServletContextListener#contextInitialized(ServletContextEvent)
*/
public void contextInitialized(ServletContextEvent arg0) {
// TODO Auto-generated method stub
}
}
创建好这个文件后,就可以进行测试了,随便找一个之前博客写过的有关session的代码加入此包中
运行session.java
package cy.listener;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Servlet implementation class SetParam
*/
@WebServlet("/SetParam")
public class Session extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public Session() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.setContentType("text/html;charset=UTF-8");
PrintWriter out=response.getWriter();
HttpSession session=request.getSession();
Date crtTime=new Date(session.getCreationTime());//创建对象的时间
Date lastAccessTime=new Date(session.getLastAccessedTime());//上次访问session的时间
Integer visitCount=new Integer(0);//统计访问次数
String visitCountKey=new String("visitCount");
String userIDKey=new String("userID");
String userID=new String("ABCD");
if(session.isNew()) {
//为空会自动创建一个session对象
session.setAttribute(userIDKey, userID);
}
else {
visitCount=(Integer)session.getAttribute(visitCountKey);
if(visitCount!=null) {
visitCount+=1;
}
if(session.getAttribute(userIDKey)!=null) {
userID=(String)session.getAttribute(userIDKey);
}
}
session.setAttribute(visitCountKey, visitCount);
response.setContentType("text/html;charset=UTF-8");
try {
out.println("<html");
out.println("<head>");
out.println("<title></title>");
out.println("</head>");
out.println("<body>");
out.println("<table border='1' align='center'>");
out.println("<tr><th>session</th><th>value</th></tr>");
out.println("<tr><td>id</td><td>"+session.getId()+"</td></tr>");
out.println("<tr><td>creation time</td><td>"+crtTime+"</td></tr>");
out.println("<tr><td>last access time</td><td>"+lastAccessTime+"</td></tr>");
out.println("<tr><td>User ID</td><td>"+userID+"</td></tr>");
out.println("<tr><td>number of visit</td><td>"+visitCount+"</td></tr>");
out.println("</body>");
out.println("</html");
}finally {
out.close();
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
注意观察控制台输出,第一次session是新创建的,所以attributeAdded()方法作出处理
刷新当前页面,访问次数发生改变,所以控制台多了一行信息对修改的属性作出描述
侦听程序是对于一个项目活动的侦听,所以项目中任何有关动作都会触发侦听程序的动作。
18天终于写完了前4章,每天总会遇到一个不好解决的问题导致频繁凌晨才能更博,后面几章更复杂,Hedy冲鸭!!!