跳到主要内容
Java Web 开发基础:Spring Web MVC 核心注解详解 | 极客日志
Java java
Java Web 开发基础:Spring Web MVC 核心注解详解 Spring Web MVC 基于 Servlet 构建,是 Spring 框架中处理 Web 请求的核心模块。从 Servlet 生命周期讲起,对比了传统 Servlet 开发与 Spring Boot 的优势,重点解析了 @RequestMapping、@RequestBody、@RequestParam 等常用注解的使用场景与参数绑定机制,帮助开发者快速掌握 Spring MVC 的请求处理流程。
remedios 发布于 2026/3/28 更新于 2026/4/25 2 浏览1.前置知识
1.1 Tomcat
Tomcat 是一个开源的轻量级 Web 服务器和 Servlet 容器。它实现了 Java Servlet 等 Java EE 规范的核心功能,常用于部署和运行 Java Web 应用程序。简单来说,Tomcat 就是一个严格遵循 Servlet 规范开发的、可以独立安装和运行的 Java Web 服务器/Servlet 容器 。
核心功能:
Servlet 容器 :支持 Servlet 的执行,处理 HTTP 请求和响应。
Web 服务器 :提供静态资源(如 HTML)的访问能力,支持基本的 HTTP 服务。
目录结构:
bin:存放可执行文件,如 startup.bat。
conf:存放配置文件。
lib:存放 Tomcat 运行所需的 jar 文件。
logs:存储日志文件。
temp:存放临时文件,如上传的文件或缓存数据。
webapps:默认 web 应用部署目录。
work:服务器的工作目录,存放运行时生成的临时文件(编译文件)。
1.2 Servlet
1.2.1 定义
Servlet 是 Java 语言编写的、运行在服务器端的程序,它遵循一套标准的 API 规范。Tomcat 是这套规范的一个具体实现(容器),并提供了让 Servlet 与前端交互的运行时环境。
1.2.2 API 示范
创建项目与配置:
在 IntelliJ IDEA 中创建 Maven 项目。
在 pom.xml 文件中添加 servlet 依赖(置于 <project> 标签下)。
<dependencies >
<dependency >
<groupId > jakarta.servlet</groupId >
<artifactId > jakarta.servlet-api</artifactId >
<version > 6.1.0</version >
<scope > provided</scope >
</dependency >
</dependencies >
在 main 路径下创建 webapp/Web-INF/web.xml,在 xml 文件中添加以下内容:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app >
<display-name > Archetype Created Web Application</display-name >
</web-app >
下载插件:Smart Tomcat(为了方便启动项目)。
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/method")
public class MethodServlet extends HttpServlet {
@Override
protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws IOException {
System.out.println("doPost" );
resp.setContentType("text/html; charset=utf-8" );
resp.getWriter().write("doPost" );
}
@Override
protected void doPut (HttpServletRequest req, HttpServletResponse resp) throws IOException {
System.out.println("doPut" );
resp.setContentType("text/html; charset=utf-8" );
resp.getWriter().write("doPut" );
}
@Override
protected void doDelete (HttpServletRequest req, HttpServletResponse resp) throws IOException {
System.out.println("doDelete" );
resp.setContentType("text/html; charset=utf-8" );
resp.getWriter().write("doDelete" );
}
}
1.2.3 生命周期 Servlet 生命周期由 Web 容器(如 Tomcat)管理,包含加载、初始化、处理请求和销毁 四个阶段。每个阶段对应特定的方法调用,开发者可通过重写这些方法实现自定义逻辑。
类加载 :Web 容器通过类加载器加载 Servlet 类(通常首次请求触发或容器启动时预加载,字节码文件被加载到内存但未实例化)。
实例化 :确认 Servlet 类成功加载后立刻执行,在整个 Web 容器中每种 Servlet 类(如 HttpServlet)只会有一个实例化对象。
初始化 :Web 容器调用刚刚创建好的 Servlet 实例的 init(ServletConfig config) 方法,在整个 servlet 实例的生命周期中仅调用一次,主要作用是读取配置和资源加载。若初始化失败,抛出 ServletException,Servlet 不会被加入可用队列。
处理请求 :Web 容器为每个请求创建线程,调用 service(ServletRequest req, ServletResponse res) 方法。service() 方法根据 HTTP 请求类型(get/post)调用 doGet() 或 doPost()。
销毁 :Web 容器调用 destroy() 方法,Servlet 实例被标记为垃圾回收。
2.SpringBoot Servlet 是 Java EE 规范中处理 Web 请求的核心组件,但随着应用复杂度提升,Servlet 的直接使用显得笨重。Spring 框架通过一系列抽象和扩展,简化了企业级应用开发。
我们可以用一个非常形象的比喻来贯穿始终:建造一座房子。
目标 :建造一个能遮风挡雨的房子(一个能处理 HTTP 请求的 Web 应用)。
你的工作状态 :
材料 :你有最基础的原材料——泥土(Java 语言)和水(JVM)。你需要自己烧制砖块(编写 Servlet 类)。
工具 :只有简单的泥瓦刀(Servlet API)。
过程 :
你为每一面墙、每一扇门都亲手烧制一块特定的砖(编写 LoginServlet, UserServlet, OrderServlet)。
你亲自规划每块砖的位置(在 web.xml 中配置大量的 <servlet> 和 <servlet-mapping>)。
你亲自搅拌水泥,一块一块地砌墙(在每个 Servlet 的 doGet/doPost 方法中手动解析参数、处理业务、组装 HTML)。
核心特点 :
高度灵活 :你可以造出任何形状的砖。
极其繁琐 :大量重复性劳动(每个 Servlet 都有获取参数、关闭连接等样板代码)。
难以维护 :砖块之间紧密耦合(对象依赖硬编码),想换一扇窗(修改功能)可能会牵动整面墙。
依赖外部 :房子建在别人的地上(需要将 war 包部署到外部的 Tomcat 服务器)。
总结 :Servlet 提供了 Web 开发的基础能力,但开发效率极低,代码冗余且难以维护。
第二阶段:Spring 时代 - 使用预制件和设计图纸
目标 :用更高效、更标准化的方式建造一个结构更好、更易扩展的房子。
你的工作状态 :
材料 :你不再烧砖,而是使用工厂提供的标准化预制件(Spring Bean,如 @Controller, @Service)。
核心创新 :你聘请了一位神奇的管家(IoC 容器)。你不再亲自'砌砖'(用 new 实例化对象),只需告诉管家你需要什么(用 @Autowired 声明依赖)。管家会自动把预制件(Bean)按照图纸(配置)组装好,送到你手上(依赖注入 DI)。
过程 :
一个总大门(DispatcherServlet):房子只有一个入口,所有访客(请求)都先到这里。
管家调度:总大门处的接待员(DispatcherServlet)根据访客需求,呼叫房子里对应的专业房间(@Controller 中的方法)来接待。
开发者只需专注于房间内的专业服务(业务逻辑),而不用关心访客是怎么进来的。
核心特点 :
解耦 :预制件之间是松耦合的,易于更换和测试。
专业化 :AOP(面向切面编程)可以像'装修队'一样,非侵入式地为所有房间统一安装中央空调(日志、安全、事务)。
效率提升 :避免了大量重复劳动,结构清晰。
配置复杂 :绘制详细的'组装图纸'(配置 Spring)本身成了一项复杂的工作。
总结 :Spring 框架通过 IoC/DI 和 AOP 等理念,解决了代码耦合和重复劳动问题,但引入了显著的配置复杂度。
Spring Boot 1.0.0 正式发布于 2014 年 4 月 1 日,标志着该框架的首次稳定版本发布。SpringBoot 基于 Spring Framework 4 进行设计,显著减少了开发者的配置工作量,彻底消除了 Spring 的配置地狱。
约定大于配置 :约定了默认配置。
Start 机制 :是一种依赖管理机制,每个 Starter 包含特定功能所需的依赖库和自动配置类,开发者只需引入对应 Starter 即可快速启用功能模块。
嵌入式容器 :内置了 Tomcat 等嵌入式容器,无需部署 war 文件到外部容器,直接运行即可启动应用。
3.Spring Web MVC
3.1 概述 官方描述 :Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,并从一开始就在 Spring 框架中。正式名称'Spring Web MVC',来自其源模块的名称(spring-webmvc),但它通常被称为'Spring MVC'。
MVC 的起源与发展 :MVC(Model-View-Controller)模式最初由挪威计算机科学家 Trygve Reenskaug 于 1978 年在施乐帕克研究中心(Xerox PARC)提出,目的是为 Smalltalk 编程语言设计用户界面。其核心思想是将应用程序的逻辑分为三个独立组件:
Model :处理数据逻辑和业务规则。
View :负责数据展示和用户界面。
Controller :接收用户输入并协调 Model 与 View 的交互。
Spring MVC 与 MVC 的关系 :Spring MVC 是 MVC 模式在 Spring 框架中的具体化,同时扩展了传统 MVC 的功能以适应现代 Web 开发需求。
3.2 必需工具 Postman :主要用于 API 的开发和测试。它提供了一个用户友好的界面,支持发送 HTTP 请求、管理请求历史、自动化测试以及团队协作。
Fiddler :是一个网络调试代理工具,主要用于监控和分析 HTTP/HTTPS 流量。它可以捕获设备与服务器之间的所有请求和响应,支持修改请求、重放请求以及性能分析。
3.3 RequestMapping 作用 :是 Spring MVC 中最核心、最基础的注解之一,用于将 HTTP 请求映射到具体的方法上。
注解级别 :类 + 方法。
作为类注解 :可以为整个类提供一个统一的 url 前缀(可有可无)。
作为方法注解 :指定该方法负责处理哪个 url 的请求(强制要求)。
@RequestMapping("/HelloController")
@RestController
public class HelloController {
@RequestMapping(value = "/hello", method = RequestMethod.GET, produces = "application/json")
public String hello () {
return "{\"Hello\" : World}" ;
}
@RequestMapping("/receiveAge1")
public String receiveAge1 (Integer age) {
return "接收到参数 age:" + age;
}
@RequestMapping("/receiveAge2")
public String receiveAge2 (int age) {
return "接收到参数 age:" + age;
}
@RequestMapping("/receiveArray")
public String receiveArray (String[] array) {
return "接收到参数 array:" + Arrays.toString(array);
}
@RequestMapping("/receivePerson")
public String receivePerson (Person person) {
return "接收到参数 person:" + person;
}
}
3.4 RequestBody 作用 :将 HTTP 请求体中的 json 数据绑定到 Java 对象(方法注解)。
注解级别 :方法。
@RequestMapping("/receivePerson")
public String receivePerson (@RequestBody Person person) {
return "接收到参数 person:" + person;
}
3.5 RequestParam 作用 :是 Spring MVC 框架中从 HTTP 请求中提取参数/查询字符串 的注解,主要用于将请求参数绑定到控制器方法的参数上。
注解级别 :方法。
@RequestMapping("/receiveRename")
public String receiveRename (@RequestParam(value = "name", required = false) String userName) {
return "接收到参数 name:" + userName;
}
注意 :需要接收多个同名参数 时(如 param=value1¶m=value2),直接绑定到 List 类型需通过该注解明确声明。
在 Spring MVC 中,参数绑定机制对集合类型 和数组类型 的处理存在差异:
使用 ArrayList<String> 作为方法参数时,必须显式添加 @RequestParam 注解。原因如下:
默认绑定规则 :Spring 默认将单个请求参数的值绑定到简单类型(如 String、int)或单个对象。对于集合类型,框架无法自动推断是否需要将多个同名参数合并为集合。
需要明确指示 :@RequestParam 注解会告知 Spring 将同名请求参数的值收集到一个集合中。
数组(如 String[])无需 @RequestParam 注解即可正确接收。原因如下:
内置支持 :Spring 对数组类型有原生支持,能自动将多个同名请求参数值绑定到数组。这是框架的默认行为,无需额外配置。
@RequestMapping("/receiveList1")
public String receiveList1 (ArrayList<String> list) {
return "接收到参数 list:" + list;
}
@RequestMapping("/receiveList2")
public String receiveList2 (@RequestParam(required = false) ArrayList<String> list) {
return "接收到参数 list:" + list;
}
@RequestMapping("/receiveList3")
public String receiveList3 (List<String> list) {
return "接收到参数 list:" + list;
}
后端报错 :java.lang.IllegalStateException: No primary or single unique constructor found for interface java.util.List。
receiveList3 方法使用 List<String> 接口类型而非具体实现类。Spring 虽然支持接口类型参数绑定,但需要满足特定条件:必须配合 @RequestParam 注解使用,不能直接使用未注解的接口类型参数。
报错根本原因 :Spring 尝试实例化 List 接口失败(接口不可实例化)。
3.6 PathVariable 作用 :用于从 URL 路径中提取变量值 并绑定到方法的参数上。
注解级别 :方法。
@RequestMapping("/receivePath/{article}/{blog}")
public String receivePath (
@PathVariable(value = "article", required = false) Integer title,
@PathVariable(value = "blog", required = false) String content
) {
return "接收到参数 article:" + title + " blog:" + content;
}
3.7 RequestPart 作用 :用于处理 HTTP 请求中的 multipart/form-data 类型数据,通常用于文件上传或同时上传文件和其他表单字段的场景。
注解级别 :方法。
@RequestMapping("/receiveFile")
public String receiveFile (
@RequestPart(value = "file", required = false) MultipartFile imgFile,
@RequestParam(value = "userName", required = false) String name
) {
return "用户:" + name + ",接收到文件:" + imgFile.getOriginalFilename();
}
3.8 Controller & ResponseBody & RestController
作用 :是 Spring MVC 中的核心注解,用于标记一个类作为 Web 请求的处理器(声明一个类是一个 Spring MVC 控制器),负责处理 HTTP 请求并返回视图。
注解级别 :类。
作用 :指示方法返回值应直接写入 HTTP 响应体,而非通过视图解析器渲染。
注解级别 :类 + 方法。
@RequestMapping("/ControllerResponse")
@Controller
public class ControllerResponse {
@RequestMapping("/HTMLView")
public String HTMLView () {
return "/show.html" ;
}
@ResponseBody
@RequestMapping("/HTMLData")
public String HTMLData () {
return "/show.html" ;
}
}
作用 :是 Spring MVC 中的一个组合注解,它结合了 @Controller 和 @ResponseBody 的功能,标记的类所有方法返回值默认直接作为 HTTP 响应体(JSON/XML 等格式),无需额外视图渲染。
注解级别 :类。
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online