[Java] JSP笔记 - Listener 监听器
Java Web 开发时,可以使用 Listener 来监听来监听一些事件,从而实现一些功能。实际上这个监听器,原理就是 Delphi 中大家常用的各种事件。
1. 那么,监听器的主要用途用哪些呢:
- 统计在线人数和在线用户
- 系统启动时加载初始化信息: 包括各种缓存、共公的定制器、数据库链接等等
- 统计网站访问量
- 路Spring结合
2. 监听器可以按监听的对象来分类:
- ServletContext (ServletContextListener):用于监听应用程序环境对象的事件监听器(一个项目中只有一个),可以用来启动定时器、初始化全局对象。
- HttpSession (HttpSessionListener): 用于监听用户会话对象的事件监听器。
- ServletRequest (ServletRequestListener): 用于监听请求消息对象的事件监听器,可以用来读取参数,记录访问历史等。
3. 按监听的事件来划分:
- 监听域对象自身的创建和销毁的事件监听器(2中的三类)。
- 监听域对象中的属性的增加和删除的事件监听器: ServletContextAttributeListener、HttpSessionAttributeListener、ServletRequestAttributeListener。
- 监听绑定到 HttpSession 域中的某个对象的状态的事件监听器。它分为这几种状态:
- 绑定: 将状态通过 set 保存到 Session 中。
- 解除绑定 : 使用 remove 删除状态。
- 钝化: 将 session 对象持久化到存储设备上。(Session本身是存在于服务器内存中。Session 钝化机制由SessionManager管理: 第一种管理器是 org.apache.catalina.session.StandardManger, 当 tomcat服务器被关闭或重启时,tomcat服务器会将当前内存中的session钝化到服务器文件系统中。另一种情况是web应用程序被重新加载时,内存中的session对象也会被钝化到服务器的文件系统中。钝化后的文件被保存到 Tomcat安装路径下的 /work/Catalina/hostname/applicationname/SESSION.ser 中。第二种管理器是 org.apache.catalina.session.Persistentmanager ,它是在钝化基础上进行了扩张,前两种情况和StandardManager相同,第三种情况,可以配置主流内存的Session对象数目,将不常用的Session对象保存到文件系统或数据库中,当要使用时再进行加载。默认情况下,Tomcat提供两个钝化驱动类:org.apache.Catalina.FileStore 和 org.apache.Catalina.JDBCStore。)
- 活化: 从存储设备上恢复。
绑定、解除绑定使用 HttpSessionBindingListener 接口, 钝化、活化使用 HttpSessionActivationListener 接口。这两个监听器不需要注册。
4. 注册方法
在 Servlet 3.0 之前的版本中, 需要在 web.xml 中进行注册。也比较简单,就是一个声明:
<listener>
<listener-class>com.imooc.listener.FirstListener</listener-class>
</listener>
在 servlet 3.0 之后, 可以不再到 web.xml 中进行配置, 直接给监听器类加上注解 @WebListener 就可以。
package com.imooc.listener; import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener; import com.demo.utils.UserManager; @WebListener
public class FirstListener implements ServletContextListener { @Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("contextInitialized");
} @Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("contextDestroyed");
} }
5. 示例: 使用监听器实现的显示在线用户列表
效果如下:

