Spring MVC核心组件与请求处理流程分析

 更新时间:2025年01月16日 11:46:16   作者:小·恐·龙  
该文章详细介绍了SpringMVC的请求处理流程,从Filter链处理开始,经过DispatcherServlet、HandlerMapping、HandlerAdapter、拦截器(前置处理、后置处理、完成处理)到视图渲染,感兴趣的朋友跟随小编一起看看吧

Spring MVC请求处理完整流程详解

一、流程文字描述

当一个HTTP请求到达服务器后,会经历以下流程:

Filter链处理(入口)

  • 请求首先经过Filter链
  • 每个Filter按照定义的顺序执行doFilter方法的前置处理
  • Filter通过调用chain.doFilter()将请求传递给下一个Filter

DispatcherServlet接收请求

  • 所有Filter处理完后,请求到达DispatcherServlet
  • DispatcherServlet作为前端控制器,统一处理所有请求

寻找Handler

  • DispatcherServlet调用getHandler方法
  • 遍历所有HandlerMapping,找到与当前URL匹配的Handler
  • 找到Handler后,把Handler和对应的拦截器封装成HandlerExecutionChain对象

获取HandlerAdapter

  • 根据Handler的类型,遍历所有HandlerAdapter
  • 找到支持该Handler类型的HandlerAdapter
  • HandlerAdapter用于调用Handler并处理参数、返回值等

拦截器前置处理

  • 按顺序调用HandlerExecutionChain中所有拦截器的preHandle方法
  • 如果任一拦截器的preHandle返回false,则中断请求处理
  • 中断时会触发已执行的拦截器的afterCompletion方法

Handler处理请求

  • 通过HandlerAdapter调用Handler(Controller方法)
  • HandlerAdapter负责参数解析、类型转换
  • Handler执行业务逻辑,返回处理结果

拦截器后置处理

  • Handler执行完成后,按逆序调用所有拦截器的postHandle方法
  • 此时视图尚未渲染

视图渲染

  • 根据Handler返回的结果进行视图渲染
  • 如果是@RestController,将返回值转换为JSON/XML等格式
  • 如果是传统@Controller,解析视图名称并渲染视图

拦截器完成处理

  • 视图渲染完成后,按逆序调用所有拦截器的afterCompletion方法
  • 无论过程中是否有异常,都会执行afterCompletion

Filter链处理(出口)

  • 响应会按照与处理请求相反的顺序经过Filter链
  • 每个Filter执行doFilter方法的后置处理
  • 最终响应返回给客户端

二、关键组件详解

2.1 HandlerMapping

// 核心数据结构
public class RequestMappingHandlerMapping {
    // 保存URL与处理器方法的映射关系
    private final Map<RequestMappingInfo, HandlerMethod> mappingLookup;
}
// 映射示例
mappingLookup = {
    RequestMappingInfo{
        patterns=/users/{id},    // URL模式
        methods=GET,             // HTTP方法
        params=[],              // 请求参数
        headers=[]              // 请求头
    } -> HandlerMethod{UserController.getUser()}
}

2.2 HandlerExecutionChain

public class HandlerExecutionChain {
    // Handler本身(如Controller的方法)
    private final Object handler;
    // 与Handler关联的拦截器列表
    private List<HandlerInterceptor> interceptors;
}

2.3 HandlerAdapter

// 处理@RequestMapping注解的方法
public class RequestMappingHandlerAdapter implements HandlerAdapter {
    public ModelAndView handle(request, response, handler) {
        // 1. 解析请求参数
        Object[] args = resolveParameters(request, handler);
        // 2. 调用Controller方法
        Object returnValue = invokeMethod(handler, args);
        // 3. 处理返回值
        return processReturnValue(returnValue);
    }
}

2.4 视图渲染

// 1. @RestController(JSON渲染)
@GetMapping("/api/user")
public User getUser() {
    return user;  // 自动转换为JSON
}
// 2. @Controller(HTML渲染)
@GetMapping("/user")
public String user(Model model) {
    model.addAttribute("user", user);
    return "userView";  // 解析为具体视图
}

三、拦截器执行流程

