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 的。
相关推荐
confiself8 分钟前
大模型系列——LLAMA-O1 复刻代码解读
java·开发语言
Wlq041513 分钟前
J2EE平台
java·java-ee
XiaoLeisj20 分钟前
【JavaEE初阶 — 多线程】Thread类的方法&线程生命周期
java·开发语言·java-ee
鹿屿二向箔30 分钟前
基于SSM(Spring + Spring MVC + MyBatis)框架的汽车租赁共享平台系统
spring·mvc·mybatis
豪宇刘34 分钟前
SpringBoot+Shiro权限管理
java·spring boot·spring
Elaine20239139 分钟前
02多线程基础知识
java·多线程
gorgor在码农41 分钟前
Redis 热key总结
java·redis·热key
百事老饼干1 小时前
Java[面试题]-真实面试
java·开发语言·面试
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS医院管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·开源·intellij-idea