Java监听器详解

发布一下 0 0

一.监听器的定义

是指专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生变化时,立即采取相应的行动。

Web应用当中监听器是什么?

Java监听器详解

web监听器由servlet规范提供的,它可以监听客户端的请求,服务端的操作,监听的对象包括ServletContext,HttpSession,ServletRequest三个预对象(内置对象),分别对应aplication,session,request

Java监听器详解

内置对象

JSP中一共预先定义了9个这样的内置对象,分别为:request、response、session、application、out、pagecontext、config、page、exception

内置对象(又叫隐含对象)特点:

由JSP规范提供,不用编写者实例化。

通过Web容器实现和管理

所有JSP页面均可使用

只有在脚本元素的表达式或代码段中才可使用(<%=使用内置对象%>或<%使用内置对象%>)

request对象

request 对象是 javax.servlet.httpServletRequest类型的对象。 该对象代表了客户端的请求信息,主要用于接受通过HTTP协议传送到服务器的数据。(包括头信息、系统信息、请求方式以及请求参数等)。request对象的作用域为一次请求。

session对象

session 对象是由服务器自动创建的与用户请求相关的对象。服务器为每个用户都生成一个session对象,用于保存该用户的信息,跟踪用户的操作状态。session对象内部使用Map类来保存数据,因此保存数据的格式为 “Key/value”。 session对象的value可以使复杂的对象类型,而不仅仅局限于字符串类型。

application对象

application 对象可将信息保存在服务器中,直到服务器关闭,否则application对象中保存的信息会在整个应用中都有效。与session对象相比,application对象生命周期更长,类似于系统的“全局变量”。

Web监听器概念

Servlet规范中定义的一种特殊类

用于监听ServletContext,HttpSession和ServletRequest等域对象的创建与销毁事件用于监听域对象的属性发生修改的事件可以在事件发生前,发生后做一些必要的处理

二.Web监听器的用途

1.统计在线人数和在线用户

2.系统启动时加载初始化信息

3.统计网站访问量

4.跟Spring结合

三.第一个Web监听器

实现步骤

1.创建一个实现监听器接口的类

Java监听器详解

Java监听器详解

代码如下:
package com.java.listener;

import javax.servlet.ServletContextEvent;

import javax.servlet.ServletContextListener;

/**

* @author : xiayj

* @date : 2019/8/3 17:58

*/

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");

}

}

2.配置web.xml进行注册

把监听对象放到web.xml中

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"

version="4.0">

<listener>

<listener-class>com.java.listener.FirstListener</listener-class>

</listener>

<welcome-file-list>

<welcome-file>index.jsp</welcome-file>

</welcome-file-list>

<login-config>

<auth-method>BASIC</auth-method>

</login-config>

</web-app>

启动tomcat,控制台输出如下说明当web应用启动时会自动创建一个application对象,且只有一个

Java监听器详解

关闭tomcat,如下表示当前应用销毁

Java监听器详解

监听器的启动顺序

Java监听器详解

四.监听器的分类

1.按监听的对象划分

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

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

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

2.按监听的事件划分

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

Java监听器详解

ServletContext的创建与销毁

ServletContext实现了ServletContextListener用于监听它的创建与销毁事件,一个web项目可以定义多个ServletContextListener,但一个web项目只有一个ServletContext对象。

ServletContextListener有两个事件处理方法,这两个方法都会传入ServletContextEvent事件对象,可以获取ServletContext对象以及一些初始化参数。ServletContextListener主要用途:可以做定时器,加载全局属性对象,创建全局的数据库连接,加载一些缓存信息。

Java监听器详解

web.xml配置如下

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"

version="4.0">

<listener>

<listener-class>com.java.listener.FirstListener</listener-class>

</listener>

<welcome-file-list>

<welcome-file>index.jsp</welcome-file>

</welcome-file-list>

<login-config>

<auth-method>BASIC</auth-method>

</login-config>

<!--配置初始化参数-->

<context-param>

<param-name>initParam</param-name>

<param-value>listener</param-value>

</context-param>

