SpringMvc源码分析-请求流程(一)

SpringMvc源码分析-从前端到接口请求流程

SpringMvc执行流程

其实SpringMVC请求原理很简单:说白了就是用一个DispatcherServlet 封装了一个Servlet的调度中心, 由调度中心帮我们调用我们的处理方法:在这个过程中调度中心委托给各个组件执行具体工作 ,比如帮我们映射方法请求、帮我解析参数、调用处理方法、响应数据和页面 等

名词解释

DispatcherServlet

它负责协调和组织不同组件完成请求处理并返回响应工作。它是SpringMVC统一的入口,所有的请求都通过它。

ViewReslover

根据ModelAndView的视图去找具体的jsp封装在View对象。

View

View是Spring MVC框架中的一个接口,它定义了如何渲染模型数据并生成响应。View对象负责将模型数据渲染为客户端可以理解的格式,例如HTML、JSON或XML等。

Handler

Handler表示请求处理器,(自己写的业务逻辑方法)。是一个Object类型的。在SpringMVC中有四种Handler:

1.实现了Controller接口的Bean对象:这是Spring MVC最初的设计,每个请求对应一个Controller对象,每个Controller只处理一个单一的动作或者请求。该方式的优点是分工明确,缺点是如果请求很多,会产生大量的Controller类,增加了代码的复杂度。在Controller的handleRequest方法中,你可以直接操作HttpServletRequest和HttpServletResponse对象来处理请求和生成响应。

java 复制代码
//实现了Controller接口的Bean对象
@Component("/login")
public class HandlerDemo implements Controller {

   @Override
   public ModelAndView handleRequest
         (HttpServletRequest httpServletRequest,
          HttpServletResponse httpServletResponse)
         throws Exception {
      return new ModelAndView();
   }
}

2.实现了HttpRequestHandler接口的Bean对象:这是另一种处理请求的方式。相比于Controller接口,HttpRequestHandler接口提供了更多的灵活性,因为你可以直接操作ServletRequest和ServletResponse。但是,它通常只用于处理一些特定的请求,比如文件上传和下载,而不是用于处理一般的用户请求。

java 复制代码
@Component("/login")
public class HandlerDemo implements HttpRequestHandler {
   @Override
   public void handleRequest
         (HttpServletRequest request,
          HttpServletResponse response)
         throws ServletException, IOException {
      System.out.println(1);
   }
}

3.添加了@RequestMapping注解的方法:只需要在任意一个Bean的方法上添加@RequestMapping注解,Spring MVC就会自动将这个方法映射到一个URL,然后当这个URL被请求时,Spring MVC会调用这个方法来处理请求。

java 复制代码
@RequestMapping("/showIndex2")
public String index2(ModelAndView modelAndView) {
   modelAndView.addObject("user","zhangsan");
   return "a";
}

HandlerMapping

HandlerMapping是个接口,有不同的实现,HandlerMapping负责去寻找Handler,并且保存路径和Handler之间的映射关系。因为有不同类型的Handler,所以在SpringMVC中会由不同的HandlerMapping来负责寻找Handler,比如:

  • BeanNameUrlHandlerMapping:会把所有路径名(Bean的名称)以 "/" 开头的Bean都当作是一个Handler,BeanNameUrlHandlerMapping就会将这个Bean名称和对应的Bean实例保存到内部的一个Map结构中。然后存入到它的内部Map结构中。当接收到一个请求后,它会根据请求的URL路径去这个Map中查找对应的Handler。一般处理Controller接口和HttpRequestHandler接口
  • RequestMappingHandlerMapping:会把先把所有类上加有@Controller和@RequestMapping的bean找出来然后并解析@RequestMapping中的内容,比如method、path,封装为一个RequestMappingInfo对象,最后把RequestMappingInfo对象做为key,Method对象封装为HandlerMethod对象后作为value,存入Map。

在寻找handler的时候spring会遍历所有的HandlerMapping,挨个寻找,找到了直接返回。

HandlerAdaper

负责调用handler的具体方法,并返回试图的名称。由于我们有好几种handler,分别存放在不同的HandlerMapping中,有的handler是方法,有的是实例。

  • 实现了Controller接口的Bean对象,执行的是Bean对象中的handleRequest()
  • 实现了HttpRequestHandler接口的Bean对象,执行的是Bean对象中的handleRequest()
  • 添加了@RequestMapping注解的方法,具体为一个HandlerMethod,执行的就是当前加了注解的方法

spring在拿到handler后,它会遍历所有已注册的HandlerAdapter,调用它们的supports()方法来检查是否支持当前handler类型。如果支持,则使用该HandlerAdapter来处理请求。

