【Java Web】第六章 会话\_过滤器\_监听器

深入理解Java Web开发中的会话、过滤器与监听器

在Java Web开发领域,会话管理、过滤器以及监听器是极为关键的技术,它们在提升用户体验、保障系统安全以及增强系统可维护性等方面发挥着重要作用。接下来,我们将深入剖析这些技术,并结合实际案例,详细阐述它们的原理、应用场景以及具体实现方式。

一、会话:搭建客户端与服务端交互的桥梁

1.1 会话管理概述:为何需要它以及如何实现

1.1.1 为什么需要会话管理

HTTP作为无状态协议,自身不会对请求和响应之间的通信状态进行保存。这意味着,服务器在处理完浏览器发送的请求并作出响应后,不会记录该请求来自哪个浏览器,也无法识别浏览器的特征,即无法保存客户端的状态。例如,张三去饭馆吃饭,第二天再次光顾时,若饭馆不记录顾客信息,张三就需重新点菜。

1.1.2 会话管理实现的手段

为解决HTTP的无状态问题,Cookie和Session技术应运而生。Cookie是在客户端保留少量数据的技术,由服务端生成并通过响应头传递给客户端。而Session则是在服务端保留更多数据的技术,通过HttpSession对象为每个客户端开辟内存空间,存储与客户端相关的信息。两者相互配合,实现了对请求状态的有效记录。例如,张三去银行办业务,银行开户(Session)并发放银行卡(Cookie),后续张三凭借银行卡即可访问自己的账户。

1.2 Cookie:客户端存储的轻量级解决方案

1.2.1 Cookie概述

Cookie是一种客户端会话技术,由服务端产生并存储在浏览器中。每次浏览器访问该服务器时,都会携带这些数据。服务端创建Cookie后,Tomcat容器将其转化为set - cookie响应头发送给客户端,客户端下次请求时,会以cookie请求头的形式携带这些数据。Cookie以键值对格式存储数据,从Tomcat 8.5开始可保存中文,但出于安全考虑,一般不建议存储敏感信息。其应用场景广泛,如记录用户名,下次访问登录页面时自动填充;保存电影播放进度,再次打开时自动跳转到上次退出的位置。

1.2.2 Cookie的使用

在Java代码中,可通过以下方式操作Cookie:

  • 创建并添加Cookie到响应
@WebServlet("/servletA")
public class ServletA extends HttpServlet {
   
   
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   
   
        Cookie cookie1 = new Cookie("c1", "c1_message");
        Cookie cookie2 = new Cookie("c2", "c2_message");
        resp.addCookie(cookie1);
        resp.addCookie(cookie2);
    }
}
  • 从请求中读取Cookie
@WebServlet("/servletB")
public class ServletB extends HttpServlet {
   
   
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   
   
        Cookie[] cookies = req.getCookies();
        if (null!= cookies && cookies.length!= 0) {
   
   
            for (Cookie cookie : cookies) {
   
   
                System.out.println(cookie.getName() + ":" + cookie.getValue());
            }
        }
    }
}
1.2.3 Cookie的时效性

默认情况下,Cookie的有效期为一次会话范围。不过,可通过setMaxAge()方法实现Cookie的持久化保存。

  • 会话级Cookie:服务器未明确指定Cookie存在时间,在浏览器端存储于内存,浏览器关闭即释放。
  • 持久化Cookie:服务器设置Cookie存在时间,在浏览器端保存到硬盘,存在时间由服务器限定,不受浏览器关闭影响。
  • 设置持久化时间及删除Cookie:若setMaxAge(int expiry)参数为正数,代表Cookie的持久化时间(单位为秒);若为0,则表示删除浏览器中保存的该Cookie。
1.2.4 Cookie的提交路径

为避免每次访问互联网资源都携带所有Cookie,可通过setPath(String path)方法设置Cookie的提交路径。例如,可设置某个Cookie仅在访问特定路径(如/web03_war_exploded/servletB)时才携带。

1.3 Session:服务端的个性化数据存储

1.3.1 HttpSession概述

