从 Servlet 到 Spring MVC:一次看懂 Java Web 的底层与进阶

01|网络基础(Servlet 的根基)

1️⃣ HTTP 是什么

Servlet 本质就是:用 Java 写的 HTTP 请求处理程序

HTTP 核心模型:

客户端(浏览器)
   ↓ 请求(Request)
服务器(Tomcat + Servlet)
   ↑ 响应(Response)

2️⃣ HTTP 请求的组成

GET /login?name=tom HTTP/1.1
Host: localhost:8080
Cookie: JSESSIONID=xxx

请求体(POST 才有)

关键点:

  • 请求行:方法 + URL
  • 请求头:浏览器信息、Cookie
  • 请求体:POST 参数 / JSON

3️⃣ HTTP 响应

HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8

<html>...</html>

Servlet 做的事情就是:

读取请求 → 业务处理 → 写响应


02|Tomcat 安装(Servlet 的运行环境)

1️⃣ Tomcat 是什么

  • Web 服务器 + Servlet 容器
  • 负责:
    • 监听端口(8080)
    • 解析 HTTP
    • 调用 Servlet

2️⃣ 安装步骤(Mac / Linux / Windows 类似)

官网下载 apache-tomcat-9.x.zip
解压
bin/startup.sh(或 startup.bat)

访问:

http://localhost:8080

3️⃣ 目录结构重点

bin/        启动脚本
conf/       server.xml / web.xml
webapps/    部署的项目
logs/       日志

03|Servlet 配置(Servlet 如何被访问)

方式一:web.xml(传统)

<servlet>
  <servlet-name>Hello</servlet-name>
  <servlet-class>com.demo.HelloServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>Hello</servlet-name>
  <url-pattern>/hello</url-pattern>
</servlet-mapping>

方式二:注解(推荐)

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
}

📌 URL → Servlet 映射关系


04|Servlet 生命周期(非常重要)

生命周期流程

实例化
  ↓
init()        (只执行一次)
  ↓
service()     (每次请求)
  ↓
destroy()     (服务器关闭)

示例

@Override
public void init() {
    System.out.println("Servlet 初始化");
}

@Override
protected void doGet(...) {
    System.out.println("处理请求");
}

@Override
public void destroy() {
    System.out.println("Servlet 销毁");
}

⚠️ 重点:

  • Servlet 是单例
  • 不要用成员变量存请求数据(线程不安全)

05|请求和响应(HttpServletRequest / Response)

1️⃣ 获取请求参数

String name = request.getParameter("name");

2️⃣ 请求对象能做什么

  • 参数
  • 请求头
  • Cookie
  • Session
  • 请求域(request.setAttribute)

3️⃣ 响应对象

response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("Hello");

06|转发和重定向(高频面试点)

转发(Forward)

request.getRequestDispatcher("/jsp/success.jsp")
       .forward(request, response);

特点:

  • 服务器内部
  • 地址栏不变
  • 共享 request

重定向(Redirect)

response.sendRedirect("/login");

特点:

  • 浏览器再次请求
  • 地址栏改变
  • request 不共享

📌 登录成功 → 重定向
📌 表单校验失败 → 转发


07|过滤器(Filter)

1️⃣ 作用

请求到达 Servlet 之前 / 响应返回之前 做处理

常见用途:

  • 登录校验
  • 编码设置
  • 权限控制
  • 日志

2️⃣ 示例

@WebFilter("/*")
public class EncodingFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse res,
                         FilterChain chain) {
        req.setCharacterEncoding("UTF-8");
        chain.doFilter(req, res);
    }
}

3️⃣ 执行链

Filter1 → Filter2 → Servlet → Filter2 → Filter1

08|监听器(Listener)

监听什么?

  • ServletContext
  • Session
  • Request

常用监听器

监听器 作用
ServletContextListener 项目启动/关闭
HttpSessionListener Session 创建/销毁
HttpSessionAttributeListener Session 属性变化

示例

@WebListener
public class AppListener implements ServletContextListener {
    public void contextInitialized(...) {
        System.out.println("项目启动");
    }
}

📌 常用于:

  • 初始化配置
  • 连接池
  • 缓存预热

09|Cookie 和 Session(状态保持)

HTTP 是无状态的 ❌

Cookie / Session 用来 记住用户


Cookie(客户端)

Cookie c = new Cookie("token", "123");
c.setMaxAge(3600);
response.addCookie(c);

特点:

  • 存在浏览器
  • 不安全
  • 有大小限制

Session(服务器)

HttpSession session = request.getSession();
session.setAttribute("user", user);

特点:

  • 安全
  • 基于 Cookie(JSESSIONID)
  • 超时销毁

📌 登录系统 = Session


10|JSP(Servlet 的表现层)

JSP 本质是什么?

JSP = Servlet

<%= request.getAttribute("msg") %>

JSP 执行过程

.jsp → 翻译成 Servlet → 编译 → 执行

MVC 中的位置

Servlet(Controller)
JSP(View)
JavaBean(Model)

⚠️ 现代项目:

  • JSP 用得少
  • Thymeleaf / Vue 取代

11|项目部署

1️⃣ 传统 war 包

mvn clean package
xxx.war → tomcat/webapps/

访问:

http://localhost:8080/项目名

