spring MVC执行流程
详细的项目结构
src
├── main
│ ├── java
│ │ ├── com.example
│ │ │ ├── config
│ │ │ │ └── SpringMvcInitializer.java // 配置 DispatcherServlet
│ │ │ │ └── SpringConfig.java // Spring MVC 配置
│ │ │ ├── controller
│ │ │ │ └── UserController.java // 控制器,返回 JSON
│ │ │ ├── service
│ │ │ │ └── UserService.java // 服务层,处理业务逻辑
│ │ │ └── model
│ │ │ │ └── User.java // 数据模型
│ └── webapp
│ └── WEB-INF
│ └── web.xml(可选,可省略)
- 注意:我们不再需要
views
文件夹和userInfo.jsp
,因为不再渲染 HTML 页面。
详细代码实现(每个步骤对应之前的流程)
1. HTTP 请求(1. http请求)
- 描述:用户通过浏览器、Postman 或其他客户端发送
GET /user/info?id=1
到服务器,请求用户信息。 - 细节:请求可以是 HTTP GET 方法,URL 包含查询参数
id
,期望返回 JSON 格式的数据。 - 测试方式:
- 使用 Postman:设置请求方法为 GET,URL 为
http://localhost:8080/user/info?id=1
,Headers 中可添加Accept: application/json
。 - 浏览器直接访问(需要确保服务器支持 JSON 响应)。
- 使用 Postman:设置请求方法为 GET,URL 为
- 通俗解释:就像你在餐厅点了一份外卖,期望收到菜的配方(JSON 数据)而不是直接上菜(HTML 页面)。
2. DispatcherServlet 接收请求(2. 寻找控制器)
- 描述:
DispatcherServlet
作为 Spring MVC 的核心控制器,接收 HTTP 请求,并分发到合适的处理器。 - 配置细节:我们使用
AbstractAnnotationConfigDispatcherServletInitializer
替代传统web.xml
,确保DispatcherServlet
加载SpringConfig
配置。 - 代码(
SpringMvcInitializer.java
):package com.example.config;import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {@Overrideprotected Class<?>[] getRootConfigClasses() {// 根应用上下文配置(这里可以用于其他非 MVC 的配置,如数据源)return null;}@Overrideprotected Class<?>[] getServletConfigClasses() {// 指定 Spring MVC 配置类return new Class<?>[] { SpringConfig.class };}@Overrideprotected String[] getServletMappings() {// 所有请求(/)都由 DispatcherServlet 处理return new String[] { "/" };} }
- 注意事项:
getServletMappings
中的"/"
表示拦截所有请求(包括静态资源),如果需要处理静态资源(如 CSS、JS),需要额外配置(见后文)。- 确保项目部署到支持 Servlet 3.0+ 的容器(如 Tomcat 8+)。
- 通俗解释:服务员(
DispatcherServlet
)在餐厅入口接单,准备分发到后厨(Controller)。
3. HandlerMapping 匹配处理器(3. 调用控制器)
- 描述:
DispatcherServlet
调用HandlerMapping
(通常是RequestMappingHandlerMapping
),根据 URL/user/info
找到UserController
的getUserInfo
方法。 - 配置细节:
@EnableWebMvc
自动启用RequestMappingHandlerMapping
,无需额外配置。 - 代码(
UserController.java
):package com.example.controller;import com.example.model.User; import com.example.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController;@RestController // 标记为 REST 控制器,自动返回 JSON,无需视图 public class UserController {@Autowiredprivate UserService userService;@GetMapping("/user/info") // 处理 GET 请求,路径为 /user/infopublic User getUserInfo(@RequestParam("id") int id) {// 调用服务层查询用户信息User user = userService.getUserById(id);return user; // 直接返回 User 对象,Spring 自动转换为 JSON} }
- 注意事项:
@RestController
结合@GetMapping
简洁地定义了 REST API,@RequestParam
绑定 URL 参数id
。- Spring 依赖
Jackson
库将User
对象序列化为 JSON,确保项目有jackson-databind
依赖。
- 通俗解释:服务员(
DispatcherServlet
)问前台(HandlerMapping
):“这单谁做?”前台说:“交给这个厨师(UserController
)处理,返回菜的配方(JSON)。”
4. Controller 处理请求并返回数据(4. 调用业务逻辑进行处理)
- 描述:
UserController
调用UserService
执行业务逻辑,模拟查询用户信息,返回User
对象。 - 代码(
UserService.java
和User.java
):// User.java(模型类,优化为支持 JSON 序列化) package com.example.model;import com.fasterxml.jackson.annotation.JsonProperty; // 可选,用于自定义 JSON 字段名public class User {private String name;private int age;// 无参构造(Jackson 要求,用于反序列化)public User() {}public User(String name, int age) {this.name = name;this.age = age;}@JsonProperty("name") // 可选,指定 JSON 字段名public String getName() { return name; }public void setName(String name) { this.name = name; }@JsonProperty("age")public int getAge() { return age; }public void setAge(int age) { this.age = age; }@Overridepublic String toString() {return "User{name='" + name + "', age=" + age + "}";} }// UserService.java(服务层,模拟业务逻辑) package com.example.service;import com.example.model.User; import org.springframework.stereotype.Service;@Service public class UserService {public User getUserById(int id) {// 模拟从数据库查询,实际项目中可能用 JPA、MyBatis 或 JDBCreturn new User("User" + id, 20 + id);} }
- 注意事项:
User
类添加了无参构造和 getter/setter 方法,以支持 Jackson 的 JSON 序列化/反序列化。@JsonProperty
是可选的,用于自定义 JSON 字段名(如将name
映射为userName
)。@Service
注解使UserService
成为 Spring Bean,可通过@Autowired
自动注入。
- 通俗解释:厨师(
Controller
)叫助手(UserService
)查菜谱(数据库),炒好一道菜(User
数据),打包成 JSON 配方返回。
5. DispatcherServlet 接收数据(5. 视图处理结果)
- 描述:
DispatcherServlet
接收User
对象,并通过 Spring 的HttpMessageConverter
(默认使用MappingJackson2HttpMessageConverter
)将其转换为 JSON 格式。 - 细节:Spring 自动检测返回的
User
对象类型,使用 Jackson 库序列化为 JSON,并设置 HTTP 响应头Content-Type: application/json
。 - 代码:无额外代码,
DispatcherServlet
内部处理。 - 注意事项:
- 确保
pom.xml
中有jackson-databind
依赖,否则 Spring 无法序列化 JSON。 - 如果 JSON 格式需要自定义(如日期格式、忽略某些字段),可配置
ObjectMapper
。
- 确保
- 通俗解释:服务员(
DispatcherServlet
)拿到菜的配方(User
对象),用打印机(HttpMessageConverter
)打印成 JSON 格式。
6. 移除 ViewResolver(6. 视图模板解析)
- 描述:因为我们不再返回 HTML 页面,移除
ViewResolver
和 JSP 相关配置。 - 代码(
SpringConfig.java
):package com.example.config;import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration @EnableWebMvc @ComponentScan(basePackages = "com.example") public class SpringConfig implements WebMvcConfigurer {// 移除 ViewResolver Bean,因为我们直接返回 JSON// 如果需要处理静态资源,可以在这里添加配置@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/static/");} }
- 注意事项:
@EnableWebMvc
启用了 Spring MVC 的所有功能,但默认禁用了 Spring Boot 的自动静态资源处理。如果需要静态资源(如 CSS、JS),需手动配置addResourceHandlers
。- 移除
ViewResolver
后,Spring 专注于 REST API,不再处理视图模板。
- 通俗解释:服务员发现不需要盘子(JSP),直接把菜的配方(JSON)打包送出。
7. 返回 JSON 数据(7. 数据直接返回)
- 描述:
User
对象被序列化为 JSON,返回给客户端。最终响应为:{"name": "User1","age": 21 }
- 细节:
- Spring 使用
MappingJackson2HttpMessageConverter
进行序列化。 - 返回的 HTTP 状态码默认是 200 OK。
- 如果需要自定义 JSON 格式(如日期、字段过滤),可以配置
ObjectMapper
:@Bean public ObjectMapper objectMapper() {ObjectMapper mapper = new ObjectMapper();mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));return mapper; }
- Spring 使用
- 代码:已在
UserController.java
中实现。 - 通俗解释:服务员把菜的配方(JSON)直接交给送餐员(客户端),不需要装盘(HTML)。
8. 返回 HTTP 响应(8. http响应)
- 描述:客户端(浏览器、Postman)收到 JSON 数据,可以解析或显示。
- 细节:
- 响应头包括
Content-Type: application/json; charset=UTF-8
。 - 如果客户端是 Postman,JSON 数据直接显示;如果是浏览器,可能需要插件(如 JSONView)格式化显示。
- 响应头包括
- 测试验证:
- 打开 Postman,设置请求方法为 GET,URL 为
http://localhost:8080/user/info?id=1
。 - 点击发送,查看响应:
{"name": "User1","age": 21 }
- 确保服务正常运行,依赖配置正确。
- 打开 Postman,设置请求方法为 GET,URL 为
- 通俗解释:送餐员(客户端)收到菜的配方(JSON),可以直接查看或用在其他地方。
完整依赖配置(Maven 示例)
确保 pom.xml
包含以下依赖:
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.23</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.0</version></dependency><dependency><groupId>jakarta.servlet</groupId><artifactId>jakarta.servlet-api</artifactId><version>6.0.0</version><scope>provided</scope></dependency>
</dependencies>
- 说明:
jackson-databind
是 JSON 序列化/反序列化的核心库,确保版本兼容 Spring。
可能扩展和注意事项
-
参数验证:
- 可以使用
@Valid
和@NotNull
验证id
参数:
需要添加@GetMapping("/user/info") public User getUserInfo(@RequestParam @NotNull int id) {return userService.getUserById(id); }
hibernate-validator
依赖:<dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId><version>6.2.5.Final</version> </dependency>
- 可以使用
-
异常处理:
- 可以使用
@ExceptionHandler
或@ControllerAdvice
处理异常:@ControllerAdvice public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)@ResponseBodypublic Map<String, Object> handleException(Exception e) {Map<String, Object> result = new HashMap<>();result.put("error", "Internal Server Error");result.put("message", e.getMessage());return result;} }
- 可以使用
-
跨域支持(CORS):
- 如果前端在不同域名,需配置 CORS:
@Configuration public class SpringConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins("http://localhost:3000") // 允许的源.allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的方法.allowedHeaders("*"); // 允许的头} }
- 如果前端在不同域名,需配置 CORS:
-
性能优化:
- 可以使用
@Cacheable
缓存查询结果:
需要添加@Service public class UserService {@Cacheable("users")public User getUserById(int id) {return new User("User" + id, 20 + id);} }
spring-boot-starter-cache
或spring-context-support
依赖。
- 可以使用
-
静态资源处理:
- 如果需要静态资源(如 CSS、JS),在
SpringConfig
中配置:@Override public void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/static/").setCachePeriod(3600); // 缓存 1 小时 }
- 如果需要静态资源(如 CSS、JS),在
对应图中的流程变化(更详细)
- 原图中的
ViewResolver
和View(HTML/FTL)
被移除,因为我们直接返回 JSON。 - 新流程简化为:
- HTTP 请求 →
DispatcherServlet
DispatcherServlet
找HandlerMapping
→UserController
UserController
调用UserService
→ 返回User
对象DispatcherServlet
转换User
为 JSON → 返回 HTTP 响应
- HTTP 请求 →
运行和测试
-
运行环境:
- 使用 JDK 11 或更高版本。
- 部署到 Tomcat 8+ 或运行 Spring Boot 项目。
- 确保 Maven 依赖下载完整。
-
测试:
- 使用 Postman 测试
GET http://localhost:8080/user/info?id=1
。 - 预期响应:
{"name": "User1","age": 21 }
- 使用 Postman 测试
-
调试:
- 检查日志,确保
DispatcherServlet
、HandlerMapping
和HttpMessageConverter
正常工作。 - 如果 JSON 格式错误,检查
User
类是否有无参构造、getter/setter。
- 检查日志,确保
总结
通过上述详细修改,我们将 Spring MVC 从返回 JSP 页面改为返回 JSON 数据,适合 RESTful API 开发。我补充了技术细节(如 Jackson 配置、参数验证、异常处理等)和代码注释,确保每个步骤清晰易懂。
相关文章:
spring MVC执行流程
详细的项目结构 src ├── main │ ├── java │ │ ├── com.example │ │ │ ├── config │ │ │ │ └── SpringMvcInitializer.java // 配置 DispatcherServlet │ │ │ │ └── SpringConfig.java // Sprin…...
递归遍历目录 和 普通文件的复制 [Java EE]
递归遍历目录 首先 先列出当前目录所包含的内容 File[] files currentDir.listFiles();if (files null || files.length 0) {// 若是空目录或非法目录, 则直接返回return;} 然后 遍历列出的文件, 分情况两种讨论 for (File f: files) {// 加个日志, 方便查看程序执行情…...

如何在docker上部署java服务
目录结构 首先 Dockerfile FROM bladex/alpine-java:openjdk17_cn_slimMAINTAINER admin@rsz.comENV TZ=Asia/ShanghaiRUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezoneRUN mkdir -p /xhWORKDIR /xhEXPOSE 8106ADD ./blade-system.…...

Machine Learning 初探
前置知识 pandas 读取文件:read_csv查看信息 describe:查看整体信息,包括每列的平均值、最大最小值、标准差等head:输出头部几行数据columns:输出所有列名loc:查询数据,或是根据索引取对应的数…...

GESP2024年12月认证C++三级( 第三部分编程题(1)数字替换)
参考程序: #include <iostream> #include <vector> #include <algorithm> using namespace std; int a[100010]; // 定义一个数组a,用于存储序列A,数组大小为100010 int main() {int n, k; // 定义变量n和k,…...
IDEA-插件开发踩坑记录-第六坑-UAST依赖问题
背景 简要说明: UAST – Unified Abstract Syntax Tree UAST (Unified Abstract Syntax Tree) is an abstraction layer on the PSI of different programming languages targeting the JVM (Java Virtual Machine). It provides a unified API for working with co…...

单片机总结【GPIO/TIM/IIC/SPI/UART】
一、GPIO 1、概念 通用输入输出口;开发者可以根据自己的需求将其配置为输入或输出模式,以实现与外部设备进行数据交互、控制外部设备等功能。简单来说,GPIO 就像是计算机或微控制器与外部世界沟通的 “桥梁”。 2、工作模式 工作模式性质特…...

信号和槽
connect(信号发送者,发送的信号,信号接收者,信号的处理); 信号函数和槽函数的参数必须是一样的,但信号的参数可以多余槽函数的参数(前面的参数类型必须一致) 是控件和控件间的信号传递,这两个…...

Window下Redis的安装和部署详细图文教程(Redis的安装和可视化工具的使用)
文章目录 Redis下载地址:一、zip压缩包方式下载安装 1、下载Redis压缩包2、解压到文件夹3、启动Redis服务4、打开Redis客户端进行连接5、使用一些基础操作来测试 二、msi安装包方式下载安装 1、下载Redis安装包2、进行安装3、进行配置4、启动服务5、测试能否正常工…...

1.2.3 使用Spring Initializr方式构建Spring Boot项目
本实战概述介绍了如何使用Spring Initializr创建Spring Boot项目,并进行基本配置。首先,通过Spring Initializr生成项目骨架,然后创建控制器HelloController,定义处理GET请求的方法hello,返回HTML字符串。接着…...

数据可视化02-PCA降维
一、PCA PCA做什么?找坐标系。 目标?二维降到一维,信息保留最多。 怎么样最好?数据分布最分散的方向(方差最大),作为主成分(坐标轴)。 二、怎么找主成分? …...

大连指令数据集的创建--数据收集与预处理_02
1.去哪儿爬虫 编程语言:Python爬虫框架:Selenium(用于浏览器自动化)解析库:BeautifulSoup(用于解析HTML) 2.爬虫策略 目标网站:去哪儿(https://travel.qunar.com/trav…...

xr-frame 3D Marker识别,扬州古牌坊 3D识别技术稳定调研
目录 识别物体规范 3D Marker 识别目标文件 map 生成 生成任务状态解析 服务耗时: 对传入的视频有如下要求: 对传入的视频建议: 识别物体规范 为提高Marker质量,保证算法识别效果,可参考Marker规范文档 Marker规…...

【网络安全 | 漏洞挖掘】利用文件上传功能的 IDOR 和 XSS 劫持会话
未经许可,不得转载。 本文涉及漏洞均已修复。 文章目录 前言正文前言 想象这样一个场景:一个专门处理敏感文档的平台,如保险理赔或身份验证系统,却因一个设计疏漏而成为攻击者的“金矿”。在对某个保险门户的文件上传功能进行测试时,我意外发现了一个可导致大规模账户接管…...

达梦数据库系列之安装及Mysql数据迁移
达梦数据库系列之安装及Mysql数据迁移 1. 达梦数据库1.1 简介1.2 Docker安装达梦1.2.1 默认密码查询1.2.2 docker启动指定密码 1.3 达梦数据库连接工具1.3.1 快捷键 2 Mysql数据库迁移至达梦2.1 使用SQLark进行数据迁移 1. 达梦数据库 1.1 简介 DM8是达梦公司在总结DM系列产品…...

FS800DTU联动OneNET平台数据可视化View
目录 1 前言 2 环境搭建 2.1 硬件准备 2.2 软件环境 2.3 硬件连接 3 注册OneNET云平台并建立物模型 3.1 参数获取 3.2 连接OneNET 3.3上报数据 4 数据可视化View 4.1 用户信息获取 4.2 启用数据可视化View 4.3 创建项目 4.4 编辑项目 4.5 新增数据源 4.6 数据过滤器配置 4.6 项…...
ffmpeg avdevice_register_all 注册设备的作用
在 FFmpeg 中,avdevice_register_all() 是一个用于注册所有输入和输出设备的函数。它是 FFmpeg 的 libavdevice 模块的一部分,专门用于处理音频和视频的输入/输出设备(如摄像头、麦克风、屏幕捕获等)。 以下是对 avdevice_regist…...
使用JS遍历JSON数组
在JavaScript中,遍历JSON对象或数组是一个常见的操作,尤其是在处理复杂数据结构时。这里有几种不同的方法可以根据你的需求进行遍历。 1. 遍历JSON对象 如果你有一个JSON对象(实际上在JavaScript中,所有的对象都可以视为JSON对象…...
Go基于协程池的延迟任务调度器
原理 通过用一个goroutine以及堆来存储要待调度的延迟任务,当达到调度时间后,将其添加到协程池中去执行。 主要是使用了chan、Mutex、atomic及ants协程池来实现。 用途 主要是用于高并发及大量定时任务要处理的情况,如果使用Go协程来实现每…...
k8S通过代理将集群外的中间件引入集群内访问 —— 筑梦之路
背景说明 有部分中间件是跑在Kubernetes集群之外,我们希望通过service的方式来访问集群外的中间件,比如访问我们k8s集群外的elasticsearch集群。 ES节点本身又处在一个负载均衡IP:192.168.100.100 之后,但是代理的端口号是9202&am…...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...

高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...

群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...

Android写一个捕获全局异常的工具类
项目开发和实际运行过程中难免会遇到异常发生,系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler,它是Thread的子类(就是package java.lang;里线程的Thread)。本文将利用它将设备信息、报错信息以及错误的发生时间都…...

Axure零基础跟我学:展开与收回
亲爱的小伙伴,如有帮助请订阅专栏!跟着老师每课一练,系统学习Axure交互设计课程! Axure产品经理精品视频课https://edu.csdn.net/course/detail/40420 课程主题:Axure菜单展开与收回 课程视频:...

aurora与pcie的数据高速传输
设备:zynq7100; 开发环境:window; vivado版本:2021.1; 引言 之前在前面两章已经介绍了aurora读写DDR,xdma读写ddr实验。这次我们做一个大工程,pc通过pcie传输给fpga,fpga再通过aur…...

[KCTF]CORE CrackMe v2.0
这个Reverse比较古老,已经有20多年了,但难度确实不小。 先查壳 upx压缩壳,0.72,废弃版本,工具无法解压。 反正不用IDA进行调试,直接x32dbg中,dump内存,保存后拖入IDA。 这里说一下…...