监听器
事件(ActionEvent)
事件源(JButton)
监听器(ActionListener)
注册监听(addActionListener)
监听器就是可以监听某一个事件在执行一个特定操作时,我们可以让其触发一个操作。可以在满足特定条件的情况下执行一段操作。
Javaweb中的监听器,主要用于监听Javaweb中常用对象(request(HttpServletrequest),session(HttpSession),application(ServletContext))的三种类型操作。
- 对象的创建与销毁
- 对象的属性变化
- session绑定JavaBean
在javaweb中servlet规范只给你定义了三种技术:servlet,Listener,Filter
监听创建与销毁
- HttpServletRequest
- 监听器:ServletRequestListener可以监听request对象的创建与销毁
- HttpSession
- 监听器:HttpSessionListener 可以监听session对象的创建与销毁。
- ServletContext
- 监听器:ServletContextListener可以监听application对象的创建与销毁。
监听web对象的属性变化
- HttpServletRequest属性变化
- 监听器:ServletRequestAttributeListener监听request对象的属性变化
- HttpSession 属性变化
- 监听器:HttpSessionAttributeListener 监听session对象的属性变化。
- ServletContext 属性变化
- 监听器:ServletContextAttributeListener 监听application对象的属性变化。
在web中监听器的使用
创建监听器步骤:
- 创建一个类,去实现指定的监听器接口
- 重写接口中的方法
- 在web.xml文件中配置注册监听
public class MyServletContextListener implements ServletContextListener{
public void contextDestroyed(ServletContextEvent arg0){
System.out.println("servletContext对象销毁");
}
public void contextInitialized(ServletContextEvent arg0){
System.out.println("servletContext对象创建");
}
}
在web.xml的配置中,选中web-app,点击F2,可以看到web-app根元素下的所有子元素(按顺序排列 ),
示例:application对象的创建与销毁
application对象在服务器开启时创建,服务器关闭时销毁
<!--web.xml-->
<web-app versio="2.5"
xmlns=...
xmlns.xsi=...
xsi.schemaLocation=...>
<!--注册监听ServletContext对象创建与销毁-->
<listener>
<listener-class>cn.itcast.web.listener.application.MyServletContextListener</listener-class>
</listener>
<welcome-file-list>
<welcome-file></welcome-file>
</welcome-file-list>
</web-app>
示例:session对象的创建与销毁
public class MySessionListener implements HttpSessionListener{
public void sessionCreated(HttpSessionEvent arg0){
System.out.println("session对象创建了");
}
public void sessionDestoryed(HttpSessionEvent arg0){
System.out.println("session对象销毁了");
}
}
<!--注册监听HttpSession对象创建与销毁-->
<listener>
<listener-class>cn.itcast.web.listener.session.MysessionListener</listener-class>
</listener>
session对象创建
- request.getSession();它是用不获取session
- 是否创建,分为以下几种情况
- 请求中如果没有jsessionid,那么就是创建session对象
- 如果请求头中有jessionid值,
- 如果在服务器端,有一个session的id值与其一样,不创建,直接使用
- 如果在服务器端,没有这个session的id值,那么会创建
session销毁
- 默认超时,30分钟
- 设置session超时时间 (setMaxInactiveInterval(int interval))
- invalidate();手动销毁
- invalidate(),手动销毁;
- 关闭服务器
示例:监听request对象创建与销毁
请求发生,request对象创建,响应产生,request对象销毁
public class MyRequestListener implements ServletRequestListener{
public void requestDestoryed(ServletRequestEvent arg0){
System.out.pritnln("request对象销毁")
}
public void requestInitialized(ServletRequestEvent arg0){
System.out.println(“request对象创建”);
}
}
<!--监听HttpServletRequest对象的创建与销毁-->
<listener>
<listener-class>cn.itcast.listener.request.MyRequestListener</listener-class>
</listener>
监听对象的属性变化
示例:演示监听session的属性变化
public class MySessionAttributeListener implements HttpSessionAttributeListener{
public void attributeAddes(HttpSessionBindingEvent arg0){
//arg0.getSession();获取事件源,也就是获取session对象
System.out.pritnln(arg0.getName());//sname
System.out.println(arg0.getValue());//svalue
System.out.println("向session中添加属性");
}
public void attributeRemoved(HttpSessionBindingEvent arg0){
System.out.println(“从session中移除属性”);
}
public void attributeReplaced(HttpSessionBindingEvent arg0){
System.out.println(“将session中的属性修改”);
}
}
//session.jsp
<body>
<%
session.setAttribute("sname","svalue");//添加
session.setAttribute("sname","ssss");//修改
session.removeAttribute("sname");//移除
%>
</body>
在监听器中是否可以得到属性值
- 常识:在java的监听机制中,是可以在监听器中获取事件源的。
- 在开发中,如果遇到了事件触发机制,那么一般情况下,都可以使用方法的参数(事件对象)来获取想要的信息。
监听器在开发中的作用
- 在主流中应用比较少,但是可以完成一些性能监视操作
示例:扫描session对象在指定时间内没有使用,人为销毁。
扫描程序中的session,如果session在指定的时间内没有使用,那么可以人为销毁,session默认时间是30分钟,此处设置时间为10分钟,如果十分钟没用,就销毁,以此来释放内存提高性能
分析:
- 怎样获取session多长时间没有使用?
- 当前时间-最后使用时间
- HttpSession接口中,getLastAccessedTime()
- public long getLastAccessedTime()
- 返回客户端上一次与此会话关联的请求的时间
- 什么时候开始扫描,扫描多长时间
- Timer定时器
//Timer工具类展示
public class TimerDemo{
public static void main(String[] args){
timer t = new Timer();
t.schedule(new TimerTask(){
public void run(){
System.out.println("hello timer");
}
},1000,2000);
//延迟一秒钟执行,没间隔两秒钟调用一次
}
}
完成定时扫描session,如果超时没有使用,销毁案例
- 要将所有的session对象得到,保存到集合中
- 创建一个监听器 ServletContextListener,当服务器启动时,创建一个集合保存到ServletContext域。
- 创建一个监听器 HttpSessionListener,当创建一个session时,就从ServletContext域中获取集合,将session对象储存到集合中。
- 定时扫描
- 问题:
- session超时,不能只销毁session,还要从集合中移除
- 因为操作是多线程的,要考虑集合的同步问题
- 集合需要时线程安全的
- 需要使用迭代器进行遍历
//用于监听session对象创建,如果创建了,将其保存到一个集合中
public class MyHttpSessionListener implements HttpSessionListener{
public void sessionCreated(HttpSessionEvent se){
//session创建了
//得到session
HttpSession session = se.getSession();
//将session保存到集合中
//集合是在ServletContext中存储的,我们只需要从ServletContext中获取就可以
ServletContext context= session.getServletContext();
List<HttpSession> sessions = (List<HttpSession>)context.getAttribute("sessions");
sessions.add(session);
}
public void sessionDestroyed(HttpSessionEvent se){
}
}
public class MyServletContextListener implements ServletContextListener{
private List<HttpSession> sessions= Collections.synchronizedList(new ArrayList<HttpSession>());//线程安全的List集合
public void contextDestoryed(ServletContextEvent sce){
}
public void contextInitialized(ServletContextEvent sce){
//该方法执行了,说明了项目启动了
//得到ServletContext对象
ServletContext context = sce.getServletContext();
//将集合保存到context中
context.setAttribute("session",sessions);
//开始扫描
Timer t = new Timer();
t.schedule(new TimerTask(){
public void run(){
//判断session是否过期---session如果10秒钟没有使用,将其销毁。
for(Iterator<HttpSession> it = sessions.iterator();it.hasNext();){
HttpSession session = it.next();
//判断session是否过期
//sessions.remove(session);//从集合中移除session
it.remove();
session.invalidate();
}
}
}
},1000,3000);//延迟一秒钟,每隔3秒钟扫描一次
}
}
//配置文件
<listener>
<listener-class>cn.itcast.listener.demo.MyServletContextListener</listener-class>
</listener>
<listener>
<listener-class>cn.itcast.listener.demo.MyHttpSessionListener</listener-class>
</listener>
session绑定JavaBean监听器
- HttpSessionBindingListener
- 这个监听器,可以让JavaBean对象,感知它被绑定到session中或从session中移除。
- HttpSessionActivationListener
- 这个监听器,可以让JavaBean感知,被钝化或活化。
- 钝化—>将session中的JavaBean保存到文件中。
- 活化—-> 从文件中将JavaBean直接获取。
- 需要创建一个配置文件context.xml
- 以上两个监听器特点:
- 它们是由JavaBean实现的
- 它们不需要在web.xml文件中配置
创建JavaBean
public class User implements HttpSessionBindingListener,HttpSessionActivationListener,Serializable{
private int id;
private String name;
//get.set方法
public void valueBound(HttpSessionBindingEvent event){
System.out.println("将User对象绑定到了session中");
}
public void valueUnbound(HttpSessionBindingEvent event){
System.out.println("从session中将user对象移除");
}
public void sessionDidActivate(HttpSessionEvent se){
System.out.println("活化");
}
public void sessionWillPassivate(HttpSessionEvent se){
System.out.println("钝化");
}
}
//bean1.jsp
<body>
<%
User user = new User();
user.setId(1);
user.setName("zhangsai");
%>
</body>
//bean2.jsp
<body>
<%
session.removeAttribute("user");//移除
%>
</body>
//bean3.jsp
<body>
${user.name}
</body>
配置context文件
<Context>
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore" directory="it315"/>
</Manager>
</Context>