</web-app>

代码实现:

package com.java.listener;

import javax.servlet.ServletContextEvent;

import javax.servlet.ServletContextListener;

/**

* @author : xiayj

* @date : 2019/8/3 17:58

*/

public class FirstListener implements ServletContextListener {

//ServletContext是上下文对象,当web应用启动时创建,web应用销毁时销毁

@Override

public void contextInitialized(ServletContextEvent sce) {

//项目启动时获取初始化参数

String initParam = sce.getServletContext().getInitParameter("initParam");

System.out.println("contextInitialized : initParam = " + initParam);

}

@Override

public void contextDestroyed(ServletContextEvent sce) {

//销毁主要用于当数据库连接关闭时释放一些不必要的资源

System.out.println("contextDestroyed");

}

}

项目启动结果如下,说明当项目启动时就加载了在web.xml中配置的参数

HttpSession的创建与销毁

与ServletContext类似,HttpSession实现了HttpSessionListener用于监听它的创建与销毁事件,一个web项目可以定义多个HttpSessionListener,但一个web项目只有一个HttpSession对象。HttpSessionEvent事件对象,可以获取当前被创建的HttpSession对象。HttpSessionListener主要用途:统计在线人数,记录访问日志。

Session创建:用户打开浏览器第一次访问我们应用时,这次会话web容器会分配一个session,可以在session中保存一些信息

Session销毁:1.手动点退出,关闭服务器2.关闭浏览器一段时间直到session过期3.不关闭浏览器,session超时

实现HttpSessionListener:

package com.java.listener;

import javax.servlet.http.HttpSessionEvent;

import javax.servlet.http.HttpSessionListener;

/**

* @author : xiayj

* @date : 2019/8/4 16:59

*/

public class MyHttpSessionListener implements HttpSessionListener {

@Override

public void sessionCreated(HttpSessionEvent se) {

System.out.println("sessionCreated");

}

@Override

public void sessionDestroyed(HttpSessionEvent se) {

System.out.println("sessionDestroyed");

}

}

web.xml文件加如下配置

<!--配置session超时时间,1表示1分钟0表示没有超时限制--><session-config>    <session-timeout>1</session-timeout></session-config>1234

访问项目

Java监听器详解

控制台输出如下Listener监听到session创建

Java监听器详解

等一分钟后,监听到session被销毁

Java监听器详解

ServletRequest的创建与销毁

ServletRequest实现了ServletRequestListener用于监听它的创建与销毁事件,一个web项目可以定义多个ServletRequestListener,但一个web项目只有一个ServletRequest对象。ServletRequestListener主要用途:读取request里的参数,记录访问历史,路径。

Java监听器详解

实现ServletRequestListener

package com.java.listener;

import javax.servlet.ServletRequestEvent;

import javax.servlet.ServletRequestListener;

/**

* @author : xiayj

* @date : 2019/8/4 17:54

*/

public class MyServletRequestListener implements ServletRequestListener {

@Override

public void requestInitialized(ServletRequestEvent sre) {

//获取当前的请求参数

String name = sre.getServletRequest().getParameter("name");

System.out.println("requestInitialized");

}

@Override

public void requestDestroyed(ServletRequestEvent sre) {

System.out.println("requestDestroyed");

}

}

Web.xml中增加监听器配置信息

<listener>

<listener-class>com.java.listener.MyServletRequestListener</listener-class>

</listener>

启动项目,打开浏览器,查看控制台如下,可知request监听到了用户的访问请求,并在请求结束后销毁

Java监听器详解

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

Java监听器详解

代码实现:
新建三个类

package com.java.listener;

import javax.servlet.ServletRequestAttributeEvent;

import javax.servlet.ServletRequestAttributeListener;

/**

* @author : xiayj

* @date : 2019/8/10 17:18

*/

