You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ServletContext属性读取不一致问题及Servlet相关技术咨询

关于ServletContext与ServletRequest的疑问解答

问题代码

@Component
public class APIAttributeInitializeFilter implements Filter{

@Autowired
ServletContext servletContext;

@Override
public void doFilter(ServletRequest servletRequest,ServletResponse ServletResponse, FilterChain filterChain){


HttpServletRequest httpReq=(HttpServletRequest)servletRequest;
servletContext.setAttribute("intakeNumber",httpReq.getHeader("intakeNumber"));
}
}

问题描述

该Filter会从请求头获取intakeNumber并存入ServletContext,尝试在Controller返回响应后执行的切面类中读取该属性,但发现属性时而存在时而不存在,表现出不一致性。将存储对象换成ServletRequest后,能稳定获取到intakeNumber,但不清楚其内部工作原理,现咨询以下问题:

  1. 请讲解ServletContext与ServletRequest的相关知识;
  2. 说明二者的适用场景;
  3. 分析原问题出现的原因。

1. ServletContext与ServletRequest核心概念

ServletContext

  • 是整个Web应用的全局上下文对象,一个Web应用对应唯一的ServletContext实例,从应用启动时创建,到应用停止时销毁。
  • 属于全应用共享资源,所有请求、所有Servlet都能访问其中的属性。
  • 存储的属性全局可见,生命周期与应用完全一致。

ServletRequest

  • 是单个HTTP请求的上下文对象,每个请求都会生成独立的ServletRequest实例,请求处理完成后立即被销毁。
  • 仅属于当前请求,存储的属性只能在当前请求的处理链路中访问(比如Filter、Controller、切面等同一请求流程内)。
  • 生命周期严格限定在当前请求的处理周期内。

2. 二者适用场景

ServletContext适用场景

  • 存储应用级别的共享配置或资源,比如:
    • 系统全局参数(如应用版本、全局功能开关)
    • 全应用共享的静态缓存数据(如字典表、系统基础配置)
    • 提供应用级资源访问(如获取应用根目录路径)

ServletRequest适用场景

  • 存储单个请求链路中需要传递的临时数据,比如:
    • 从请求头/参数解析出、需在后续环节使用的业务数据
    • 请求级别的状态信息(如当前请求的用户身份、请求唯一ID)
    • 仅在当前请求生命周期内有效的临时变量

3. 原问题出现的原因

属性时而存在时而不存在的核心原因是ServletContext的全局共享特性引发多请求并发冲突:

  1. 当多个请求同时进入系统时,每个请求都会在Filter中执行servletContext.setAttribute("intakeNumber", ...)操作。
  2. 由于ServletContext是全局共享的,后到达的请求会直接覆盖前一个请求设置的intakeNumber值。
  3. 切面类读取属性时,当前请求设置的属性可能已经被其他并发请求覆盖,或者当前请求的设置操作还未完成就被其他请求抢先修改,导致读取到的是其他请求的值,甚至出现属性不存在的情况(比如后续请求将属性覆盖为null)。
  4. 换成ServletRequest后,每个请求都有独立的属性存储空间,不会与其他请求产生数据冲突,因此能稳定获取到当前请求的intakeNumber值。

内容的提问来源于stack exchange,提问作者Iswarya Elango

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 00:45:01