此示例综合用到了这些技术: jstl和el标签、jsp脚本、listener监听器 、单例全局对象、javabean、线程同步。
主要代码:
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" %>
<%@ page import="com.demo.utils.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<!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>欢迎访问</title>
</head>
<body>
<% request.setAttribute("users", UserManager.getInstance().getItems()); %>
<h1>在线用户列表</h1><hr>
<!-- 使用 JSTL 输出在线用户列表 -->
<table>
<tr><th width="80px">name</th><th width="320px">sessionID</th><th width="180px">IP地址</th><th>登录时间</th><tr>
<c:forEach var="user" items="${requestScope.users}">
<tr>
<td>${user.name}</td>
<td>${user.sessionID}</td>
<td>${user.ipaddr}</td>
<td>${user.firstTimeStr}</td>
</tr>
</c:forEach></table>
<br>
当前在线: <c:out value="${fn:length(users)}"></c:out>人。
</body>
</html>
RequestListener.java
package com.demo.listener; import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest; import com.demo.utils.User;
import com.demo.utils.UserManager; @WebListener
public class RequestListener implements ServletRequestListener { @Override
public void requestDestroyed (ServletRequestEvent sre) {
System.out.println("requestDestroyed");
} @Override
public void requestInitialized (ServletRequestEvent sre) {
HttpServletRequest req = (HttpServletRequest) sre.getServletRequest();
UserManager mgr = UserManager.getInstance();
// 用户请求时,如果 mgr 中不存在当前会放原 sessionID, 则新建一个User对象,加入管理器中
if (!mgr.existSession(req.getSession().getId())) {
User item = new User();
item.setFirstTime(System.currentTimeMillis());
item.setIpaddr(req.getRemoteAddr() + ":" + req.getRemotePort());
item.setName(req.getParameter("name"));
item.setSessionID(req.getSession().getId());
mgr.addSession(item);
}
System.out.println("requestInitialized: " + req.getRequestURI() + ", " + req.getParameter("name"));
}
}
SessionListener.java
package com.demo.listener; import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener; import com.demo.utils.UserManager; @WebListener
public class SessionListener implements HttpSessionListener { @Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("sessionCreated");
} @Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("sessionDestroyed");
// Session 失效时,从列表中删除
UserManager.getInstance().removeSession(se.getSession().getId());
}
}
UserManager.java
package com.demo.utils; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; /** 用户管理 */
public class UserManager {
private static UserManager Instance; private Map<String, User> items = new HashMap<String, User>(); /** 单例 */
public static UserManager getInstance() {
if (Instance == null)
Instance = new UserManager();
return Instance;
} private UserManager() {} // 由于 Web 请求是并发的,对列表的操作,需要使用 synchronized 关键字线程同步,防止出现异常
public synchronized boolean existSession(String sessionID) {
return items.containsKey(sessionID);
} public synchronized void addSession(User v) {
if (v != null)
items.put(v.getSessionID(), v);
} public synchronized void removeSession(String sessionID) {
if (items.containsKey(sessionID))
items.remove(sessionID);
} public int size() {
return items.size();
} public synchronized User get(String sessionID) {
return items.get(sessionID);
} public synchronized List<User> getItems() {
ArrayList<User> list = new ArrayList<User>();
for (Map.Entry<String, User> entry : items.entrySet())
list.add(entry.getValue());
return list;
}
}
User.java
package com.demo.utils; import java.io.Serializable;
import java.text.SimpleDateFormat; /** 用户对象 Java Bean */
public class User implements Serializable {
private static final long serialVersionUID = 1L; private String name;
private String sessionID;
private String ipaddr;
private long firstTime; public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSessionID() {
return sessionID;
}
public void setSessionID(String sessionID) {
this.sessionID = sessionID;
}
public String getIpaddr() {
return ipaddr;
}
public void setIpaddr(String ipaddr) {
this.ipaddr = ipaddr;
}
public long getFirstTime() {
return firstTime;
}
public void setFirstTime(long firstTime) {
this.firstTime = firstTime;
} public String getFirstTimeStr() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(firstTime).toString();
}
}
完整项目下载:
链接: http://pan.baidu.com/s/1jI2fVqm 密码: wjr5
【感谢】
慕课网、Fcming 老师
[Java] JSP笔记 - Listener 监听器的更多相关文章
- java新手笔记27 监听器类
1.外部类监听 package com.yfs.javase; import java.awt.Button; import java.awt.FlowLayout; import java.awt. ...
- Java中的Listener 监听器
Listener的定义与作用 监听器Listener就是在application,session,request三个对象创建.销毁或者往其中添加修改删除属性时自动执行代码的功能组件. Listener ...
- JAVA JSP笔记
一.jsp加载项目中资源图片 如果直接将静态页面写的代码copy到jsp中,你会发现图片都无法加载. 获取代码: String path = request.getContextPath(); Str ...
- [Java] JSP笔记 - 自定义标签
自定义标签的创建步骤: 自定义标签的四大功能: 自定义标签的类结构: 在 1.0 中呢, 可以将 <body-content> 的值设置为 JSP, 2.0中则不允许在自定义标签体中出现j ...
- [Java] JSP笔记 - EL、JSTL 常用标签
一. 什么是 EL 语言 表达式语言(EL)是 JSP 2.0 引入的一种计算和输出 Java 对象的简单语言. 二.EL 语言的作用 为了使JSP写起来更加简单.表达式语言的灵感来自于 ECMASc ...
- [Java] JSP笔记 - Filter 过滤器
一.什么是Web过滤器 Servlet API 很久以前就已成为企业应用开发的基石,而 Servlet 过滤器则是对 J2EE 家族的相对较新的补充. Servlet 过滤器是可插入的 Web 组件, ...
- [Java] JSP笔记 - Java Bean
一. Java Bean 是什么? Java Bean 其实就是一个符合特定规则的 Java Class.这些规则包括: 使用 public 声明的公用类 属性使用public 的get,set方法访 ...
- 【Servlet】Java Serlvet Listener 监听器
Listener监听器 Servlet规范中定义的一种特殊的组件,用来监听Servlet容器产生的事件并进行相应的处理 容器产生的事件分类 - 生命周期相关的事件 - 设置和删除Attribute数据 ...
- .jsp文件的使用和理解以及一些小练习和Listener监听器
什么是 jsp,它有什么用? jsp 的全换是 java server pages.Java 的服务器页面.jsp 的主要作用是代替 Servlet 程序回传 html 页面的数据.因为 Servle ...
随机推荐
- 国产方法论之 ReDoIt -- 惟思捷
最近上了PMP课程,感觉受益匪浅,思路有被打开. 很同意一个观点“国人很擅长做事,但是不擅长总结出解决问题的通用框架和方法论”. 为了能提高中小企业生产力我最近成了一个小的软件咨询公司取名“惟思捷”, ...
- apachetop 实时监测web服务器运行状况
apachetop 实时监测web服务器运行状况 我们经常会需要知道服务器的实时监测服务器的运行状况,比如哪些 URL 的访问量最大,服务器每秒的请求数,哪个搜索引擎正在抓取我们网站?面对这些问题 ...
- Newtonsoft.Json, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b9a188c8922137c6
未能加载文件或程序集“Newtonsoft.Json, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b9a188c8922137c6”或它的某一个 ...
- 编译安装mysql
参考:http://www.centoscn.com/CentosServer/www/2015/0422/5245.html 安装mysql5.6.17 1.按照标准需要给mysql创建所属用户和用 ...
- 萌新笔记——git的问题(error: object file .git/objects/* is empty...)的解决方案及对git版本库文件的了解
由于操作不当,导致git版本库出了大问题,如下所示: error: object file .git/objects/8b/61d0135d3195966b443f6c73fb68466264c68e ...
- 萌新笔记——linux下(ubuntu)反删除(误删恢复)与回收站制作
刚刚有个小伙伴不小心删了他写了好几的天代码,为他心疼之余帮他找回了文件. 想到我之前也常常误删一些文件,就干脆分享一下我的反删除方法,并说说我做的回收站(好low的,求大神指点) 首先是反删除软件ex ...
- linux基本知识0
linux的基本原则: 1.有目的单一的小程序组成,组合小程序完成复杂任务. 2.一切皆文件 3.尽量避免捕获用户接口 4.配置文件保存为纯文本格式 CLI接口: 命令提示符,prompt,bash ...
- 中大东校小米路由器mini实现inode上网,ipv6 wifi【中大】【东校】【inode】【ipv6】
还有不到4个月就要毕业了,前几天半夜没事捣鼓小米路由没想到竟然实现了wifi的ipv6. 正好又安利了同学一台小米路由mini,从刷机到inode到ipv6全搞了一遍. 这里将教程写出来,服务学弟妹. ...
- Jquery UI
jQuery UI简介 jQuery UI包含了许多维持状态的小部件(Widget),因此,它与典型的 jQuery 插件使用模式略有不同.所有的 jQuery UI 小部件(Widget)使用相同的 ...
- java 静态内部类小总结
内部类是指在一个外部类的内部再定义一个类.内部类作为外部类的一个成员,并且依附于外部类而存在的.内部类可为静态,可用protected和private修饰(而外部类只能使用public和缺省的包访问权 ...