Java监听器介绍和入门
Web服务器可以通过监听器对ServletContext、HttpServlet、ServletRequest这三个域对象进行监听。下面是监听器实现学习的路线

配置监听器
以ServletContextListener为例来实现监听器的基本功能
先创建一个Java类,然后使用ServletContextListener接口
public void contextInitialized(ServletContextEvent sec)该方法是监听器的启动方法
public void contextDestroyed(ServletContextEvent sec)当项目停止或者被移除,该方法就销毁监听器,也就是俗称的销毁方法
package com.zhumeng.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class MyFirstListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent sec) {// TODO Auto-generated method stub System.out.println("被销毁了"); }
@Override
public void contextInitialized(ServletContextEvent sec) { // TODO Auto-generated method stub System.out.println("启动"); }
}
写Java类监听器后,就要对监听器进行配置,通过Web项目中的xml文件来配置
1.默认项目的初始页面为index.jsp(不用创建)
2.使用listener标签,填写格式为”包名”+”监听器类名”。非常简单的配置方式
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>WebListenerDemo2</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<listener>
<listener-class>com.zhumeng.listener.MyFirstListener</listener-class>
</listener>
</web-app>
接下来就可以启动服务器来查看控制台输出的内容
显示”启动”表示该监听器的初始化方法正常执行,也说明监听器启动配置成功。接下来就可以停止服务器,控制台就显示出”被销毁了”,说明监听器被正常销毁


监听器的注册和销毁顺序
Web项目中通常有多个监听器,监听器的实现和销毁都是有顺序的,这些顺序和xml中配置监听器的位置有关系

监听器的分类
请参考思维导图的解析
ServletContext:
在xml文件中设置初始化参数,设置好之后可以通过ServletContextListener中的ContextInitialized方法来读取xml文件中设置好的参数,然后存放到ServletContext对象中。这样就能使Web项目一启动就可以把必要的信息存储在ServletContext中。
当关闭的时候就可以对一些链接,比如数据库链接,文件链接进行处理
在xml文件中配置参数可以通过<context-param>标签来实现,<param-name>参数名、<param-value>参数值。这样设置的好处就是以后维护方便,只需要在xml文件中修改参数即可。
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>WebListenerDemo2</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<listener>
<listener-class>com.zhumeng.listener.MyServletContextListener</listener-class>
</listener>
<context-param>
<param-name>AppName</param-name>
<param-value>Listener</param-value>
</context-param>
<context-param>
<param-name>version</param-name>
<param-value>1.0</param-value>
</context-param>
</web-app>
package com.zhumeng.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent sce)
{
// TODO Auto-generated method stub String appName = (String) sce.getServletContext().getAttribute("appName"); String version = (String) sce.getServletContext().getAttribute("version"); System.out.println("销毁名称:"+appName); System.out.println("销毁版本:"+version); }
@Override
public void contextInitialized(ServletContextEvent sce)
{ String appName = sce.getServletContext().getInitParameter("AppName"); String version = sce.getServletContext().getInitParameter("version"); sce.getServletContext().setAttribute("appName", appName); sce.getServletContext().setAttribute("version", version); System.out.println("启动名称:"+appName); System.out.println("启动版本:"+version); }}
通过一个Servlet类来测试是否将数值存入到ServletContext域中
package com.imooc.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** * Servlet implementation class MyServletContextListener */
@WebServlet("/MyServletContextListener") public class MyServletContextListener extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
Object name = this.getServletContext().getAttribute("appName");
System.out.println(name);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
doGet(request, response);
}
}

