文档章节

javaweb开发之Listener

小米米儿小
 小米米儿小
发布于 2013/12/06 15:25
字数 2687
阅读 42
收藏 1
点赞 0
评论 0

一、 监听器

WEB应用开发中的监听器是指对整个WEB环境的监听,当被监视的对象(ServletContext)发生情况(生命周期,setAttribute)时,立即调用相应的方法进行处理。

实现了监听者模式(观察者模式)。

servlet 规范中为每种事件监听器都定义了相应的接口,在编写事件监听器程序时只需实现这些接口就可以了。 web 服务器根据用户编写的事件监听器所实现的接口把它注册到相应的被监听对象上。

一些Servlet事件监听器需要在web应用程序的部署文件描述符文件(web.xml)中进行注册,一个web.xml可以注册多个servlet事件监听器。web服务器按照它们在web.xml中注册顺序来加载和注册这些servlet事件监听器。

servlet事件监听器的注册和调用过程都是由web容器自动完成的,当发生被监听的对象被创建,修改,销毁等事件时,web容器将调用与之相关的servlet事件监听器对象的相应方法,用户在这些方法中编写的事件处理代码即被执行。

由于在一个web应用程序中只会为每个事件监听器类创建一个实例对象,有可能出现多个线程同时调用一个事件监听对象的情况,所以要注意多线程安全问题。

二、Servlet 监听器的分类

1. 按监听的对象划分

用于监听应用程序环境对象(ServletContext)的事件监听器

用于监听用户会话对象(HttpSession)的事件监听器

用于监听请求消息对象(ServletRequest)的事件监听器

2. 按监听的事件类项划分

用于监听域对象自身的创建和销毁的事件监听器

用于监听域对象中的属性的增加和删除的事件监听器

用于监听绑定到HttpSession域中的某个对象的状态的事件监听器

三、Servlet 事件监听器

1. 监听域对象的创建和销毁

域对象创建和销毁的事件监听器就是用来监听 ServletContext, HttpSession, HttpServletRequest 这三个对象的创建和销毁事件的监听器。

1.1 域对象的创建和销毁时机

ServletContext 

创建:是在 Web 服务器启动并加载某个 Web 应用程序时创建相应的ServletContext 对象;

销毁:是在 Web 服务器关闭或卸载时为每个 Web 应用程序销毁相应的ServletContext 对象。


HttpSession 

创建:是在浏览器开始与服务器会话时创建;

销毁:是在调用HttpSession.invalidate();超过了Session的最大有效时间间隔,服务器进程被停止的时候。


ServletRequest 

创建:每次请求开始时创建;

销毁:每次访问结束后销毁 。


1.2 域对象的创建和销毁监听器

ServletContextListener 接口

ServletContextListener 接口用于监听 ServletContext 对象的创建和销毁事件。
当 ServletContext 对象被创建时,激发public void contextInitalized(ServletContextEvent sce)方法;
当 ServletContext 对象被销毁时,激发public void contextDestroyed(ServletContextEvent sce)方法。

方法参数是ServletContextEvent事件是在servlet对象创建时自动激活的事件。


HttpSessionListener 接口

HttpSessionListener 接口用于监听HttpSession对象的创建和销毁。
创建一个Session时,激发public void sessionCreated(HttpSessionEvent se)方法;

销毁一个Session时,激发public void sessionDestroyed(HttpSessionEvent se)方法。


ServletRequestListener接口 

ServletRequestListener 接口用于监听ServletRequest 对象的创建和销毁。
创建一个ServletRequest 对象时,激发public void requestInitialized(ServletRequestEvent sre)方法;

销毁一个ServletRequest时,激发public void requestDestroyed(ServletRequestEvent sre)方法。


2. 监听域对象中的属性的增加和删除

域对象中属性的变更的事件监听器就是用来监听 ServletContext, HttpSession, HttpServletRequest 这三个对象中的属性变更信息事件的监听器。

这三个监听器接口分别是ServletContextAttributeListener, HttpSessionAttributeListener 和ServletRequestAttributeListener,这三个接口中都定义了三个方法来处理被监听对象中的属性的增加,删除和替换的事件,同一个事件在这三个接口中对应的方法名称完全相同,只是接受的参数类型不同。