可以理解为:

java 复制代码
for(HandlerAdapter adapter : this.handlerAdapters)){
    if(adapter.supports(handler)){
        //具体执行方法逻辑,去解析Request对象,传参,执行逻辑
        adapter.handle(request,response,handler);
    }
}
//各个adapters中的supports可以理解为
public boolean supports(Object handler) {
    return (handler instanceof Controller);
 }

请求的流程:

  1. 用户发送请求到DispatcherServlet。
  2. dispatcherServlet收到请求调用处理器映射器HandlerMapping,当HandlerMapping找到一个匹配的处理程序时,它会创建一个HandlerExecutionChain对象,HandlerExecutionChain是一个包含处理程序和所有匹配的拦截器(HandlerInterceptor)的对象。拦截器可以在请求处理之前和之后执行额外的操作,最后将HandlerExecutionChain返回给dispatcherServlet。
  3. DispatcherServlet会根据处理器Handler找到处理器适配器HandlerAdaper。执行参数封装,数据格式转换,数据验证等操作
  4. HandlerAdaper执行处理器处理器Handler,并将结果ModelAndView返回给DispatcherServlet。
  5. dispatcherServlet将ModelAndView传给视图解析器ViewReslover。
  6. ViewReslover将解析ModelAndView并返回view给disatcherServlet。
  7. dispatcherServlet对view进行渲染试图。

dispatcherServlet解释请求流程

其实上述的流程都是在DispatcherServlet的doDispatch里完成的。

DispatcherServlet 是一个继承自 Servlet 的关键组件,因此当接收到请求时,会首先进入 Servletservice 方法,然后调用 doGet/doPost 方法,最后进入 processRequestdoService 方法,从而触发 doDispatch 方法。这个 doDispatch 方法中,执行了以下关键步骤:

1、检查请求类型:首先,会检查是否是文件上传的请求。如果是,则进行相应的处理。

java 复制代码
processedRequest = checkMultipart(request);

2、获取handler :然后根据请求获取 HandlerExecutionChain。如果没有找到对应的处理器链,那么就会返回404错误。

java 复制代码
HandlerExecutionChain mappedHandler = getHandler(processedRequest);
if(mappedHandler == null){
    noHandlerFound(processedRequest, response);
    return; 
}

3、查找适配器 :有了handler,就可以通过处理器找到对应的适配器 HandlerAdapter。这个适配器是 Spring MVC 中的一个关键组件,它使得 Spring MVC 可以支持多种类型的处理器,不仅仅是一个。

java 复制代码
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

4、执行前置拦截器:这个步骤会执行所有的前置拦截器。

java 复制代码
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    return;
}

5、处理请求 :然后 HandlerAdapter 会执行处理器中的一系列操作,如参数封装,数据格式转换,数据验证等。

java 复制代码
ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

6、设置默认视图 :如果 ModelAndView 中没有设置视图,那么这里会为其设置一个默认视图。

java 复制代码
applyDefaultViewName(processedRequest, mv);

7、执行后置处理器:在处理完请求后,这个步骤会执行所有的后置处理器。

java 复制代码
mappedHandler.applyPostHandle(processedRequest, response, mv);

8、渲染视图并响应用户 :最后,DispatcherServlet 会将 ModelAndView 对象传给 ViewReslover 视图解析器进行解析,得到具体的视图对象,并进行视图渲染,最后响应给用户。

java 复制代码
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

接下来的内容,我们将更深入地探索 Spring MVC 的工作机制,比如Tomcat启动后Spring MVC是如何创建的,handlerMapping 是如何找到对应的处理器的,adapter 是如何处理处理器的,以及 SPI 如何实现 Spring MVC 的。

ler, mv, dispatchException);

复制代码
接下来的内容,我们将更深入地探索 Spring MVC 的工作机制,比如Tomcat启动后Spring MVC是如何创建的,`handlerMapping` 是如何找到对应的处理器的,`adapter` 是如何处理处理器的,以及 SPI 如何实现 Spring MVC 的。
相关推荐
奋进的芋圆8 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin8 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model20058 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉8 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国8 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_941882489 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈9 小时前
两天开发完成智能体平台
java·spring·go
alonewolf_999 小时前
Spring MVC重点功能底层源码深度解析
java·spring·mvc
沛沛老爹9 小时前
Java泛型擦除:原理、实践与应对策略
java·开发语言·人工智能·企业开发·发展趋势·技术原理
专注_每天进步一点点9 小时前
【java开发】写接口文档的札记
java·开发语言