注意:这里销毁的是不是初始化参数,而是保存到ServletContext域中的信息。
HttpSession:
当用户第一次通过浏览器对服务器进行访问的时候,服务器就会创建一个会话对象(HttpSession)。这个会话存储的是用户的专有信息,例如用户名,密码、权限等等。一个会话对象就代表一个用户,也就是说当一个用户离开后对应的会话对象也被消除
HTTPSession对应的接口是HttpSessionListener
package com.zhumeng.listener;
import java.util.Date;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class MyHttpSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent hrc) {
// 获得session编号
String id = hrc.getSession().getId();
//获取创建时间
Date time = new Date(hrc.getSession().getCreationTime());
System.out.println("创建编号:"+id);
System.out.println("创建时间:"+time);
}
@Override
public void sessionDestroyed(HttpSessionEvent hrc) {
// 监听销毁对象编号
String id = hrc.getSession().getId();
System.out.println("销毁编号:"+id);
}
}
<?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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>WebListenerDemo2</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<listener>
<listener-class>com.zhumeng.listener.MyHttpSessionListener</listener-class>
</listener>
<session-config>
<session-timeout>1</session-timeout>
</session-config>
</web-app>
<session-config>标签是设置1分钟后会话对象自动销毁。配置好xml后还要创建一个jsp页面,内容空白即可。
当使用两款不同的浏览器访问index.jsp页面的时候,就创建了两个不同的id。1分钟后两个id自动销毁。

ServletRequest:
用户每一次发出一个请求,都会生成一个请求对象。通过监听器可以监听请求对象,然后对用户请求的内容进行分析
因为获得的是Http请求对象,所以要进行转型。
获得请求路径的目的是可以知道请求的资源或者操作的内容等等
package com.zhumeng.listener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
public class MyServletRequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sce) {
// TODO Auto-generated method stub
System.out.println("销毁!");
}
@Override
public void requestInitialized(ServletRequestEvent sce) {
HttpServletRequest request = (HttpServletRequest)sce.getServletRequest();
// 获得请求路径
String path = request.getRequestURI();
String par = request.getParameter("par");
System.out.println("初始化path:"+path);
System.out.println("初始化请求参数:"+par);
}
}
<?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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>WebListenerDemo2</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<listener>
<listener-class>com.zhumeng.listener.MyServletRequestListener</listener-class>
</listener>
</web-app>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试</title>
</head>
<body>
<h1>首页</h1>
<label>
<a href="index2.jsp?par=java" target="_blank">初始化</a>
</label>
</body>
</html>
index2.jsp的内容空白即可,主要是体现index1发出请求传递参数的时候,监听器能监听到并且获取参数。值得一提的是,初始化结束后就立刻执行销毁方法,根之间的监听器有点差别。

域对象中属性的创建、替换和消除事件监听器
这类监听器主要对对象中的指定的属性进行监听,一旦发现该属性发送变化,例如增加、删除、修改等,就会做出相对应的操作
package com.zhumeng.listener;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
public class MyServletContextAttributeListener implements ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent sce) {
// 属性添加
System.out.println("add...name:"+sce.getName());
System.out.println("add...value:"+sce.getValue());
System.out.println();
}
@Override
public void attributeRemoved(ServletContextAttributeEvent sce) {
//属性删除
System.out.println("removed...name:"+sce.getName());
System.out.println("removed...value:"+sce.getValue());
System.out.println();
}
@Override
public void attributeReplaced(ServletContextAttributeEvent sce) {
// 属性修改
System.out.println("replaced...name:"+sce.getName());
System.out.println("replaced...value:"+sce.getValue());
System.out.println();
}
}
<?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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>WebListenerDemo2</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<listener>
<listener-class>com.zhumeng.listener.MyServletContextAttributeListener</listener-class>
</listener>
</web-app>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="index3.jsp">点击</a>
<a href="index4.jsp">删除</a>
<a href="index5.jsp">修改</a>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
application.setAttribute("java", "java入门到放弃");
application.setAttribute("C","C入门到放弃");
application.setAttribute("python", "py入门到放弃");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>属性测试</title>
</head>
<body>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%
application.removeAttribute("java");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
application.setAttribute("java", "精通");
Object java = application.getAttribute("java");
Object C = application.getAttribute("C");
Object python = application.getAttribute("python");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
</body>
</html>