会话&过滤器&监听器
文章目录
- 会话&过滤器&监听器
- 一、会话
-
- [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配合记录请求状态,实现会话管理
1.1 Cookie
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类似):
- 创建类继承 Filter 接口
- 在 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
- application域监听器
- 按监听的事件分
- 域对象的创建和销毁监听器
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域监听器:记录请求日志、统计请求次数