2.1 attributeAdded() 方法

当向被监听器对象中增加一个属性时,web容器就调用事件监听器的 attributeAdded 方法进行响应,这个方法接受一个事件类型的参数,监听器可以通过这个参数来获得正在增加属性的域对象和被保存到域中的属性对象。各个域属性监听器中的完整语法定义为:

public void attributeAdded(ServletContextAttributeEvent scae) 
public void attributeAdded (HttpSessionBindingEvent  hsbe) 
public void attributeAdded (ServletRequestAttributeEvent srae)

2.2 attributeRemoved() 方法

当删除被监听对象中的一个属性时,web 容器调用事件监听器的这个方法进行响应。各个域属性监听器中的完整语法定义为:

public void attributeRemoved(ServletContextAttributeEvent scae) 
public void attributeRemoved (HttpSessionBindingEvent  hsbe) 

public void attributeRemoved (ServletRequestAttributeEvent srae)

2.3 attributeReplaced() 方法

当监听器的域对象中的某个属性被替换时,web容器调用事件监听器的这个方法进行相应。各个域属性监听器中的完整语法定义为:
public void attributeReplaced(ServletContextAttributeEvent scae) 
public void attributeReplaced (HttpSessionBindingEvent  hsbe) 
public void attributeReplaced (ServletRequestAttributeEvent srae)

3. 监听绑定到HttpSession域中的某个对象的状态

保存在 Session 域中的对象可以有多种状态:绑定到  Session 中;从 Session 域中解除绑定;随 Session 对象持久化到一个存储设备中;随 Session 对象从一个存储设备中恢复。
Servlet 规范中定义了两个特殊的监听器接口来帮助 JavaBean 对象了解自己在 Session 域中的这些状态:
          HttpSessionBindingListener接口
          HttpSessionActivationListener接口  
实现这两个接口的类不需要 web.xml 文件中进行注册。

3.1 HttpSessionBindingListener接口

实现了HttpSessionBindingListener接口的 JavaBean 对象可以感知自己被绑定到 Session 中和从 Session 中删除的事件 。
当对象被绑定到 HttpSession 对象中时,web 服务器调用该对象的  void valueBound(HttpSessionBindingEvent event) 方法 ;

当对象从 HttpSession 对象中解除绑定时,web 服务器调用该对象的 void valueUnbound(HttpSessionBindingEvent event)方法。

3.2 HttpSessionActivationListener接口

实现了HttpSessionActivationListener接口的 JavaBean 对象可以感知自己被活化和钝化的事件 。
当绑定到 HttpSession 对象中的对象将要随 HttpSession 对象被钝化之前,web 服务器调用该对象的  void sessionWillPassivate(HttpSessionBindingEvent event) 方法 ;
当绑定到 HttpSession 对象中的对象将要随 HttpSession 对象被活化之后,web 服务器调用该对象的 void sessionDidActive(HttpSessionBindingEvent event)方法 。

四、应用

统计当前在线人数


User.java

package cn.heimar.online;

public class User {
	private String id;
	private String name;
	private String ip;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public String getIp() {
		return ip;
	}

	public void setIp(String ip) {
		this.ip = ip;
	}
}
IndexServlet.java
package cn.heimar.online;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class IndexServlet extends HttpServlet {

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		HttpSession session = req.getSession();
		User u = (User) session.getAttribute("USER_IN_SESSION");
		if (u == null) {
			u = new User();
			u.setId(session.getId());
			u.setIp(req.getRemoteAddr());
			session.setAttribute("USER_IN_SESSION", u);
		}
		req.getRequestDispatcher("/WEB-INF/login.jsp").forward(req, resp);
	}
}

LoginServlet.java

package cn.heimar.online;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LoginServlet extends HttpServlet {
	private boolean hasLength(String s) {
		return s != null && !"".equals(s.trim());
	}

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		req.setCharacterEncoding("UTF-8");
		String name = req.getParameter("username");
		String password = req.getParameter("password");
		if (hasLength(name) && hasLength(password)) {
			HttpSession session = req.getSession();
			User u = (User) session.getAttribute("USER_IN_SESSION");
			u.setName(name);
			req.getRequestDispatcher("/WEB-INF/success.jsp").forward(req, resp);
		} else {
			resp.sendRedirect(req.getContextPath()+"/index");
		}
	}
}