public class MyServletRequestAttributeListener implements ServletRequestAttributeListener {

@Override

public void attributeAdded(ServletRequestAttributeEvent srae) {

//可知是什么对象添加了什么属性,移除了什么属性 System.out.println("ServletRequest_attributeAdded:"+srae.getName());

}

@Override

public void attributeRemoved(ServletRequestAttributeEvent srae) {

System.out.println("ServletRequest_attributeRemoved:"+srae.getName());

}

@Override

public void attributeReplaced(ServletRequestAttributeEvent srae) {

System.out.println("ServletRequest_attributeReplaced:"+srae.getName());

}

}

package com.java.listener;

import javax.servlet.http.HttpSessionAttributeListener;

import javax.servlet.http.HttpSessionBindingEvent;

/**

* @author : xiayj

* @date : 2019/8/10 16:55

*/

public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener {

@Override

public void attributeAdded(HttpSessionBindingEvent se) {

System.out.println("HttpSession_attributeAdded:"+se.getName());

}

@Override

public void attributeRemoved(HttpSessionBindingEvent se) {

System.out.println("HttpSession_attributeRemoved:"+se.getName());

}

@Override

public void attributeReplaced(HttpSessionBindingEvent se) {

System.out.println("HttpSession_attributeReplaced:"+se.getName());

}

}

package com.java.listener;

import javax.servlet.ServletContextAttributeEvent;

import javax.servlet.ServletContextAttributeListener;

/**

* @author : xiayj

* @date : 2019/8/10 16:52

*/

public class MyServletContextAttributeListener implements ServletContextAttributeListener {

@Override

public void attributeAdded(ServletContextAttributeEvent scae) {

System.out.println("ServletContext_attributeAdded:"+scae.getName());

}

@Override

public void attributeRemoved(ServletContextAttributeEvent scae) {

System.out.println("ServletContext_attributeRemoved:"+scae.getName());

}

@Override

public void attributeReplaced(ServletContextAttributeEvent scae) {

System.out.println("ServletContext_attributeReplaced:"+scae.getName());

}

}

Web.xml文件中注册监听器

<listener>

<listener-class>com.java.listener.MyHttpSessionAttributeListener</listener-class>

</listener>

<listener>

<listener-class>com.java.listener.MyServletContextAttributeListener</listener-class>

</listener>

<listener>

<listener-class>com.java.listener.MyServletRequestAttributeListener</listener-class>

</listener>


创建新增各个属性值得jsp界面,为了方便在每个页面都加上了初始化,销毁的按钮

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<html>

<head>

<title>这是myweb应用</title>

</head>

<body>

你好!这是一个listener

<button onclick="location.href='<%=request.getContextPath()%>/init.jsp';">Init</button>

<button onclick="location.href='<%=request.getContextPath()%>/destory.jsp';">Destory</button>

</body>

</html>

init.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServletPath();

//添加属性,让Listener监听执行attributeAdded方法

request.setAttribute("requestName","requestValue");

request.getSession().setAttribute("sessionName","sessionValue");

request.getSession().getServletContext().setAttribute("contextName","contextValue");

%>

<html>

<head>

<title>Title</title>

</head>

<body>

这是初始化值得界面

<button onclick="location.href='<%=request.getContextPath()%>/init.jsp';">Init</button>

<button onclick="location.href='<%=request.getContextPath()%>/destory.jsp';">Destory</button>

</body>

</html>

destory.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServletPath();

//移除属性,让Listener监听执行attributeRemoved方法

request.removeAttribute("requestName");

request.getSession().removeAttribute("sessionName");

request.getSession().getServletContext().removeAttribute("contextName");

%>

<html>

<head>

<title>Title</title>

</head>

<body>

这是销毁界面

<button onclick="location.href='<%=request.getContextPath()%>/init.jsp';">Init</button>

<button onclick="location.href='<%=request.getContextPath()%>/destory.jsp';">Destory</button>

</body>

</html>

超时时间改为0

<!--配置session超时时间,1表示1分钟0表示没有超时限制--><session-config>    <session-timeout>0</session-timeout></session-config>

打开主页面

Java监听器详解

点击init,控制台输出如下

Java监听器详解

再次点击init

Java监听器详解

