跳到主要内容 Java 基础:Spring Web MVC 核心注解与开发流程 | 极客日志
Java java
Java 基础:Spring Web MVC 核心注解与开发流程 Java Web 开发涉及 Tomcat 服务器与 Servlet 规范,Spring Boot 简化了配置并内置容器。Spring Web MVC 基于 Servlet API,通过 DispatcherServlet 分发请求。核心注解包括 RequestMapping 映射路径,RequestBody 绑定 JSON,RequestParam 提取查询参数,PathVariable 获取路径变量,RequestPart 处理文件上传。Controller 标记处理器,ResponseBody 返回数据,RestController 组合两者。相比原生 Servlet,Spring MVC 实现了低耦合与高扩展性。
Tomcat 是一个开源的轻量级 Web (Http) 服务器和 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 示范
在 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 >
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 类型需通过该注解明确声明。
(1) 在 Spring MVC 中,参数绑定机制对集合类型 和数组类型 的处理存在差异。
(2) 使用 ArrayList<String> 作为方法参数时,必须显式添加 @RequestParam 注解,原因如下:
- 默认绑定规则 :Spring 默认将单个请求参数的值绑定到简单类型 (如 String、int) 或单个对象。对于集合类型,框架无法自动推断是否需要将多个同名参数合并为集合。
- 需要明确指示 :@RequestParam 注解会告知 Spring 将同名请求参数的值收集到一个集合中。
(3) 数组 (如 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 等格式),无需额外视图渲染。
注解级别 :类。
微信扫一扫,关注极客日志 微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具 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