先看一下SpringMVC的处理流程:
各个组件的作用:
DispatcherServlet
:分发请求HandlerMapping
:根据URL匹配能够处理当前request
的Handler
(也就是我们的Controller
)和拦截器HandlerAdapter
:负责实际执行Handler
的处理方法,并返回ModelAndView
ViewResolver
:将ModelAndView
解析为实际的视图
具体过程
- 首先用户发送请求 —> DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行 处理,作为统一访问点,进行全局的流程控制;
- DispatcherServlet —> HandlerMapping, HandlerMapping 将会把请求映射为
HandlerExecutionChain
对象(包含Handler 处理器和HandlerInterceptor
拦截器)对象 - DispatcherServlet —> HandlerAdapter,HandlerAdapter 将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理,并返回 ModelAndView;
- ModelAndView —> ViewResolver,ViewResolver 将把ModelAndView中的逻辑视图名解析为具体的 View
- View —> 渲染,View 会根据传进来的 Model 模型数据进行渲染
- 返回控制权给 DispatcherServlet,由 DispatcherServlet 返回响应给用户,到此一个流程结束。
上面的流程有两个关键点:HandlerMapping
和HandlerAdapter
,HandlerAdapter
据说是使用了适配器模式,但具体适配了什么,我一直不知道🤨,直到后面看到了一篇博客才明白。至于它俩的作用,还得从Controller的定义方式说起
SpringMVC中定义Controller的方式有三种:
@RequestMapping
最最最常用的方式,除了这个都不知道其他的了🤣- 继承 org.springframework.web.servlet.mvc.Controller接口,大概是这样:
1 |
|
- 继承 org.springframework.web.HttpRequestHandler接口
不管后面两个怎么实现,总之,他们仨的处理方式是不一样的,需要用到不同的HandlerMapping
和HandlerAdapter
处理,比如:
@RequestMapping
→RequestMappingHandlerMapping
和RequestMappingHandlerAdapter
Controller
接口 →BeanNameUrlHandlerMapping
和HttpRequestHandlerAdapter
HttpRequestHandler
接口 →BeanNameUrlHandlerMapping
和HttpRequestHandlerAdapter
HandlerMapping
HandlerMapping
处理后所有的URL和对应的Handler都会被放在一个Map里做映射,这里其实是用了一个策略模式,根据Controller定义方式的不同使用不同策略的HandlerMapping
去处理
HandlerMapping
是一个策略接口,RequestMappingHandlerMapping
和BeanNameUrlHandlerMapping
是对应的具体策略
HandlerExecutionChain
是一个封装策略的上下文角色
来看一下如何根据request
来获取HandlerMapping
:
1 | protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { |
HandlerAdapter
说完HandlerMapping
之后,下面就要来介绍HandlerAdapter
了。
既然Handler
有多种实现形式,但是Servlet需要的处理方法的结构却是固定的,都是以request
和response
作为方法入参,因此HandlerAdapter
的实现类都实现了统一的handle()
方法来处理Servlet
不过由于上面提到的Handler
的形式不同,@RequestMapping
对应的Handler
是一个方法,而其他两个对应的Handler
是一个类,而HandlerAdapter使用了适配器模式能够模糊掉具体的实现,从而就能提供统一访问接口(妙😎)
我们来看一下getHandlerAdapter()
方法,注意Handler
是Object类型:
1 | protected HandlerAdapter getHandlerAdapter(Object handler) |
DispatcherServlet的分发流程
最后看一下DispatcherServlet#doDispatch()
的分发流程,注意DispatcherServlet
是如何使用HandlerMapping
和HandlerAdapter
:
1 | protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { |
参考: