HandlerExecutionChain:由HandlerMethod和Interceptor集合组成的类,会被HandlerMapping接口的getHandler方法获取。
HandlerInterceptor接口:Spring拦截器基础接口
AbstractHandlerMapping:HandlerMapping的基础抽象类
AsyncHandlerInterceptor:继承HandlerInterceptor接口,额外提供了afterConcurrentHandlingStarted方法,该方法用来处理异步请求。
Web请求被DispatcherServlet截获后,会调用DispatcherServlet的doDispatcher方法。
HandlerExecutionChain mappedHandler = null; mappedHandler = getHandler(processedRequest); HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
首先得到HandlerExecutionChain对象,这个对象包含了HandlerMethod和Interceptors集合,并根据其中的HandlerMethod得到HandlerAdapter。
在HandlerAdapter处理之后,以及处理完成之后会调用HandlerExecutionChain的applyPreHandle、applyPostHandle方法。
DispatchServlet继承关系
DispatchServlet->FrameworkServlet->HttpServletBean->HttpServlet
HttpServlet
HTTP请求刚进来的时候实际上只是一个HTTP请求报文,容器会自动将这个HTTP请求报文包装成一个HttpServletRequest对象,并且自动调用HttpServlet的service()方法来解析这个请求,service()方法会解析HTTP请求行,而请求行由method、uri、http version三个组成,method就是get或者post,service()方法根据method决定是执行doGet还是doPost,这一切都是服务器Tomcat\jetty自动完成的,HTTP的格式也自动被解析。
只要你的类继承了HttpServlet,并且在web.xml里面配置了相应的servlet和mapping,服务器就会自动帮你执行以上过程。
Servlet框架的核心是javax.servlet.Servlet接口,所有的Servlet都必须实现这一接口,其中有三个方法代表了Servlet的生命周期:
- init方法,负责初始化Servlet对象
- service方法,负责相应客户的请求
- destroy方法,负责释放占有的资源
HttpServletBean
HttpServletBean重写了init方法,对初始化流程做了一些处理。主要是:set bean properties from init parameters
1.ServletConfigPropertyValues是HttpServletBean内部静态类,构造过程中会使用ServletConfig对象找出web.xml配置文件中的配置参数并设置到ServletConfigPropertyValues内部
2.使用BeanWrapper构造DispatcherServlet
3.Resource类型参数使用属性编辑器
4.设置DispatcherServlet属性
5.initServletBean()默认实现不做任何处理,子类覆盖该方法可以做任何处理,也就是初始化的时候做更多的事情
<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springConfig/dispatcher-servlet.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
比如上面这段参数,传递了contextConfigLocation参数,之后构造BeanWrapper,这里使用BeanWrapper有2个理由,1.contextConfigLocation属性在FrameworkServlet中定义,HttpServletBean中无定义。2.利用Spring的注入特性,只需要调用stPropertyValues方法就可将contextConfigLocation属性设置到对应实例中,也就是以依赖注入的方式初始化属性。
然后设置DispatcherServlet的contextConfigLocation属性为web.xml中读取的contextConfigLocation参数,该参数用于构造SpringMVC容器上下文。
FrameworkServlet
该类首先覆写了initServletBean方法,如下:
- 初始化WebApplicationContext属性,WebApplicationContext是继承自ApplictionContext接口的接口,该属性也就是spring容器上下文。FrameworkServlet的作用就是将Servlet与Spring容器关联。
- initFrameworkServlet()默认无处理,主要是为了让子类覆盖做一些需要的处理,不过DispatchServlet并没有覆盖该方法。
- rootContext为得到根上下文
- DispatcherServlet有个以WebApplicationContext为参数的构造函数,当使用有WebApplicationContext参数的构造函数时使用到if判断这段代码。
- wac=findWebApplicationContext(),以contextAttribute属性为key从ServletContext中找WebApplicationContext,一般不会设置contextAttribute属性,也就是这里找到的wac为空。
- wac=createWebApplicationContext(rootContext),创建WebApplicationContext上下文,并设置根上下文为父上下文,然后配置ServletConfig,ServletContext等实例到这个上下文中。这个父上下文即web.xml中配置的ContextLoaderListener监听器初始化的容器上下文。
- onRefresh(wac),模板方法,WebApplicationContext创建成功之后会调用,FrameworkServlet空实现,子类Dispatcher会覆写该方法。
- getServletContext().setAttrubute(attrName,wac),将新创建的容器上下文设置到ServletContext中
DispatcherServlet
覆盖了FrameworkServlet中的onRefresh方法:
很明显,initStrategies方法内部会初始化各个策略接口的实现类。比如异常处理初始化initHandlerExceptionResolvers方法,视图处理初始化initViewResolvers方法,请求映射处理初始化initHandlerMappings方法。
DispatcherServlet请求处理过程
HttpServlet提供了service方法用于处理请求,service使用了模板设计模式,在内部对于http get会调用doGet方法,http post方法会调用doPost方法。其内部调用了processRequest方法。
- 得到与当前请求线程绑定的LocalContext和ServletRequestAttrbutes对象,然后构造新的Local和ServletRequestAttrbutes对象。
- 让新构造的LocaleContext和RequestAttributes与当前请求线程绑定(通过ThreadLocal完成)
- doService()抽象方法,具体由子类DispatcherServlet实现
- resetContextHolders()重置LocaleContext与RequestAttributes对象,重置也就是解除请求线程与LocalContext和RequestAttributes对象的绑定。
继续看DispatcherServlet的doService方法:
- 如果该请求是include请求,那么保存一份快照版本的request域中的数据,doDispatcher方法结束之后,这个快照版本中的数据将会覆盖新的request域中的数据。
- request域中设置一些属性
- doDispatch()最重要的方法。请求分发处理。
首先根据请求的路径找到HandlerMethod(带有Method反射属性,也就是对应Controller中的方法),然后匹配路径对应的拦截器,有了HandlerMethod和拦截器构造个HandlerExecutionChain对象。HandlerExecutionChain对象的获取是通过HandlerMapping接口提供的方法中得到。有了HandlerExecutionChain之后,通过HandlerAdapter对象进行处理得到ModelAndView对象,HandlerMethod内部handle的时候,使用各种HandlerMethodArgumentResolver实现类处理HandlerMethod的参数,使用各种HandlerMethodReturnValueHandler实现类处理返回值。 最终返回值被处理成ModelAndView对象,这期间发生的异常会被HandlerExceptionResolver接口实现类进行处理。