OnlineServlet.java

package cn.heimar.online;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class OnlineServlet extends HttpServlet {

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String cmd = req.getParameter("cmd");
		String id = req.getParameter("id");

		List<User> guests = new ArrayList<User>();
		List<User> users = new ArrayList<User>();

		@SuppressWarnings("unchecked")
		List<User> onlines = (List<User>) this.getServletContext()
				.getAttribute("ONLINE_IN_CTX");

		if ("remove".equals(cmd) && id != null && !"".equals(id)) {
			for (User u : onlines) {
				if (u.getId().equals(id)) {
					u.setName(null);
				}
			}
		}

		for (User u : onlines) {
			if (u.getName() != null) {
				users.add(u);
			} else {
				guests.add(u);
			}
		}

		req.setAttribute("guests", guests);
		req.setAttribute("users", users);

		req.getRequestDispatcher("/WEB-INF/online.jsp").forward(req, resp);
	}

}

OnlineServletCtxListener.java

package cn.heimar.online;

import java.util.ArrayList;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
 * 在线用户统计ServletContext监听器
 * 在应用启动时,初始化在线用户列表属性“ONLINE_IN_CTX”
 */
public class OnlineServletCtxListener implements ServletContextListener {

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		sce.getServletContext().setAttribute("ONLINE_IN_CTX",
				new ArrayList<User>());
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		// TODO Auto-generated method stub
	}

}

OnlineSessionAttrListener.java

package cn.heimar.online;

import java.util.List;

import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

/**
 * 在线用户统计HttpSessionAttribute监听器
 * 在当前用户session中添加“USER_IN_SESSION”时,将该用户添加到在线用户列表
 */
public class OnlineSessionAttrListener implements HttpSessionAttributeListener {

	@Override
	public void attributeAdded(HttpSessionBindingEvent event) {
		String name = event.getName();
		if ("USER_IN_SESSION".equals(name)) {
			User u = (User) event.getValue();
			List<User> onlines = (List<User>) event.getSession()
					.getServletContext().getAttribute("ONLINE_IN_CTX");
			onlines.add(u);
		}
	}

	@Override
	public void attributeRemoved(HttpSessionBindingEvent se) {
		// 可以在用户退出后将当前用户从在线用户列表中删除。此处不演示
	}

	@Override
	public void attributeReplaced(HttpSessionBindingEvent se) {
		// TODO Auto-generated method stub
	}

}

OnlineSessionListener.java

package cn.heimar.online;

import java.util.List;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * 在线用户统计HttpSession监听器
 * 在当前用户session销毁时,将该用户从在线用户列表中移除
 */
public class OnlineSessionListener implements HttpSessionListener {

	@Override
	public void sessionCreated(HttpSessionEvent se) {
		// TODO Auto-generated method stub
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		User u = (User) se.getSession().getAttribute("USER_IN_SESSION");
		List<User> onlines = (List<User>) se.getSession().getServletContext()
				.getAttribute("ONLINE_IN_CTX");
		for (int i = 0; i < onlines.size(); i++) {
			User t = onlines.get(i);
			if (t.getId().equals(u.getId())) {
				onlines.remove(i);
			}
		}
	}

}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<!--注册监听器-->
	<listener>
		<listener-class>cn.heimar.online.OnlineServletCtxListener</listener-class>
	</listener>
	<listener>
		<listener-class>cn.heimar.online.OnlineSessionAttrListener</listener-class>
	</listener>
	<listener>
		<listener-class>cn.heimar.online.OnlineSessionListener</listener-class>
	</listener>

	<servlet>
		<servlet-name>index</servlet-name>
		<servlet-class>cn.heimar.online.IndexServlet</servlet-class>
	</servlet>
	<servlet>
		<servlet-name>login</servlet-name>
		<servlet-class>cn.heimar.online.LoginServlet</servlet-class>
	</servlet>
	<servlet>
		<servlet-name>online</servlet-name>
		<servlet-class>cn.heimar.online.OnlineServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>login</servlet-name>
		<url-pattern>/login</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>index</servlet-name>
		<url-pattern>/index</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>online</servlet-name>
		<url-pattern>/online</url-pattern>
	</servlet-mapping>
