文档章节

javaweb开发之Listener

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

一、 监听器

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>


© 著作权归作者所有

共有 人打赏支持
小米米儿小
粉丝 39
博文 114
码字总数 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
线程中无法通过spring注入services为null

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

深谷不见幽兰
2013/12/03
6.3K
4
Javaweb组件--Listener

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

a1ie2
2017/11/21
0
0
开源会议管理系统--CoolMeeting

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

Java-大神
2017/09/01
652
0

没有更多内容

加载失败,请刷新页面

加载更多

python生成HTML报告

# -*- coding=utf-8 -*-# author=zyqimport timeclass Template(object): '''html报告''' HTML_TEMP=''' <!DOCTYPE html> <html lang="en"> <head......

小白兔_球球
18分钟前
1
0
模型融合资料汇总

https://blog.csdn.net/u012526003/article/details/79109418https://blog.csdn.net/willduan1/article/details/73618677https://blog.csdn.net/wstcjf/article/details/77989963?utm_so......

KYO4321
20分钟前
1
0
热更步骤

根据官方文档: http://docs.cocos.com/creator/manual/zh/advanced-topics/hot-update.html version_generator.js文件放到项目根目录下 注意步骤的顺序: 1.构建 2.根据构建目录运行下面命令...

Valiancer
20分钟前
2
0
小程序重写CheckBox样式

CheckBox /* 重写 checkbox 样式 *//* 未选中的 背景样式 */checkbox .wx-checkbox-input{ border-radius: 50%; width: 40rpx; height: 40rpx;}/* 选中后的 背景样式...

originDu
24分钟前
1
0
mysql自动安装脚本

[root@localhost_04 ~]# cat mysql.sh #!/bin/bash# "################检查本机安装mysql的基本条件########################"echo "Checking  user :"d=`id -u`if [ $d ......

芬野de博客
38分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部