3.1 拦截器定义

public class LogInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(request, response, handler) {
        System.out.println("LogInterceptor - preHandle");
        return true;
    }
    @Override
    public void postHandle(request, response, handler, mv) {
        System.out.println("LogInterceptor - postHandle");
    }
    @Override
    public void afterCompletion(request, response, handler, ex) {
        System.out.println("LogInterceptor - afterCompletion");
    }
}

3.2 执行顺序示例

Filter1 - 请求处理
    Filter2 - 请求处理
        LogInterceptor - preHandle
            SecurityInterceptor - preHandle
                Controller方法执行
            SecurityInterceptor - postHandle
        LogInterceptor - postHandle
        视图渲染
            SecurityInterceptor - afterCompletion
        LogInterceptor - afterCompletion
    Filter2 - 响应处理
Filter1 - 响应处理

3.3 拦截器调用过程

// 1. preHandle调用(正序)
for (HandlerInterceptor interceptor : interceptors) {
    if (!interceptor.preHandle(request, response, handler)) {
        triggerAfterCompletion(request, response, handler, null);
        return false;
    }
}
// 2. postHandle调用(逆序)
for (int i = interceptors.length - 1; i >= 0; i--) {
    interceptors[i].postHandle(requestresponse, handler, mv);
}
// 3. afterCompletion调用(逆序)
for (int i = interceptors.length - 1; i >= 0; i--) {
    interceptors[i].afterCompletion(request, response, handler, ex);
}

到此这篇关于Spring MVC核心组件与请求处理流程的文章就介绍到这了,更多相关Spring MVC请求处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • sa-token整合springboot中的代码示例展示

    sa-token整合springboot中的代码示例展示

    sa-token 是一个轻量级的 Java 权限认证框架,它可以很方便地集成到 Spring Boot 项目中,以提供简洁的认证和授权功能,这篇文章主要介绍了sa-token整合springboot中的代码示例展示,需要的朋友可以参考下
    2024-04-04
  • WebSocket无法注入属性的问题及解决方案

    WebSocket无法注入属性的问题及解决方案

    这篇文章主要介绍了WebSocket无法注入属性的问题及解决方法,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • 扩展tk.mybatis的流式查询功能实现

    扩展tk.mybatis的流式查询功能实现

    mybatis查询默认是一次获取全部,如果数据过于庞大,就会导致OOM问题,本文就介绍了tk.mybatis 流式查询,具有一定的参考价值,感兴趣的可以了解一下
    2021-12-12
  • Spring解决循环依赖问题的四种方法汇总

    Spring解决循环依赖问题的四种方法汇总

    这篇文章主要介绍了Spring解决循环依赖问题的四种方法汇总,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-07-07
  • spring如何使用xml装配bean

    spring如何使用xml装配bean

    这篇文章主要介绍了spring如何使用xml装配bean,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • 详解shrio的认证(登录)过程

    详解shrio的认证(登录)过程

    这篇文章主要介绍了shrio的认证(登录)过程,帮助大家更好的理解和使用shrio框架,感兴趣的朋友可以了解下
    2021-02-02
  • springmvc+ajax+formdata上传图片代码实例

    springmvc+ajax+formdata上传图片代码实例

    这篇文章主要介绍了springmvc+ajax+formdata上传图片代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • Spring框架开发scope作用域分析总结

    Spring框架开发scope作用域分析总结

    这篇文章主要介绍了Spring框架开发中scope作用域的分析总结,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2021-09-09
  • 详解SpringBoot如何自定义自己的Starter组件

    详解SpringBoot如何自定义自己的Starter组件

    这篇文章主要为大家详细介绍了在SpringBoot中如何自定义自己的Starter组件,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-03-03
  • Java实现的不同图片居中剪裁生成同一尺寸缩略图功能示例

    Java实现的不同图片居中剪裁生成同一尺寸缩略图功能示例

    这篇文章主要介绍了Java实现的不同图片居中剪裁生成同一尺寸缩略图功能,涉及java针对图片的读取、属性修改等相关操作技巧,需要的朋友可以参考下
    2017-09-09

最新评论