先看一下SpringMVC的处理流程:

各个组件的作用:
DispatcherServlet:分发请求HandlerMapping:根据URL匹配能够处理当前request的Handler(也就是我们的Controller)和拦截器HandlerAdapter:负责实际执行Handler的处理方法,并返回ModelAndViewViewResolver:将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和RequestMappingHandlerAdapterController接口 →BeanNameUrlHandlerMapping和HttpRequestHandlerAdapterHttpRequestHandler接口 →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 { |
参考: