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对象来处理请求和生成响应。
//实现了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。但是,它通常只用于处理一些特定的请求,比如文件上传和下载,而不是用于处理一般的用户请求。
@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会调用这个方法来处理请求。
@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来处理请求。
可以理解为:
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);
}
请求的流程:
- 用户发送请求到DispatcherServlet。
- dispatcherServlet收到请求调用处理器映射器HandlerMapping,当HandlerMapping找到一个匹配的处理程序时,它会创建一个HandlerExecutionChain对象,HandlerExecutionChain是一个包含处理程序和所有匹配的拦截器(HandlerInterceptor)的对象。拦截器可以在请求处理之前和之后执行额外的操作,最后将HandlerExecutionChain返回给dispatcherServlet。
- DispatcherServlet会根据处理器Handler找到处理器适配器HandlerAdaper。执行参数封装,数据格式转换,数据验证等操作
- HandlerAdaper执行处理器处理器Handler,并将结果ModelAndView返回给DispatcherServlet。
- dispatcherServlet将ModelAndView传给视图解析器ViewReslover。
- ViewReslover将解析ModelAndView并返回view给disatcherServlet。
- dispatcherServlet对view进行渲染试图。
dispatcherServlet解释请求流程
其实上述的流程都是在DispatcherServlet的doDispatch里完成的。
DispatcherServlet
是一个继承自 Servlet
的关键组件,因此当接收到请求时,会首先进入 Servlet
的 service
方法,然后调用 doGet/doPost
方法,最后进入 processRequestdoService
方法,从而触发 doDispatch
方法。这个 doDispatch
方法中,执行了以下关键步骤:
1、检查请求类型:首先,会检查是否是文件上传的请求。如果是,则进行相应的处理。
processedRequest = checkMultipart(request);
2、获取handler:然后根据请求获取 HandlerExecutionChain
。如果没有找到对应的处理器链,那么就会返回404错误。
HandlerExecutionChain mappedHandler = getHandler(processedRequest);
if(mappedHandler == null){
noHandlerFound(processedRequest, response);
return;
}
3、查找适配器:有了handler,就可以通过处理器找到对应的适配器 HandlerAdapter
。这个适配器是 Spring MVC 中的一个关键组件,它使得 Spring MVC 可以支持多种类型的处理器,不仅仅是一个。
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
4、执行前置拦截器:这个步骤会执行所有的前置拦截器。
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
5、处理请求:然后 HandlerAdapter
会执行处理器中的一系列操作,如参数封装,数据格式转换,数据验证等。
ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
6、设置默认视图:如果 ModelAndView
中没有设置视图,那么这里会为其设置一个默认视图。
applyDefaultViewName(processedRequest, mv);
7、执行后置处理器:在处理完请求后,这个步骤会执行所有的后置处理器。
mappedHandler.applyPostHandle(processedRequest, response, mv);
8、渲染视图并响应用户:最后,DispatcherServlet
会将 ModelAndView
对象传给 ViewReslover
视图解析器进行解析,得到具体的视图对象,并进行视图渲染,最后响应给用户。
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 的。