当前位置: 首页 > news >正文

SpringMVC的核心架构与请求处理流程

Spring MVC 核心架构


核心组件

组件作用类比
DispatcherServlet前端控制器,统一接收请求并协调各组件处理一个餐厅的前台
HandlerMapping根据请求URL映射到对应的处理器(Controller)路由表
HandlerAdapter执行处理器方法,处理参数绑定、方法调用等适配器(兼容不同处理器)
ViewResolver将逻辑视图名解析为物理视图(如JSP、Thymeleaf)地图导航
View渲染模型数据生成最终响应(HTML/JSON等)厨师(加工数据)
HandlerExceptionResolver统一处理控制器抛出的异常故障应急小组

分层架构

客户端 => DispatcherServlet => HandlerMapping

=> Controller => ModelAndView => View => 响应

相当于

客户端 => 前端控制器 => 处理器映射器 => 处理器 =>模型与视图容器 => 响应器 =>响应

请求处理的流程

  1. 请求到达:客户端发送http请求到前端控制器DispatcherServelt
  2. 查找处理器:前端控制器DispatcherServlet调用HandlerMapping确定目标控制器Controller
  3. 获取适配器:通过处理器适配器HandlerAdapter执行控制器方法
  4. 拦截器预处理:执行拦截器链的preHandle()
  5. 参数绑定:适配器解析请求参数(路径变量、表单数据等),传递给控制器方法
  6. 执行控制器:调用控制器Controller方法执行业务逻辑
  7. 返回模型与视图:控制器Controller返回ModelAndView(或String视图名、@ResponseBody等)
  8. 拦截器后处理:执行拦截器链后的postHandle()
  9. 视图解析:视图解析器ViewResolver将逻辑视图名转换为具体View对象
  10. 视图渲染:响应器View渲染模型数据产生响应内容(HTML/JSON)
  11. 拦截器完成:执行拦截器链的afterCompletion()

关键环节:HTTP请求 → Java对象

当请求到达控制器方法前,Spring MVC会自动提取请求中的各种数据

@RequestParam:获取URL查询字符串参数

// 请求:/search?keyword=spring
@GetMapping("/search")
public String search(@RequestParam("keyword") String keyword) {// keyword = "spring"
}

@PathVariable:获取URL路径中的变量

// 请求:/users/123/profile
@GetMapping("/users/{userId}/profile")
public String profile(@PathVariable("userId") Long id) {// id = 123
}

@RequestBody:将JSON/XML请求体转换为Java对象

// 请求体:{"name":"John","age":30}
@PostMapping("/users")
public User createUser(@RequestBody User user) {// user.getName() = "John"// user.getAge() = 30
}

表单绑定:自动将表单字段映射到对象属性

// 表单字段:username=admin&password=123
@PostMapping("/login")
public String login(UserForm form) {// form.getUsername() = "admin"
}

配置视图解析器的流程

(假如控制器返回一个字符串“success”)

控制器返回字符串 => return ‘success’=> 视图解析器=> 检查配置

=> 前缀+字符串success+后缀=> 合成地址/WEB-INF/views/success.jsp=> 范文实际视图文件

应用配置的前缀和后缀

resolver.setPrefix("/WEB-INF/views/"); // 视图文件目录
resolver.setSuffix(".jsp");            // 文件扩展名

配置文件示例:

@Configuration
public class WebConfig {@Beanpublic ViewResolver viewResolver() {InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setPrefix("/WEB-INF/views/"); // 视图存放目录resolver.setSuffix(".jsp");            // 文件扩展名return resolver;}
}

异常的分层处理

方法级处理(优先级最高)

@Controller
public class UserController {@ExceptionHandler(UserNotFoundException.class)public ResponseEntity<String> handleUserNotFound() {return ResponseEntity.status(404).body("用户不存在");}
}

控制器级处理

@Controller
@ExceptionHandler({IllegalArgumentException.class, DataAccessException.class})
public ResponseEntity<String> handleControllerExceptions() {// 处理本控制器所有指定异常
}

全局处理(最常用)

@ControllerAdvice // 作用于所有控制器
public class GlobalExceptionHandler {// 处理特定异常@ExceptionHandler(ResourceNotFoundException.class)public ResponseEntity<ErrorResponse> handleResourceNotFound(ResourceNotFoundException ex) {ErrorResponse error = new ErrorResponse("NOT_FOUND",ex.getMessage(),System.currentTimeMillis());return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);}// 兜底处理所有未捕获异常@ExceptionHandler(Exception.class)public ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex) {// 返回通用错误响应}
}

关于用户访问个人资料页面的示例

请求GET /users/123/profile

参数绑定:提取路径变量 userId=123

控制器方法处理:

@GetMapping("/users/{userId}/profile")
public String userProfile(@PathVariable Long userId, Model model) {User user = userService.findById(userId); // 可能抛出异常model.addAttribute("user", user);return "user/profile"; // 逻辑视图名
}

处理异常:若用户不存在,抛出UserNotFoundException

视图解析:将"user/profile"转换为/WEB-INF/views/user/profile.jsp

渲染页面并返回响应

http://www.lryc.cn/news/605612.html

相关文章:

  • PostgreSQL dblink 与 Spring Boot @Transactional 的事务整合
  • 网络层概述
  • AngularJS 事件
  • Web 开发 08
  • 智慧社区项目开发(四)——前后端登录认证相关功能实现解析
  • 网关 + MDC 过滤器方案,5分钟集成 日志 traceid
  • Gemini Fullstack LangGraph Quickstart(DeepSeek+Tavily版本)
  • 智慧园区通行效率↑68%!陌讯多模态融合算法的实战解析
  • 【Cpolar实现内网穿透】
  • 转码刷 LeetCode 笔记[1]:3.无重复字符的最长子串(python)
  • 解决宇道项目关于接收日期格式yyyy-MM-dd HH:mm:ss后端自动转为1970-01-01 00:00:00的问题
  • 计算机网络——UDP
  • TOC-Transformer-LSTM-ABKDE,计算机一区算法龙卷风优化算法应用到概率区间预测!Matlab实现
  • css 不错的按钮动画
  • Linux日志管理与时间同步
  • 【数据结构初阶】--二叉树(六)
  • React组件化的封装
  • uniapp中uview组件中u-input格式化后赋值踩坑
  • BGP高级特性之认证
  • 大量图片一次性上传,前端优化方式
  • 使用ANSYS Fluent和群体平衡模型对搅拌罐反应器中的气泡动力学进行建模
  • FastAPI docs接口文档打不开怎么解决
  • 【Linux我做主】进程优先级
  • 智慧收银系统开发进销存库存统计,便利店、水果店、建材与家居行业的库存汇总管理—仙盟创梦IDE
  • 个股期权合约期内遇到标的停牌,如何处置?
  • React的基本语法和原理
  • Protobuf动态解析
  • 自动化备份全网服务器数据平台
  • Spring Boot 项目问题:Web server failed to start. Port 5566 was already in use.
  • [2025CVPR-小样本方向]ImagineFSL:基于VLM的少样本学习的想象基集上的自监督预训练很重要