点击destory,属性被移除,request对象因为已经被销毁了,域中已没有requestName属性,所以没有移除信息

Java监听器详解

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

Java监听器详解

绑定:通过getSession().setAttribute将对象保存到session对象中

解除绑定:通过getSession().removeAttribute将对象从session对象中移除

钝化:将session对象持久化到存储设备上

活化:将session对象从存储设备上恢复

Java监听器详解

Java监听器详解

Java监听器详解

Java监听器详解

代码实现:

新建user类

package com.java.entity;

import javax.servlet.http.HttpSessionActivationListener;

import javax.servlet.http.HttpSessionBindingEvent;

import javax.servlet.http.HttpSessionBindingListener;

import javax.servlet.http.HttpSessionEvent;

import java.io.Serializable;

/**

* @author : xiayj

* @date : 2019/8/17 16:09

*/

/** 想要钝化或活化必须实现Serializable接口*/

public class User implements HttpSessionBindingListener, HttpSessionActivationListener, Serializable {

private String username;

private String password;

/** 对象绑定执行*/

@Override

public void valueBound(HttpSessionBindingEvent event) {

System.out.println("valueBound Name:"+event.getName());

}

/** 对象解除绑定执行*/

@Override

public void valueUnbound(HttpSessionBindingEvent event) {

System.out.println("valueUnbound Name:"+event.getName());

}

/** 钝化*/

@Override

public void sessionWillPassivate(HttpSessionEvent se) {

System.out.println("sessionWillPassivate"+se.getSource());

}

/** 活化*/

@Override

public void sessionDidActivate(HttpSessionEvent se) {

System.out.println("sessionDidActivate"+se.getSource());

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

}

绑定/解除绑定测试:

在init文件里增加如下:

//将用户实例放到session中

request.getSession().setAttribute("currentUser",new com.java.entity.User());

在destory文件里增加如下:

request.getSession().removeAttribute("currentUser");

启动项目,打开首页:

点击init和destory,控制台分别输出如下,表明当对象实现HttpSessionBindingListener接口后,只要对象被session绑定,就会触发事件,执行valueBound方法,当解除绑定后,执行valueUnBound方法

钝化/活化测试

启动tomcat,打开项目,可以看到控制台已经创建session

点击init,可以看到session中保存了几个属性值

关闭tomcat,控制输出如下,sessionWillPassivateorg.apache.catalina.session.StandardSessionFacade@1e7c7811 就是session钝化的输出,StandardSession是默认的钝化管理器

钝化的文件保存位置如下

在首页新增如下:

<!-- 在首页获取用户对象 正常情况下因为tomcat已关闭,session中用户对象应该已被销毁,

但因为实现了HttpSessionActivationListener接口,tomcat重新启动时会活化保存的session文件-->

<%=request.getSession().getAttribute("currentUser")%>

你好!这是一个listener

<button onclick="location.href='<%=request.getContextPath()%>/init.jsp';">Init</button>

<button onclick="location.href='<%=request.getContextPath()%>/destory.jsp';">Destory</button>

重启tomcat,控制台输出如下:

打开首页,可以看到之前钝化的user对象被输出

Ps:如果出现可以活化,但是无法钝化的问题即重启tomcat没有调用 sessionDidActivate()方法,浏览器端也获取不到重启前存入的对象

这是因为每次重启tomcat会将如下目录删除并重新生成,之前钝化的session文件也会被一起删除

解决方法:在tomcat安装目录下conf/context.xml配置文件里增加如下配置,directory里是自定义的session文件存储路径

<Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true">

<Store className="org.apache.catalina.session.FileStore" directory="D:\tomcat\session"/>

</Manager>

在Servlet3.0版本以上提供@WebListener注解将一个实现了特定监听器接口(比如ServletContextListener,HttpSessionListener)的类定义为监听器,这样在web应用中使用监听器时不需要在web.xml文件中配置监听器的相关描述信息,感兴趣的可以自己去研究一下,用法差不多。

版权声明:内容来源于互联网和用户投稿 如有侵权请联系删除

本文地址:http://0561fc.cn/79178.html