【JavaWeb】会话&过滤器&监听器

会话&过滤器&监听器

文章目录

  • 会话&过滤器&监听器
  • 一、会话
    • [1.1 Cookie](#1.1 Cookie)
    • [1.2 Session](#1.2 Session)
    • [1.3 三大域对象](#1.3 三大域对象)
  • 二、过滤器
  • 三、监听器
    • [3.1 application域监听器](#3.1 application域监听器)
    • [3.2 session域监听器](#3.2 session域监听器)
    • [3.3 request域监听器](#3.3 request域监听器)
    • [3.4 session域的两个特殊监听器](#3.4 session域的两个特殊监听器)
      • [3.4.1 session绑定监听器](#3.4.1 session绑定监听器)
      • [3.4.2 钝化活化监听器](#3.4.2 钝化活化监听器)
    • [3.5 自定义监听器](#3.5 自定义监听器)
    • [3.6 应用场景](#3.6 应用场景)

一、会话

HTTP是无状态协议,cookie和session配合记录请求状态,实现会话管理

cookie是一种客户端会话技术,cookie由服务端产生,它是服务器存放在浏览器的一小份数据,浏览器以后每次访问该服务器的时候都会将这小份数据携带到服务器去。

  • cookie是一种键值对格式的数据,从tomcat8.5开始可以保存中文,但是不推荐
  • 由于cookie是存储于客户端的数据,比较容易暴露,一般不存储一些敏感或者影响安全的数据

Cookie的时效性:默认情况下Cookie的有效期是一次会话范围内,可以通过cookie的setMaxAge()方法让Cookie持久化保存到浏览器上

  • 会话级Cookie:存在于内存中,浏览器开着,Cookie数据就一直都在,浏览器关闭才释放
  • 持久化Cookie:服务器端明确设置了Cookie的存在时间,在浏览器端,Cookie数据会被保存到硬盘上,到达预设时间才释放

1.2 Session

HttpSession是一种保留更多信息在服务端的一种技术,服务器会为每一个客户端开辟一块内存空间,即session对象。

  • 服务端在为客户端创建session时,会同时将session对象的id,即JSESSIONID以cookie的形式放入响应对象
  • 客户端下一次请求时携带JSESSIONID,后端收到后,根据JSESSIONID找到对应的session对象
  • 如禁用了cookie也可通过将 JSESSIONID 设置到header或其他方式保存下来,请求时再发给后端处理

HttpSession时效性 :默认的session 在 tomcat/conf/web.xml 配置为30分钟,因需消耗服务端内存,建议在项目中配置时间,web.xml ,单位分钟

xml 复制代码
<session-config>
    <session-timeout>1</session-timeout>
</session-config>

1.3 三大域对象

域对象: 一些用于存储数据和传递数据的对象,传递数据不同的范围,我们称之为不同的域,不同的域对象代表不同的域,共享数据的范围也不同

web项目中,要求熟练掌握的域对象如下:

  • 请求域对象是HttpServletRequest ,传递数据的范围是一次请求之内及请求转发
  • 会话域对象是HttpSession,传递数据的范围是一次会话之内,可以跨多个请求
  • 应用域对象是ServletContext,传递数据的范围是本应用之内,可以跨多个会话

域对象的API:

API 功能
void setAttribute(String name,String value) 向域对象中添加/修改数据
Object getAttribute(String name); 从域对象中获取数据
removeAttribute(String name); 移除域对象中的数据

二、过滤器

Filter,即过滤器,是JAVAEE技术规范之一,作用目标资源的请求进行过滤的一套技术规范,是Java Web项目中最为实用的技术之一

  • Filter的工作位置是项目中所有目标资源之前,容器在创建HttpServletRequest和HttpServletResponse对象后,会先调用Filter的doFilter方法
  • Filter的doFilter方法可以控制请求是否继续,如果放行,则请求继续,如果拒绝,则请求到此为止,由过滤器本身做出响应
  • Filter不仅可以对请求做出过滤,也可以在目标资源做出响应前,对响应再次进行处理
  • Filter是设计模式中责任链模式的典型案例

过滤器开发中应用的场景:日志的记录、性能的分析、乱码的处理、事务的控制、登录的控制、跨域的处理等

源码:

java 复制代码
package jakarta.servlet;

import java.io.IOException;

public interface Filter {
    // 初始化方法,由容器调用并传入初始配置信息filterConfig对象
    default void init(FilterConfig filterConfig) throws ServletException {
    }
    // 过滤方法,核心方法,过滤请求,决定是否放行,响应之前的其他处理等都在该方法中
    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
    // 销毁方法,容器在回收过滤器对象之前调用的方法
    default void destroy() {
    }
}

多个过滤器流程图解:

过滤器使用步骤(与Servlet类似):

  1. 创建类继承 Filter 接口
  2. 在 web.xml 中配置类及过滤路径;也可用注解 @WebFilter 完成配置

xml形式

xml 复制代码
<!--配置filter,并为filter起别名-->
<filter>
    <filter-name>loggingFilter</filter-name>
    <filter-class>filter.LoggingFilter</filter-class>
    <!--配置filter的初始参数-->
    <init-param>
        <param-name>dateTimePattern</param-name>
        <param-value>yyyy-MM-dd HH:mm:ss</param-value>
    </init-param>
</filter>
<!--为别名对应的filter配置要过滤的目标资源-->
<filter-mapping>
    <filter-name>loggingFilter</filter-name>
    <!--通过映射路径确定过滤资源-->
    <url-pattern>/servletA</url-pattern>
    <!--通过后缀名确定过滤资源-->
    <url-pattern>*.html</url-pattern>
    <!--通过servlet别名确定过滤资源-->
    <servlet-name>servletBName</servlet-name>
</filter-mapping>

注解形式

java 复制代码
package filter;

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.annotation.WebInitParam;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

@WebFilter(
        filterName = "loggingFilter",
        initParams = {@WebInitParam(name="dateTimePattern",value="yyyy-MM-dd HH:mm:ss")},
        urlPatterns = {"/servletA","*.html"},
        servletNames = {"servletBName"}
)
public class LoggingFilter implements Filter {
    private SimpleDateFormat dateFormat ;

    /*init初始化方法,通过filterConfig获取初始化参数
    * init方法中,可以用于定义一些其他初始化功能代码
    * */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 获取初始参数
        String dateTimePattern = filterConfig.getInitParameter("dateTimePattern");
        // 初始化成员变量
        dateFormat=new SimpleDateFormat(dateTimePattern);
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 参数父转子
        HttpServletRequest request =(HttpServletRequest)  servletRequest;
        HttpServletResponse  response =(HttpServletResponse)  servletResponse;
        // 拼接日志文本
        String requestURI = request.getRequestURI();
        String time = dateFormat.format(new Date());
        String beforeLogging =requestURI+"在"+time+"被请求了";
        // 打印日志
        System.out.println(beforeLogging);
        // 获取系统时间
        long t1 = System.currentTimeMillis();
        // 放行请求
        filterChain.doFilter(request,response);
        // 获取系统时间
        long t2 = System.currentTimeMillis();
        String afterLogging =requestURI+"在"+time+"的请求耗时:"+(t2-t1)+"毫秒";
        // 打印日志
        System.out.println(afterLogging);

    }
}

三、监听器

监听器:专门用于对域对象对象身上发生的事件或状态改变进行监听和相应处理的对象

  • 监听器是设计模式中,观察者模式的典型案例
  • 监听器并不监听web项目中的所有组件,仅仅是对三大域对象做相关的事件监听

web中定义八个监听器接口,分类:

  • 按监听的对象划分
    • application域监听器 ServletContextListener ServletContextAttributeListener
    • session域监听器 HttpSessionListener HttpSessionAttributeListener HttpSessionBindingListener HttpSessionActivationListener
    • request域监听器 ServletRequestListener ServletRequestAttributeListener
  • 按监听的事件分
    • 域对象的创建和销毁监听器 ServletContextListener HttpSessionListener ServletRequestListener
    • 域对象数据增删改事件监听器 ServletContextAttributeListener HttpSessionAttributeListener ServletRequestAttributeListener
    • 其他监听器 HttpSessionBindingListener HttpSessionActivationListener

3.1 application域监听器

监听接口 方法名 作用
ServletContextListener contextInitialized(ServletContextEvent sce) ServletContext创建时调用
contextDestroyed(ServletContextEvent sce) ServletContext销毁时调用
ServletContextEvent attributeAdded(ServletContextAttributeEvent scab) 向ServletContext中添加属性时调用
attributeRemoved(ServletContextAttributeEvent scab) 从ServletContext中移除属性时调用
attributeReplaced(ServletContextAttributeEvent scab) 当ServletContext中的属性被修改时调用

3.2 session域监听器

监听接口 方法名 作用
HttpSessionListener sessionCreated(HttpSessionEvent hse) HttpSession对象创建时调用
sessionDestroyed(HttpSessionEvent hse) HttpSession对象销毁时调用
HttpSessionEvent attributeAdded(HttpSessionBindingEvent se) 向HttpSession中添加属性时调用
attributeRemoved(HttpSessionBindingEvent se) 从HttpSession中移除属性时调用
attributeReplaced(HttpSessionBindingEvent se) 当HttpSession中的属性被修改时调用

3.3 request域监听器

监听接口 方法名 作用
ServletRequestListener requestInitialized(ServletRequestEvent sre) ServletRequest对象创建时调用
requestDestroyed(ServletRequestEvent sre) ServletRequest对象销毁时调用
ServletRequestEvent attributeAdded(ServletRequestAttributeEvent srae) 向ServletRequest中添加属性时调用
attributeRemoved(ServletRequestAttributeEvent srae) 从ServletRequest中移除属性时调用
attributeReplaced(ServletRequestAttributeEvent srae) 当ServletRequest中的属性被修改时调用

3.4 session域的两个特殊监听器

3.4.1 session绑定监听器

HttpSessionBindingListener 监听当前监听器对象在Session域中的增加与移除

方法名 作用
valueBound(HttpSessionBindingEvent event) 该类的实例被放到Session域中时调用
valueUnbound(HttpSessionBindingEvent event) 该类的实例从Session中移除时调用

3.4.2 钝化活化监听器

HttpSessionActivationListener 监听某个对象在Session中的序列化与反序列化

方法名 作用
sessionWillPassivate(HttpSessionEvent se) 该类实例和Session一起钝化到硬盘时调用
sessionDidActivate(HttpSessionEvent se) 该类实例和Session一起活化到内存时调用

钝化与活化 :即 session 的持久化,如 session 到期,即使钝化了也会自动删除对应文件

  • 在到达设定时间前关闭服务器时,对session进行序列化到磁盘,这种情况叫做session的钝化
  • 在服务器启动后或者再次获取某个被钝化的session时,将磁盘上的session进行反序列化到内存,这种情况叫做session的活化

session持久化:在web目录下,添加 META-INF 目录,并创建 context.xml 文件

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
        <Store className="org.apache.catalina.session.FileStore" directory="d:\mysession"></Store>
    </Manager>
</Context>

3.5 自定义监听器

以application域监听器为例,自定义监听器:

java 复制代码
package listener;

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebListener;


@WebListener
public class ApplicationListener implements ServletContextListener , ServletContextAttributeListener {
    // 监听初始化
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext application = sce.getServletContext();
        System.out.println("application"+application.hashCode()+" initialized");
    }
    // 监听销毁
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        ServletContext application = sce.getServletContext();
        System.out.println("application"+application.hashCode()+" destroyed");
    }
    // 监听数据增加
    @Override
    public void attributeAdded(ServletContextAttributeEvent scae) {
        String name = scae.getName();
        Object value = scae.getValue();
        ServletContext application = scae.getServletContext();
        System.out.println("application"+application.hashCode()+" add:"+name+"="+value);
    }
    // 监听数据移除
    @Override
    public void attributeRemoved(ServletContextAttributeEvent scae) {
        String name = scae.getName();
        Object value = scae.getValue();
        ServletContext application = scae.getServletContext();
        System.out.println("application"+application.hashCode()+" remove:"+name+"="+value);
    }
    // 监听数据修改
    @Override
    public void attributeReplaced(ServletContextAttributeEvent scae) {
        String name = scae.getName();
        Object value = scae.getValue();
        ServletContext application = scae.getServletContext();
        Object newValue = application.getAttribute(name);
        System.out.println("application"+application.hashCode()+" change:"+name+"="+value+" to "+newValue);
    }
}

3.6 应用场景

  • application域监听器:进行一些初始化或清理工作,比如读取配置文件、初始化数据库连接池等
  • session域监听器:统计当前会话数,限制总会话数
  • request域监听器:记录请求日志、统计请求次数
相关推荐
hummhumm5 小时前
第 36 章 - Go语言 服务网格
java·运维·前端·后端·python·golang·java-ee
White graces7 小时前
Spring MVC练习(前后端分离开发实例)
java·开发语言·前端·后端·spring·java-ee·mvc
frost-cold18 小时前
【JavaEE】Servlet:表白墙
java·servlet·java-ee
界面开发小八哥1 天前
「Java EE开发指南」如何使用Visual JSF编辑器设计JSP?(二)
java·ide·java-ee·开发工具·myeclipse
Nu11PointerException1 天前
JAVA笔记 | 策略模式+枚举Enum简单实现策略模式(可直接套用)
java·spring boot·spring·java-ee·mybatis·个人开发·策略模式
I_Am_Me_1 天前
【JavaEE进阶】SpringBoot 快速上⼿
java·spring boot·java-ee
龙ze1 天前
javaEE初阶——多线程(1)
java-ee
薯条不要番茄酱1 天前
【JavaEE初阶】枫叶经霜艳,梅花透雪香-计算机是如何运行的?
java·开发语言·后端·java-ee·学习方法
鸽鸽程序猿1 天前
【JavaEE】Maven的介绍及配置
java·java-ee·maven
浅念同学2 天前
JavaEE-线程安全专题
java·安全·java-ee