前言
文章内容输出来源:拉勾教育Java就业训练营
Filter+Listener核心技术
Filter过滤器
基本概念
- Filter本意为”过滤“的含义,是JavaWeb的三大组件之一,三大组件为:Servlet、Filter、Listener。
- 过滤器是向 Web 应用程序的请求和响应处理添加功能的 Web 服务组件。
- 过滤器相当于浏览器与Web资源之间的一道过滤网,在访问资源之前通过一系列的过滤器对请求进行修改、判断以及拦截等,也可以对响应进行修改、判断以及拦截等。
工作方式
使用方式
- 自定义类实现Filter接口并重写doFilter方法。
public class LoginFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,ServletException {
//TODO 处理逻辑,必须调用下面的方法
chain.doFilter(request,response);
}
}
- 在web.xml文件中配置过滤器。
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>com.lagou.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Filter接口
- 基本概念
javax.servlet.Filter接口主要用于描述过滤器对象,可以对资源的请求和资源的响应操作进行筛选操作。 - 常用方法
方法声明 | 功能介绍 |
---|---|
void init(FilterConfig filterConfig) | 实现过滤器的初始化操作 |
void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) | 执行过滤操作的功能 |
void destroy() | 实现过滤器的销毁操作 |
示例:调用以上方法来测试生命周期
package com.lagou.demo02;
import javax.servlet.*;
import java.io.IOException;
public class LifeFilter implements Filter {
public LifeFilter() {
System.out.println("构造方法执行了");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化操作。。。");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("阻拦一切不和理的访问");
//放开拦截,使其正常跳转
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
System.out.println("销毁操作执行完毕了");
}
}
生命周期的测试:life.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生命周期的测试</title>
</head>
<body>
<h1>生命周期的测试效果哦!</h1>
</body>
</html>
配置方式: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">
<filter>
<filter-name>LifeFilter</filter-name>
<filter-class>com.lagou.demo02.LifeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LifeFilter</filter-name>
<url-pattern>*.html </url-pattern>
</filter-mapping>
</web-app>
结果:
- init()方法会在构造方法被调用后直接被调用初始化。
- doFilter()方法会在访问其他页面时进行拦截。
- destroy()当重启服务器或者关闭服务器时将会进行销毁。
备注:如果有构造方法,那么先创建构造方法,在进行初始化。
FilterConfig接口
- 基本概念
javax.servlet.FilterConfig接口主要用于描述过滤器的配置信息。 - 常用方法
方法声明 | 功能介绍 |
---|---|
String getFilterName() | 获取过滤器的名字 |
String getInitParameter(String name) | 获取指定的初始化参数信息 |
Enumeration getInitParameterNames() | 获取所有的初始化操作名称 |
ServletContext getServletContext() | 获取ServletContext对象 |
示例:演示FilterConfig接口的操作
LifeFilter.java;在init()方法中进行
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化操作。。。");
System.out.println("获取到的过滤器名称为:" + filterConfig.getFilterName());
String userName = filterConfig.getInitParameter("userName");//admin
System.out.println("获取到指定初始化数值为:" + userName);
Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();
while (initParameterNames.hasMoreElements()) {
//userName password
System.out.println("获取到的初始化的参数名为:" + initParameterNames.nextElement());
}
ServletContext servletContext = filterConfig.getServletContext();
System.out.println("获取到的上下文对象是:" + servletContext);
}
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">
<filter>
<filter-name>LifeFilter</filter-name>
<filter-class>com.lagou.demo02.LifeFilter</filter-class>
<init-param>
<param-name>userName</param-name>
<param-value>admin</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>123456</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>LifeFilter</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
</web-app>
获取到的结果为:
构造方法执行了
初始化操作。。。
获取到的过滤器名称为:LifeFilter
获取到指定初始化数值为:admin
获取到的初始化的参数名为:password
获取到的初始化的参数名为:userName
获取到的上下文对象是:org.apache.catalina.core
多个过滤器的使用
- 如果有多个过滤器都满足过滤的条件,则容器依据映射的先后顺序来调用各个过滤器。
示例:构建多道防线测试防线的先后顺序
第一道过滤器:AFilter.java
import javax.servlet.*;
import java.io.IOException;
public class AFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("这是第一道防线");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("第一道防线返回");
}
@Override
public void destroy() {
}
}
第二道过滤器:BFilter.java
import javax.servlet.*;
import java.io.IOException;
public class BFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("这是第二道防线");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("第二道防线返回");
}
@Override
public void destroy() {
}
}
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">
<filter>
<filter-name>Afilter</filter-name>
<filter-class>com.lagou.demo02.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Afilter</filter-name>
<url-pattern>*.avi</url-pattern>
</filter-mapping>
<filter>
<filter-name>Bfilter</filter-name>
<filter-class>com.lagou.demo02.BFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Bfilter</filter-name>
<url-pattern>*.avi</url-pattern>
</filter-mapping>
</web-app>
过滤器启动的先后顺序是根据<filter-mapping>的先后顺序来进行排序的。
输出结果:
这是第一道防线
这是第二道防线
第二道防线返回
第一道防线返回
过滤器优点
- 实现代码的“可插拔性”,即增加或减少某个功能模块,不会影响程序的正常执行。
- 可以将多个相同处理逻辑的模块集中写在过滤器里面,可实现重复利用、也方便代码的维护。
Listener监听器
基本概念
- Servlet规范中定义的一种特殊的组件,用来监听Servlet容器产生的事件并进行相应的处理。
- 容器产生的事件分类如下:
- 生命周期相关的事件。
- 属性状态相关的事件。
- 存值状态相关的事件。
- 底层原理是采用接口回调的方式实现。
基本分类
监听器类型 | 功能介绍 |
---|---|
javax.servlet.ServletRequestListener | 监听request作用域的创建和销毁 |
javax.servlet.ServletRequestAttributeListener | 监听request作用域的属性状态变化 |
javax.servlet.http.HttpSessionListener | 监听session作用域的创建和销毁 |
javax.servlet.http.HttpSessionAttributeListener | 监听session作用域的属性状态变化 |
javax.servlet.ServletContextListener | 监听application作用域的创建和销毁 |
javax.servlet.ServletContextAttributeListener | 监听application作用域的属性状态变化 |
javax.servlet.http.HttpSessionBindingListener | 监听对象与session的绑定和解除 |
javax.servlet.http.HttpSessionActivationListener | 监听session数值的钝化和活化 |
监听器详解
ServletRequestListener监听器
- 在ServletRequest创建和关闭时都会通知ServletRequestListener监听器。
- 常用方法如下:
方法声明 | 功能介绍 |
---|---|
void requestInitialized(ServletRequestEvent sre) | 实现ServletRequest对象的初始化 |
void requestDestroyed(ServletRequestEvent sre) | 实现ServletRequest对象的销毁 |
示例:测试监听器的创建和关闭
实现ServletRequestListener的接口:MyRequestListener.java
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
public class MyRequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
System.out.println("请求销毁了。。。");
}
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
System.out.println("创建请求了。。。");
}
}
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.lagou.demo03.MyRequestListener</listener-class>
</listener>
</web-app>
结果:当进入了浏览器进行访问时,会有创建请求了。。。而后会执行请求销毁了。。。
注意:idea的功能强大,他自动启动浏览器时会请求2次,所以如果要进行测试的话将自动启动浏览器关闭。
ServletRequestAttributeListener监听器
- 向ServletRequest添加、删除或者替换一个属性的时候,将会通知ServletRequestAttributeListener监听器。
- 常用方法如下:
方法声明 | 功能介绍 |
---|---|
void attributeAdded(ServletRequestAttributeEvent srae) | 增加属性时触发 |
void attributeReplaced(ServletRequestAttributeEvent srae) | 修改属性时触发 |
void attributeRemoved(ServletRequestAttributeEvent srae) | 删除属性时触发 |
测试属性出现的变化,进行监听
实现类型ServletRequestAttributeListener:MyRequestAttributeListener.java
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
public class MyRequestAttributeListener implements ServletRequestAttributeListener {
@Override
public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) {
System.out.println("增加了属性:" + servletRequestAttributeEvent.getName());
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) {
System.out.println("删除了属性:" + servletRequestAttributeEvent.getName());
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) {
System.out.println("修改了属性:" + servletRequestAttributeEvent.getName());
}
}
配置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.lagou.demo03.MyRequestAttributeListener</listener-class>
</listener>
</web-app>
HttpSessionListener监听器
- 当一个HttpSession刚被创建或者失效(invalidate)的时候,将会通知HttpSessionListener监听器。
- 常用方法如下:
方法声明 | 功能介绍 |
---|---|
void sessionCreated(HttpSessionEventse) | 当一个HttpSession对象被创建时会调用这个方法 |
void sessionDestroyed(HttpSessionEventse) | 当一个HttpSession超时或者调用HttpSession的invalidate()方法让它销毁时,将会调用这个方法 |
示例:测试监听session创建和销毁
实现HttpSessionListener:MySessionListener.java
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class MySessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
System.out.println("创建了session");
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
System.out.println("session销毁");
}
}
配置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.lagou.demo03.MySessionListener</listener-class>
</listener>
<session-config>
<!--设置session销毁时间-->
<session-timeout>1</session-timeout>
</session-config>
</web-app>
结果:当进入页面时就会创建session,等待3分钟后session就会被销毁。
HttpSessionAttributeListener监听器
- HttpSession中添加、删除或者替换一个属性的时候,将会通知HttpSessionAttributeListener监听器。
- 常用方法如下:
方法声明 | 功能介绍 |
---|---|
void attributeAdded(HttpSessionBindingEventse) | 当往会话中加入一个属性的时候会调用这个方法 |
void attributeRemoved(HttpSessionBindingEventse) | 当从会话中删除一个属性的时候会调用这个方法 |
void attributeReplaced(HttpSessionBindingEvent se) | 当改变会话中的属性的时候会调用这个方法 |
示例:测试Session会话的增删改的效果
实现HttpSessionAttributeListener:MySessionAttributeListener.java
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
public class MySessionAttributeListener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("增加了属性:" + httpSessionBindingEvent.getName());
}
@Override
public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("删除了属性:" + httpSessionBindingEvent.getName());
}
@Override
public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("修改了属性:" + httpSessionBindingEvent.getName());
}
}
配置xml:web.xml
<listener>
<listener-class>com.lagou.demo03.MySessionAttributeListener</listener-class>
</listener>
实现会话属性状态的改变操作: sessionAttribute.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>实现会话中属性状态的改变</title>
</head>
<body>
<%
//增加属性
session.setAttribute("name","caocao");
//修改属性
session.setAttribute("name","caoren");
//删除属性
session.removeAttribute("name");
%>
</body>
</html>
结果:当进入sessionAttribute.jsp界面是,后台打印出
增加了属性:name
修改了属性:name
删除了属性:name
ServletContextListener监听器
- 在ServletContext创建和关闭时都会通知ServletContextListener监听器。
- 常用方法如下:
方法声明 | 功能介绍 |
---|---|
void contextInitialized(ServletContextEventsce) | 当ServletContext创建的时候,将会调用这个方法 |
void contextDestroyed(ServletContextEventsce) | 当ServletContext销毁的时候(例如关闭应用服务器或者重新加载应用),将会调用这个方法 |
示例:测试接口ServletContextListener。
实现ServletContextListener接口为:MyServletContextListener.java
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext对象创建了...");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext对象被销毁了...");
}
}
配置:web.xml
<listener>
<listener-class>com.lagou.demo03.MyServletContextListener</listener-class>
</listener>
结果:当启动时,ServletContext被创建了,当停止服务器后,ServletContext被销毁了。
ServletContextAttributeListener监听器
- 向ServletContext添加、删除或者替换一个属性的时候,将会通知ServletContextAttributesListener监听器
- 常用方法如下:
方法声明 | 功能介绍 |
---|---|
void attributeAdded(ServletContextAttributeEvent scae) | 往ServletContext中加入一个属性的时候触发 |
void attributeRemoved(ServletContextAttributeEventscae) | 从ServletContext中删除一个属性的时候触发 |
void attributeReplaced(ServletContextAttributeEventscae) | 改变ServletContext中属性的时候触发 |
示例:测试ServletContextAttributeListener接口
实现ServletContextAttributeListener接口:MyServletContextAttributeListener.java
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
public class MyServletContextAttributeListener implements ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("增加了属性:"+servletContextAttributeEvent.getName());
}
@Override
public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("删除了属性:"+servletContextAttributeEvent.getName());
}
@Override
public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("修改了属性"+servletContextAttributeEvent.getName());
}
}
配置:web.xml
<listener>
<listener-class>com.lagou.demo03.MyServletContextAttributeListener</listener-class>
</listener>
测试页面:contextAttribute.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>实现SerbletContex对象属性的改变</title>
</head>
<body>
<%
//增加属性
application.setAttribute("name", "zhaosan");
//修改属性
application.setAttribute("name", "lisi");
//删除属性
application.removeAttribute("name");
%>
</body>
</html>
结果:当进入页面后
增加了属性:org.apache.jasper.runtime.JspApplicationContextImpl
增加了属性:org.apache.jasper.compiler.ELInterpreter
增加了属性:name
修改了属性name
删除了属性:name
HttpSessionBindingListener监听器
- HttpSession中绑定和解除绑定时,将会通知HttpSessionListener监听器。
- 常用方法如下:
方法声明 | 功能介绍 |
---|---|
void valueBound(HttpSessionBindingEvent event) | 有对象绑定时调用该方法 |
void valueUnbound(HttpSessionBindingEvent event) | 有对象解除绑定时调用该方法 |
示例:监控HttpSession中对象的绑定和解绑效果
实现接口HttpSessionListener的实体类:Person.java
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
public class Person implements HttpSessionBindingListener {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public void valueBound(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("对象绑定到session中了");
}
@Override
public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("解除绑定成功");
}
}
测试数据:sessionBind.jsp
<%@ page import="com.lagou.demo03.Person" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>实现session中对象的绑定和解除</title>
</head>
<body>
<%
//准备Person对象
Person person = new Person();
person.setName("zhangsan");
person.setAge(30);
//将对象与session对象进行绑定
session.setAttribute("person",person);
//解除绑定
session.removeAttribute("person");
%>
</body>
</html>
结果:当从页面进入后将会显示出:
对象绑定到session中了
解除绑定成功
HttpSessionActivationListener监听器
- 当有session数值的钝化和活化操作时,将会通知HttpSessionActivationListener监听器。
- 常用方法如下:
方法声明 | 功能介绍 |
---|---|
void sessionWillPassivate(HttpSessionEvent se) | 有钝化操作时调用该方法(序列化操作类似,直接写入到硬盘中) |
void sessionDidActivate(HttpSessionEvent se) | 有活化操作时调用该方法(从硬盘中取出) |
- 配置Tomcat下的conf中的context.xml文件将如下代码复制粘贴:
<Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true">
<!-- 配置文件存放的路径信息,可以自由指定 -->
<Store className="org.apache.catalina.session.FileStore" directory="C:\session"/>
</Manager>
示例:进行session中的钝化和活化操作
实体类:Student.java
package com.lagou.demo03;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
import java.io.Serializable;
public class Student implements Serializable , HttpSessionActivationListener {
private String name;
public Student() {
}
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
@Override
public void sessionWillPassivate(HttpSessionEvent httpSessionEvent) {
System.out.println("执行了钝化操作"+httpSessionEvent.getSession());
}
@Override
public void sessionDidActivate(HttpSessionEvent httpSessionEvent) {
System.out.println("活化操作进行中。。。");
}
}
进行钝化操作:sessionAcivate.jsp
<%@ page import="com.lagou.demo03.Student" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>实现session中的数据的钝化和活化操作</title>
</head>
<body>
<%
//创建Student类型的对象
Student student = new Student();
student.setName("zhangsan");
//将数据放入到session中
session.setAttribute("student",student);
%>
</body>
</html>
进行活化操作:sessionGet.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>实现session中数据的获取</title>
</head>
<body>
<%
Object student = session.getAttribute("student");
System.out.println("获取到的数据为:"+student);
%>
</body>
</html>
结果:当进入到sessionAcivate.jsp的页面后,将服务器关闭,将会执行钝化操作。
当进入到sessionGet.jsp的页面后,会进行活化操作,将钝化存储的值获取。
实战案例
监听当前的在线用户。
自定义类实现监听器接口并重写相关的方法。
public class OnlineUser implements HttpSessionListener, ServletContextListener {
ServletContext ctx = null;
// 初始化ServletContext
public void contextInitialized(ServletContextEvent e) {
ctx = e.getServletContext();
}
// 销毁ServletContext
public void contextDestroyed(ServletContextEvent e) {
//将ServletContext设置成null;
}
// 当新创建一个HttpSession对象时
public void sessionCreated(HttpSessionEvent e) {
//将当前的在线人数加上1,并且保存到ServletContext(application)中
}
// 当一个HttpSession被销毁时(过期或者调用了invalidate()方法)
public void sessionDestroyed(HttpSessionEvent e) {
//将当前人数减去1,并且保存到ServletContext(application)中
}
}
- 在web.xml中配置监听器
<listener>
<listener-class>com.lagou.listener.OnlineUser </listener-class>
</listener>
示例:
继承对应接口,OnlineUser.java
package com.lagou.demo04;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class OnlineUser implements HttpSessionListener, ServletContextListener {
//声明一个ServletContext类型的引用放在作为全局对象来记录当前在线用户的数量,通过属性记录
ServletContext servletContext = null;
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
servletContext = servletContextEvent.getServletContext();
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
servletContext = null;
}
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
System.out.println("有新用户上线...");
//若当前用户为第一个用户,则将全局对象中的属性值设置为1即可
Object count = servletContext.getAttribute("count");
if (null == count) {
servletContext.setAttribute("count", 1);
} else {
//若当前用户不是第一个用户,则将全局对象中原有的数据取出来加1后在设置上去
Integer integer = (Integer) count;
integer++;
servletContext.setAttribute("count", integer);
}
System.out.println("当前在线用户数量为:" + servletContext.getAttribute("count"));
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
System.out.println("有用户已下线");
}
}
文件配置: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.lagou.demo04.OnlineUser</listener-class>
</listener>
</web-app>
显示页面:onlineUser.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>实现当前用户的在线数量</title>
</head>
<body>
<h1>当前在线用户为:${applicationScope.count}</h1>
</body>
</html>