HttpSession是服务端用于保留更多客户端信息的技术。服务器为每个客户端创建一个独立的session对象,存于内存空间。客户端首次请求时,服务端创建session并将其id(JSESSIONID)以cookie形式放入响应。此后,客户端每次请求携带JSESSIONID,服务端据此找到对应的session对象,实现对特定客户端信息的存储。其应用场景包括记录用户登录状态、操作历史等。

1.3.2 HttpSession的使用

以用户登录为例,展示HttpSession的使用流程:

  • 用户提交表单到ServletA
<form action="servletA" method="post">
    用户名:
    <input type="text" name="username">
    <input type="submit" value="提交">
</form>
  • ServletA获取session并存储用户名
@WebServlet("/servletA")
public class ServletA extends HttpServlet {
   
   
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   
   
        String username = req.getParameter("username");
        HttpSession session = req.getSession();
        String jSessionId = session.getId();
        System.out.println(jSessionId);
        boolean isNew = session.isNew();
        System.out.println(isNew);
        session.setAttribute("username", username);
    }
}
  • 其他Servlet从session中读取用户名
@WebServlet("/servletB")
public class ServletB extends HttpServlet {
   
   
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   
   
        HttpSession session = req.getSession();
        String jSessionId = session.getId();
        System.out.println(jSessionId);
        boolean isNew = session.isNew();
        System.out.println(isNew);
        String username = (String) session.getAttribute("username");
        System.out.println(username);
    }
}
1.3.3 HttpSession时效性

随着用户量增加,为避免服务器内存耗尽,需设置session的时效。

  • 默认时效:在tomcat/conf/web.xml中,默认的session最大闲置时间为30分钟。
  • 自定义时效:可在项目的web.xml中重新设定,也可通过HttpSession的API(如setMaxInactiveInterval(60))设置,还可直接调用invalidate()方法使session失效。

1.4 三大域对象:数据共享的不同范围

1.4.1 域对象概述

域对象是用于存储和传递数据的对象,根据数据共享范围不同,分为请求域、会话域和应用域。

  • 请求域对象(HttpServletRequest):传递数据范围为一次请求之内及请求转发。
  • 会话域对象(HttpSession):传递数据范围为一次会话之内,可跨多个请求。
  • 应用域对象(ServletContext):传递数据范围为本应用之内,可跨多个会话。
1.4.2 域对象的使用

三大域对象均提供了setAttribute()getAttribute()removeAttribute()方法,用于数据的添加、获取和移除。以ServletA向三大域中放入数据,ServletB从三大域中取出数据为例:

  • ServletA放入数据
@WebServlet("/servletA")
public class ServletA extends HttpServlet {
   
   
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   
   
        req.setAttribute("request", "request - message");
        HttpSession session = req.getSession();
        session.setAttribute("session", "session - message");
        ServletContext application = getServletContext();
        application.setAttribute("application", "application - message");
    }
}
  • ServletB取出数据
@WebServlet("/servletB")
public class ServletB extends HttpServlet {
   
   
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   
   
        String reqMessage = (String) req.getAttribute("request");
        System.out.println(reqMessage);
        HttpSession session = req.getSession();
        String sessionMessage = (String) session.getAttribute("session");
        System.out.println(sessionMessage);
        ServletContext application = getServletContext();
        String applicationMessage = (String) application.getAttribute("application");
        System.out.println(applicationMessage);
    }
}

二、过滤器:请求的把关者

2.1 过滤器概述:过滤请求的强大工具

Filter是JavaEE技术规范之一,用于对目标资源的请求进行过滤。所有过滤器需实现Filter接口,工作在项目中所有目标资源之前。容器创建HttpServletRequest和HttpServletResponse对象后,先调用Filter的doFilter方法,该方法可控制请求是否继续,且可在目标资源响应前对响应进行处理。Filter是责任链模式的典型应用,常用于登录权限检查、解决乱码、过滤敏感字符等场景。

2.2 过滤器使用:以日志记录过滤器为例

2.2.1 定义过滤器类
package com.atguigu.filters;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时雨h

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值