</web-app>

login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form method="post" action="<%=request.getContextPath() %>/login">
<table>
	<tr>
		<td>姓名:</td>
		<td><input type="text" name="username" /></td>
	</tr>
	<tr>
		<td>密码:</td>
		<td><input type="password" name="password" /></td>
	</tr>
	<tr>
		<td colspan="2"><input type="submit" value="登陆" /></td>
	</tr>
</table>
</form>
</body>
</html>
online.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
游客:
<table border="1">
	<tr>
		<td width="100">ID</td>
		<td width="100">IP</td>
	</tr>
	<c:forEach var="g" items="${guests }">
		<tr>
			<td>${g.id }</td>
			<td>${g.ip }</td>
		</tr>
	</c:forEach>
</table>
<br/>
<br/>
在线用户:
<table border="1">
	<tr>
		<td width="100">ID</td>
		<td width="100">用户名</td>
		<td width="100">操作</td>
	</tr>
	<c:forEach var="u" items="${users }">
		<tr>
			<td>${u.id }</td>
			<td>${u.name }</td>
			<td><a href="<%=request.getContextPath() %>/online?cmd=remove&id=${u.id }">T掉</a></td>
		</tr>
	</c:forEach>
</table>
</body>
</html>
success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
登陆成功..
<br/>
<a href="<%=request.getContextPath() %>/online">查看在线用户列表</a>
</body>
</html>


© 著作权归作者所有

共有 人打赏支持
小米米儿小
粉丝 34
博文 107
码字总数 83921
作品 0
成都
程序员
Javaweb和spring和springmvc和maven使用记录

一、java项目使用spring框架 新建一个java项目,名为spring01 在项目新建一个libs文件夹来存放所有的第三方jar 把spring相关的jar拷贝到该目录 然后设置buildpath --> config build path -->...

独钓渔
2016/01/16
174
0
spring的使用

在前边的文章中说明了,如何搭建一个spring的开发环境,简单回顾下就是把spring的jar包导入工程中,如果是在javaWeb项目中是放在lib目录下,然后在web.xml文件中进行配置,配置spring的配置文...

wf王帆
2016/08/01
6
0
Javaweb组件--Listener

监听器就是实现特定接口的Java类,这个类专门用于监听另一个Java对象的方法调用或者属性改变,当监听对象发生上述事件后,监听器某个方法将立即被执行 JavaWeb中的监听器 JavaWeb中的监听器是...

a1ie2
2017/11/21
0
0
线程中无法通过spring注入services为null

