一. 监听器
1. 监听某一个事件的发生, 状态的改变。
2. 监听器的内部机制: 其实就是接口回调。
3. Servlet一共有8个监听器。按作用分为三大类: 监听三个作用域的创建和销毁、监听三个作用域属性状态的变更和监听httpSession里面存值状态的变更。
4. 被监听的三个作用域分别是: request(HttpServletRequest)、session(HttpSession)和application(ServletContext)。
二. 监听三个作用域的创建和销毁
1. ServletContextListener监控ServletContext的创建和销毁。
1.1. 项目被服务器(Tomcat服务器)加载的时候创建ServletContext; 项目被服务器(Tomcat服务器)移除或关闭服务器的时候销毁ServletContext。
1.2. 创建名为ServletContextListener的Web工程
1.3. 编写MyServletContextListener.java实现ServletContextListener接口
package com.lywgames.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class MyServletContextListener implements ServletContextListener {
/**
* 项目被服务器(Tomcat服务器)加载的时候调用
*/
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("servletcontext创建");
}
/**
* 项目被服务器(Tomcat服务器)移除的时候调用
*/
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("servletcontext销毁");
}
}
1.4. 在web.xml里配置监听器
1.5. 运行该项目, 监控到servletcontext被创建了
1.6. 关闭服务器, 监控到servletcontext被销毁了
2. ServletRequestListener监控request的创建和销毁。
2.1. 客户端(浏览器)访问服务器上的资源的时候就会有request的创建; 服务器对客户端做出响应的时候就会有request的销毁。
2.2. 客户端(浏览器)访问服务器上的任何资源都会有request的创建, 包括html、jsp和servlet。
2.3. 创建名为ServletRequestListener的Web工程
2.4. 编写MyServletContextListener.java实现ServletRequestListener接口
package com.lywgames.listener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
public class MyServletRequestListener implements ServletRequestListener {
/**
* 有客户端访问服务器资源的时候调用
*/
@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("有request请求");
}
/**
* 服务器对客户端做出响应的时候调用
*/
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("有request销毁了");
}
}
2.6. 创建一个MyServlet.java类
package com.lywgames.listener;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().print("请求Servlet成功。");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
2.7. 创建index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>访问html有request请求</title>
</head>
<body>
<h1>index.html</h1>
</body>
</html>
2.8. 创建index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>访问jsp有request请求</title>
</head>
<body>
<h1>index.jsp</h1>
</body>
</html>
2.9. 在web.xml里配置监听器和Servlet
2.10. 部署项目, 访问index.html、index.jsp和MyServlet都有request的创建和销毁
3. HttpSessionListener监控session的创建和销毁。
3.1. 只要有getSession()方法的调用, 就会有session的创建。访问jsp的时候, 因为jsp页面有session=true(默认也是true)的设置, 所以访问jsp就会有session的创建; 如果设置session=false, 就不会有session的创建。访问Servlet的时候, 如果Servlet里有getSession()的调用, 则会创建session; 如果没有getSession()的调用, 则不会创建session。访问html没有session的创建。超过30分钟或者非正常关闭服务器, 则会销毁session; 正常关闭服务器会序列化session。
3.2. 创建名为HttpSessionListener的Web工程
3.3. 编写MyHttpSessionListener.java实现HttpSessionListener接口
package com.lywgames.listener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class MyHttpSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent hse) {
System.out.println("创建了session");
}
@Override
public void sessionDestroyed(HttpSessionEvent hse) {
System.out.println("销毁了session");
}
}
3.4. 创建MyServlet并调用getSession()方法(如果不调用getSession(), 方法不会创建session)
package com.lywgames.listener;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 调用getSession()方法
req.getSession();
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().print("请求Servlet成功。");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
3.5. 创建index.jsp(如果设置session=false, 不会创建session)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" session="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>访问jsp有session创建</title>
</head>
<body>
<h1>index.jsp</h1>
</body>
</html>
3.6. 创建index.html(请求html不会创建session)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>访问html没有session创建</title>
</head>
<body>
<h1>index.html</h1>
</body>
</html>
3.7. 在web.xml里配置监听器和Servlet
3.8. 部署项目, 访问index.jsp和MyServlet都有session的创建(而且一次会话只会创建一个session)
4. ServletContextListener的作用
4.1. 在servletcontext创建的时候, 完成自己想要的初始化工作。
5. HttpSessionListener可以用来统计在线访问次数。
三. 监听三个作用域中值的添加、替换和移除
1. ServletContextAttributeListener监听servletContext作用域中值的添加、替换和移除。
1.1. 创建名为ServletContextAttributeListener的Web工程
1.2. 创建MyServletContextAttributeListener.java
package com.lywgames.listener;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
public class MyServletContextAttributeListener implements ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent sae) {
System.out.println("servletContext属性被添加进来了");
}
@Override
public void attributeRemoved(ServletContextAttributeEvent sae) {
System.out.println("servletContext属性被移除了");
}
@Override
public void attributeReplaced(ServletContextAttributeEvent sae) {
System.out.println("servletContext属性被替换了");
}
}
1.3. 新建index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>servletContext值的添加,替换和移除</title>
</head>
<body>
<%
application.setAttribute("name", "lisi");
application.setAttribute("name", "zhangsan");
application.removeAttribute("name");
%>
</body>
</html>
1.4. 在web.xml里配置监听器
1.5. 访问index.jsp
2. ServletRequestAttributeListener监听request作用域中值的添加、替换和移除。
2.1. 创建名为ServletRequestAttributeListener的Web工程
2.2. 创建MyServletRequestAttributeListener.java
package com.lywgames.listener;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
public class MyServletRequestAttributeListener implements ServletRequestAttributeListener {
@Override
public void attributeAdded(ServletRequestAttributeEvent hsbe) {
System.out.println("request属性被添加进来了");
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent hsbe) {
System.out.println("request属性被移除了");
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent hsbe) {
System.out.println("request属性被替换了");
}
}
2.3. 新建index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>request值的添加,替换和移除</title>
</head>
<body>
<%
request.setAttribute("name", "lisi");
request.setAttribute("name", "zhangsan");
request.removeAttribute("name");
%>
</body>
</html>
2.4. 在web.xml里配置监听器
2.5. 访问index.jsp
3. HttpSessionAttributeListener监听session作用域中值的添加、替换和移除。
3.1. 创建名为HttpSessionAttributeListener的Web工程
3.2. 创建MyHttpSessionAttributeListener.java
package com.lywgames.listener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent hsbe) {
System.out.println("Session属性被添加进来了");
}
@Override
public void attributeRemoved(HttpSessionBindingEvent hsbe) {
System.out.println("Session属性被移除了");
}
@Override
public void attributeReplaced(HttpSessionBindingEvent hsbe) {
System.out.println("Session属性被替换了");
}
}
3.3. 新建index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>session值的添加,替换和移除</title>
</head>
<body>
<%
session.setAttribute("name", "aobama");
session.setAttribute("name", "zhangsan");
session.removeAttribute("name");
%>
</body>
</html>
3.4. 在web.xml里配置监听器
3.5. 访问index.jsp
四. 监听httpSession里面存值状态的变更(这种监听器不用我们注册)
1. HttpSessionBindingListener监听对象与session绑定和解除绑定的动作。
1.1. 创建名为HttpSessionBindingListener的Web工程
1.2. 创建HttpSessionBindingListenerBean.java
package com.lywgames.listener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
public class HttpSessionBindingListenerBean implements HttpSessionBindingListener {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void valueBound(HttpSessionBindingEvent hsbe) {
System.out.println("对象被绑定进来了");
}
@Override
public void valueUnbound(HttpSessionBindingEvent hsbe) {
System.out.println("对象被解除绑定");
}
}
1.3. 新建一个index.jsp
<%@ page import="com.lywgames.listener.HttpSessionBindingListenerBean"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>监听对象与session绑定和解除绑定的动作</title>
</head>
<body>
<%
HttpSessionBindingListenerBean bean = new HttpSessionBindingListenerBean();
bean.setName("lisisi");
session.setAttribute("bean", bean);
session.removeAttribute("bean");
%>
</body>
</html>
1.4. 访问index.jsp
2. HttpSessionActivationListener用于监听现在session的值是钝化(序列化)还是活化(反序列化)的动作。
2.1. 钝化(序列化): 把内存中的数据, 存储到硬盘上。
2.2. 活化(反序列化): 把硬盘中的数据读取到内存中。
2.3. session中的值可能会很多, 并且我们有很长一段时间不使用这个内存中的值, 那么可以考虑把session的值可以存储到硬盘上[钝化], 等下一次在使用的时候, 在从硬盘上提取出来[活化]。
2.4. 配置session的钝化时间
2.4.1. 在tomcat里面 conf/context.xml 里面配置: 对所有的运行在这个服务器的项目生效。
2.4.2. 在conf/Catalina/localhost/context.xml 配置: 对localhost生效。
2.4.3. 在自己的web工程项目中的 META-INF/context.xml: 只对当前的工程生效。
2.4.4. maxIdleSwap: 钝化时间(以分钟为单位), directory: 钝化路径。
2.5. 创建名为HttpSessionActivationListener的Web工程
2.6. 创建HttpSessionActivationListenerBean.java
package com.lywgames.listener;
import java.io.Serializable;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
public class HttpSessionActivationListenerBean implements HttpSessionActivationListener, Serializable {
private static final long serialVersionUID = 1L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void sessionDidActivate(HttpSessionEvent hse) {
System.out.println("session中的值被活化了...");
}
@Override
public void sessionWillPassivate(HttpSessionEvent hse) {
System.out.println("session中的值被钝化了...");
}
}
2.7. 新建一个index.jsp
<%@page import="com.lywgames.listener.HttpSessionActivationListenerBean"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>session值的钝化/活化</title>
</head>
<body>
<%
HttpSessionActivationListenerBean bean = new HttpSessionActivationListenerBean();
bean.setName("lisisi");
session.setAttribute("bean", bean);
%>
<h1>index.jsp</h1>
</body>
</html>
2.8. 新建一个list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>session值的钝化/活化</title>
</head>
<body>
${bean.name}
</body>
</html>
2.9. 在META-INF目录下新建一个context.xml
2.10. 访问index.jsp
2.11. 等待一分钟后, session中存入的对象钝化了。同时进入D:\software\eclipse\applicationTomcat70\Tomcat 7.0\work\Catalina\localhost\HttpSessionActivationListener\lywgames目录下查看:
2.12. 访问list.jsp, 得到活化后的session数据