2️⃣ ROOT 项目

ROOT.war
http://localhost:8080/

3️⃣ 生产环境建议

  • Nginx + Tomcat
  • HTTPS
  • 日志切割
  • JVM 参数

🎯 一张整体关系图(非常重要)

浏览器
  ↓ HTTP
Tomcat
  ↓
Filter
  ↓
Servlet
  ↓
Service / DAO
  ↓
JSP / JSON

从 Servlet 到 Spring MVC

一句话先给结论:
Spring MVC = 在 Servlet 之上的一套“更高级的 Web 编程模型”


一、整体关系(先立世界观)

浏览器
  ↓ HTTP
Tomcat
  ↓
DispatcherServlet   ← Spring MVC 的核心(它本身就是 Servlet)
  ↓
Controller
  ↓
Service / DAO
  ↓
View (JSP / Thymeleaf / JSON)

📌 Spring MVC 并没有绕开 Servlet,而是“封装 + 扩展”它


二、核心对照表(重点)

对比维度 原生 Servlet Spring MVC
入口 每个 Servlet 一个入口 统一入口 DispatcherServlet
URL 映射 web.xml / @WebServlet @RequestMapping
请求参数 request.getParameter @RequestParam / 自动绑定
返回响应 response.getWriter 返回对象 / 视图名
转发重定向 手写 forward / redirect return "redirect:/xx"
JSON 手动写 @ResponseBody 自动序列化
过滤器 Filter Filter + Interceptor
生命周期 Servlet 生命周期 Bean 生命周期
依赖管理 自己 new IoC 自动注入
测试 困难 非常友好

三、入口设计对比(最本质差异)

1️⃣ Servlet:多入口、分散

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    protected void doPost(...) {
        // 登录逻辑
    }
}

问题:

  • Servlet 越多,入口越乱
  • 通用逻辑(鉴权、日志)重复

2️⃣ Spring MVC:单入口(前端控制器模式)

public class DispatcherServlet extends HttpServlet {
    // Spring 内部
}

所有请求 → DispatcherServlet → Controller

优点:

  • 统一拦截
  • 易扩展
  • 符合大型项目

📌 这是经典 Front Controller(前端控制器)模式


四、URL 映射对比

Servlet

@WebServlet("/user/add")
public class UserAddServlet {}

Spring MVC

@RestController
@RequestMapping("/user")
public class UserController {

    @PostMapping("/add")
    public User add(User user) {}
}

✅ Spring MVC 支持:

  • 类级别 + 方法级别映射
  • REST 风格
  • HTTP 方法语义

五、请求参数处理(差距最大)

Servlet(手动解析)

String name = request.getParameter("name");
int age = Integer.parseInt(request.getParameter("age"));

❌ 问题:

  • 类型转换
  • 空值校验
  • 重复代码

Spring MVC(自动绑定)

@PostMapping("/add")
public User add(@RequestParam String name,
                @RequestParam int age) {
}

甚至:

public User add(User user) {}

✅ Spring MVC 自动做了:

  • 参数提取
  • 类型转换
  • 对象封装
  • 校验(@Valid)

六、响应处理对比

Servlet

response.setContentType("application/json");
response.getWriter().write(json);

Spring MVC

@GetMapping("/user")
@ResponseBody
public User getUser() {
    return user;
}

Spring MVC 自动:

  • 调用 Jackson
  • 转 JSON
  • 设置响应头

📌 你只关心业务对象,不关心 HTTP 细节


七、转发 & 重定向

Servlet

request.getRequestDispatcher("/success.jsp")
       .forward(request, response);

response.sendRedirect("/login");

Spring MVC

return "success";              // 转发
return "redirect:/login";      // 重定向

语义更清晰、代码更干净


八、过滤 vs 拦截(非常经典)

Servlet Filter(低层)

请求 → Filter → Servlet
  • 对所有 Servlet 生效
  • 处理编码、跨域

Spring Interceptor(高层)

DispatcherServlet
  → Interceptor
    → Controller
public class AuthInterceptor implements HandlerInterceptor {
    boolean preHandle(...) {}
}

适合:

  • 登录校验
  • 权限控制
  • 业务拦截

📌 Filter 偏基础设施,Interceptor 偏业务


九、依赖管理(本质飞跃)

Servlet

UserService service = new UserServiceImpl();

❌ 强耦合、难测试


Spring MVC

@Autowired
UserService userService;

✅ IoC:

  • 解耦
  • 易扩展
  • 易 Mock

十、异常处理对比

Servlet

try {
} catch (Exception e) {
    response.sendError(500);
}

Spring MVC

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public Result error() {}
}

📌 统一异常出口 = 大型系统必备


十一、为什么说:Spring MVC 是“更现代的 Servlet”?

Servlet 能做 Spring MVC
更优雅
更安全
更适合复杂系统
更易维护

👉 Servlet 是“工具”,Spring MVC 是“体系”


十二、学习路线建议(非常重要)

你可以按这个思路理解:

Servlet
  ↓(理解 HTTP)
Filter / Listener
  ↓
Spring MVC
  ↓
Spring Boot

📌 Spring Boot 本质 = 自动配置的 Spring MVC + 内嵌 Tomcat

正文完
 0
评论(没有评论)
验证码