一个javaweb的项目,在web.xml中设置一个监听 com.thread.MyListener 下面是监听类中的方法 public class MyListener implements ServletContextListener{ private MyThread myThread; publ......

深谷不见幽兰
2013/12/03
6.3K
4
开源会议管理系统--CoolMeeting

有暇,搞了个会议管理系统,供刚入行的小伙伴们学习。 涉及到的技术点: 1.jQuery、Ajax 2.jsp 3.Servlet、Filter、Listener 4.MySql 5.JDBC 这些都是JavaWeb的基础知识。 效果图如下: 1.注...

Java-大神
2017/09/01
652
0
Java Web从入门到"改行"(4)--监听器Listener

1. 监听器Listener: JavaWeb中的监听器是Servlet规范中定义的一种特殊类,它用于监听web应用程序中的ServletContext, HttpSession和 ServletRequest等域对象的创建与销毁事件,以及监听这些...

流川枫AI
07/03
0
0
Java web部署目录结构和web.xml作用

一、Javaweb 部署目录结构 servlet规范不仅规范了servlet自身处理web请求的通用逻辑过程, 还规范了web服务器管理servlet的通用步骤。 为了使得我们开发的Java web 应用能在多种多样的 Java...

qingfeng哥
2016/09/24
165
0
JavaWeb 服务启动时,在后台启动加载一个线程

JavaWeb 服务启动时,在后台启动加载一个线程。 目前,我所掌握的一共有两种方法,第一种是监听(Listener),第二种是配置随项目启动而启动的Servlet。 下面对这两种方法做一简单的介绍,(...

别寒
2014/03/04
51
0
采用Servlet Listener方式运行Liquibase

我的javaweb项目使用springmvc+spring+mybatis框架开发的,所以我在这个框架的基础上整合liquibase的。捣鼓了一上午才运行的通,希望可以帮助到大家 使用步骤 一、在web.xml文件中添加以下内...

chenfj_fer
01/12
1
0
java极速开发框架--JDiy

JDiy开源框架。2.6版发布更新。 JDiy是一个超轻量级的java开源框架,同时也包含一套javaWeb建站开发平台。可以将JDiy应用于javaWeb/javaEE开发环境,或javaSE开发环境。 JDiy支持多种类型的数...

子秋
2013/01/07
7.3K
6

没有更多内容

加载失败,请刷新页面

加载更多

下一页

垃圾回收算法

一 如何判断对象可以回收 1 引用计数法 思路大概为:给对象添加一个引用计数器,每当有一个地方引用它时,计数器值加1;当引用失效时,计数器减1;任何时刻计算器为0的对象就是不可能再被使用...

sen_ye
10分钟前
0
0
Activiti简介(学习总结一)

一、介绍 activiti是使用命令模式设计基于bpmn2.0的一款开源工作流引擎。 工作流简单举例:提交请假申请->经理审批->结束。这就是一个简单流程。activiti支持用户自定义流程。配置各个流程对...

沙shasha
10分钟前
0
0
VCL界面控件DevExpress VCL Controls发布v18.1.3|附下载

DevExpress VCL Controls是 Devexpress公司旗下最老牌的用户界面套包。所包含的控件有:数据录入,图表,数据分析,导航,布局,网格,日程管理,样式,打印和工作流等,让您快速开发出完美、...

Miss_Hello_World
11分钟前
0
0
加米谷大数据培训:云计算、大数据和人工智能之间的关系

一般谈云计算的时候会提到大数据、谈人工智能的时候会提大数据、谈人工智能的时候会提云计算……感觉三者之间相辅相成又不可分割。 一、云计算最初的目标 云计算最初的目标是对资源的管理,管...

加米谷大数据
16分钟前
1
0
java集合元素的默认大小

当底层实现涉及到扩容时,容器或重新分配一段更大的连续内存(如果是离散分配则不需要重新分配,离散分配都是插入新元素时动态分配内存),要将容器原来的数据全部复制到新的内存上,这无疑使...

竹叶青出于蓝
18分钟前
1
0
Java快速开发平台,JEECG 3.7.7闪电版本发布,增加多套主流UI代码生成器模板

JEECG 3.7.7 闪电版本发布,提供5套主流UI代码生成器模板 导读 ⊙平台性能优化,速度闪电般提升 ⊙提供5套新的主流UI代码生成器模板(Bootstrap表单+BootstrapTable列表\ ElementUI列表表单)...

Jeecg
22分钟前
0
0
export 和 module.export 的区别

在浏览器端 js 里面,为了解决各模块变量冲突等问题,往往借助于 js 的闭包把左右模块相关的代码都包装在一个匿名函数里。而 Nodejs 编写模块相当的自由,开发者只需要关注 require,exports,...

孟飞阳
24分钟前
1
0
技术教育的兴起

技术教育的兴起 作者: 阮一峰 1、 有一年,我在台湾环岛旅行。 花莲的海边,我遇到一对台湾青年夫妻,带着女儿在海滩上玩。我们聊了起来。 当时,我还在高校当老师。他们问我,是否觉得台湾...

吕伯文
24分钟前
0
0
Linux服务器下的HTTP抓包分析

说到抓包分析,最简单的办法莫过于在客户端直接安装一个Wireshark或者Fiddler了,但是有时候由于客户端开发人员(可能是第三方)知识欠缺或者其它一些原因,无法顺利的在客户端进行抓包分析,...

mylxsw
29分钟前
0
0
mybatis3-javaapi

sqlSessionFactoryBuilder->sqlSessionFactory->sqlSession<-rowbound<-resultHandler myBatis uses a Java enumeration wrapper for transaction isolation levels, called TransactionIsol......

writeademo
32分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部