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查询字符串参数

java 复制代码
// 请求:/search?keyword=spring
@GetMapping("/search")
public String search(@RequestParam("keyword") String keyword) {
    // keyword = "spring"
}

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

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

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

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

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

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

配置视图解析器的流程

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

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

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

应用配置的前缀和后缀

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

配置文件示例:

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

异常的分层处理

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

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

控制器级处理

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

全局处理(最常用)

java 复制代码
@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

控制器方法处理:

java 复制代码
@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

渲染页面并返回响应

相关推荐
天空属于哈夫克32 天前
企业微信二次开发:精准实现关键词自动回复
架构·企业微信
晨米酱2 天前
AGENTS.md:Agent 的上下文策略层
面试·架构·agent
这个DBA有点耶2 天前
MVCC深入:Read View、版本链与快照读——InnoDB并发控制的内核
数据库·mysql·架构
码流子2 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
moMo2 天前
从固定流程到问题路由:让 LangGraph RAG 按需检索
架构
白远山2 天前
上海24小时自助健身房解决方案实战指南与经验分享
java·数据库·架构·需求分析
LorryJovens2 天前
【LAAP科研】双系统具身AGI范式研究——基于LAAP认知架构与Jev概率决策模型的系统性技术调研与范式验证
人工智能·gpt·安全·架构
JQweryuiop2 天前
中小型游戏陪练工作室数字化管理实践:基于七彩屋电竞护航小程序订单、履约与绩效系统的落地复盘
大数据·游戏·小程序·架构
LONGZETECH2 天前
一线职教实测:风光 580 汽车故障诊断仿真系统,破解实车实训四大核心痛点
人工智能·学习·安全·架构·汽车
萧瑟余晖2 天前
Netty 核心组件与 Reactor 模型详解
网络·架构