Skip to content

Web 基础

理解 Spring 之前必须搞清的 Web 底层知识。Servlet 是 Java Web 的基石,Spring MVC 本质上是对 Servlet 的封装。

概念

  • Web 应用的请求处理依赖 Servlet 容器(如 Tomcat),容器负责管理 Servlet 的生命周期和请求分发。
  • Filter 和 Listener 是 Servlet 规范提供的扩展机制,Spring Security 的过滤器链就建立在 Filter 之上。
  • HTTP 是无状态协议,Cookie、Session、Token 是三种维持用户状态的方案。

Servlet 生命周期

Servlet 容器(Tomcat)管理 Servlet 的完整生命周期:

阶段方法说明
加载与实例化构造方法容器启动或首次请求时创建 Servlet 实例(单例)
初始化init(ServletConfig)只调用一次,读取配置、初始化资源
处理请求service(request, response)每次请求调用,根据 HTTP 方法分派到 doGet/doPost 等
销毁destroy()容器关闭时调用,释放资源

关键点: Servlet 是单例的,多个请求共享同一个实例,因此 Servlet 中不应有可变的实例变量(线程安全问题)。

Servlet 容器工作原理

Tomcat 处理一个请求的流程:

  1. 监听端口,接收 TCP 连接
  2. 解析 HTTP 请求,创建 HttpServletRequestHttpServletResponse 对象
  3. 根据 URL 匹配对应的 Servlet(通过 web.xml 或注解 @WebServlet
  4. 调用 Filter 链(如果有)
  5. 调用 Servlet 的 service() 方法
  6. Servlet 写入响应内容
  7. 容器将响应发送给客户端

Filter 与 Listener

Filter 链机制

Filter 在请求到达 Servlet 之前和响应返回客户端之前执行,形成链式调用:

客户端 → Filter1 → Filter2 → Filter3 → Servlet → Filter3 → Filter2 → Filter1 → 客户端

典型用途:编码设置、日志记录、权限校验、跨域处理。

Filter vs Spring Interceptor

对比项FilterInterceptor
规范Servlet 规范Spring MVC 框架
作用范围所有请求(包括静态资源)只作用于 DispatcherServlet 处理的请求
执行时机在 Servlet 之前在 Handler(Controller)前后
访问 Spring 容器不能直接注入 Bean可以访问 Spring 容器
典型场景编码、安全过滤登录校验、日志、权限

Listener

监听 Servlet 容器中的事件:

  • ServletContextListener:应用启动和关闭时触发,常用于初始化全局资源
  • HttpSessionListener:Session 创建和销毁时触发,可用于在线用户统计
  • ServletRequestListener:请求创建和销毁时触发

HTTP 请求响应要点

常用 HTTP 方法

方法语义幂等安全
GET获取资源
POST创建资源 / 提交数据
PUT全量替换
DELETE删除资源

状态码分类

范围含义常见
1xx信息性100 Continue
2xx成功200 OK、201 Created、204 No Content
3xx重定向301 永久、302 临时、304 未修改
4xx客户端错误400 Bad Request、401 Unauthorized、403 Forbidden、404 Not Found
5xx服务器错误500 Internal Server Error、502 Bad Gateway、503 Service Unavailable

常用 Header

Header说明
Content-Type请求/响应体的 MIME 类型(application/json、text/html)
Authorization认证凭证(Bearer Token)
Cache-Control缓存策略
Set-Cookie / Cookie服务端设置 / 客户端携带 Cookie
X-Forwarded-For经过代理时的真实客户端 IP
对比项CookieSessionToken (JWT)
存储位置客户端浏览器服务端内存/Redis客户端(localStorage/Cookie)
安全性较低(可被篡改)较高(数据在服务端)中等(签名防篡改,但不加密)
跨域受同源策略限制依赖 Cookie 传递 Session ID天然支持跨域(Header 携带)
服务端压力需存储所有用户状态无(无状态)
水平扩展支持需要共享 Session(Redis)天然支持(任何节点都能验证)
主动失效设置过期时间服务端销毁无法主动失效(需配合黑名单)

为什么现在更倾向 Token?

  • 前后端分离架构下,前端可能是 Web、App、小程序,Token 方案统一且不依赖 Cookie
  • 微服务架构下,Session 共享复杂,Token 天然无状态,适合水平扩展
  • 但 Token 也有缺点:无法主动撤销、payload 不宜存敏感数据、刷新机制需要额外设计

为什么 Spring 要封装 Servlet

原生 Servlet 开发的痛点:

  1. 模板代码多 — 每个 Servlet 都要继承 HttpServlet、重写 doGet/doPost
  2. 参数解析繁琐 — 手动 request.getParameter(),类型转换、校验全靠自己
  3. 缺少 IoC 支持 — 对象依赖关系手动管理,无法注入
  4. 路由分散 — URL 映射在 web.xml 或注解中,缺乏统一管理
  5. 异常处理困难 — 没有全局异常处理机制

Spring MVC 通过 DispatcherServlet 统一入口 + 注解驱动解决了这些问题。

面试常问 & 怎么答

Q1: Servlet 的生命周期?

Servlet 是单例的,容器启动或首次请求时创建实例,调用 init() 初始化;每次请求调用 service() 方法(分派到 doGet/doPost);容器关闭时调用 destroy() 销毁。因为是单例,要注意线程安全。

Q2: Filter 和 Interceptor 的区别?

Filter 是 Servlet 规范的,作用于所有请求(包括静态资源),在 Servlet 之前执行;Interceptor 是 Spring MVC 的,只作用于 Controller 请求,可以访问 Spring 容器。执行顺序是 Filter → DispatcherServlet → Interceptor → Controller。

Q3: Cookie、Session、Token 各自的优缺点?

Cookie 存客户端,容量小且受同源策略限制;Session 存服务端,安全但不利于水平扩展(需 Redis 共享);Token(JWT)无状态,天然支持分布式和跨域,但无法主动撤销。现在前后端分离 + 微服务架构下更倾向 Token。

Q4: 为什么现在更倾向用 JWT 而不是 Session?

两个原因:一是前后端分离后前端形态多样(Web、App、小程序),JWT 通过 Header 携带,不依赖 Cookie;二是微服务架构下 Session 共享需要额外基础设施(Redis),JWT 无状态,任何节点都能验证。

看到什么就先想到这类

  • 出现 Servlet、Filter、Listener、web.xml。
  • 出现 Cookie、Session、Token、JWT 的对比。
  • 出现 HTTP 方法、状态码、Header 基础问题。
  • 出现"Spring 为什么要封装 / Spring MVC 和 Servlet 的关系"。