SpringMvc的执行流程(从源码的角度分析)
之前了解的SpringMvc是从流程图上来了解的,没有从源码的层次来深刻了解SpringMvc的运行流程,这次从源码的层次走一遍流程。
首先,我们要知道SpringMvc的流程图,然后根据流程图来一步一步的走源码。
首先我们要知道DispatchServlet(*控制器),前端发送过来的请求,首先是被这个类接收的,并且通过这个类来进行一系列的调用获得出来结果,这个类是核心。
我们现在来分析DispatchServlet关键的方法doDispatch(request,response),由于代码太多,在此只对关键部分进行分析。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
//先把要用到的组件先给定义好,比如说ModelAndView
HandlerExecutionChain mappedHandler = null;
ModelAndView mv = null;
mappedHandler = getHandler(processedRequest);
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
}
首先我们要明白,handler是干嘛的,顾名思义,他是一个控制器,前端把请求发过来,然后我们根据前端传过来的url或其他的信息来进行一系列的操作找到我们这个相对应的控制器进行逻辑处理。
我们来看到这一句代码:
mappedHandler = getHandler(processedRequest); 从代码字面意思上看,这句话的意思是获取Handler,也就是流程图上的第二步,我们来看一下getHandler(processedRequest)这个方法。
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
第一眼看去我们知道,通过这个方法我们可以得到一个HandlerExecutionChain,而这个handler 可以看到是由HandlerMapping 给到的,那么从流程图上就可以明白1,2,3了。
在这里我们顺便提一下HandlerExecutionChain 的两个构造器
public HandlerExecutionChain(Object handler) {
this(handler, (HandlerInterceptor[]) null);
}
/**
* Create a new HandlerExecutionChain.
* @param handler the handler object to execute
* @param interceptors the array of interceptors to apply
* (in the given order) before the handler itself executes
*/
public HandlerExecutionChain(Object handler, @Nullable HandlerInterceptor... interceptors) {
if (handler instanceof HandlerExecutionChain) {
HandlerExecutionChain originalChain = (HandlerExecutionChain) handler;
this.handler = originalChain.getHandler();
this.interceptorList = new ArrayList<>();
CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList);
CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList);
}
else {
this.handler = handler;
this.interceptors = interceptors;
}
}
从代码里面可以看到,HandlerExecutionChain的类属性里面是有HandlerInterceptor的,并且可以为空。
我们回到doDispatch方法上,代码继续往下走,我们可以看到这句话
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
同上面的方法,我们看看getHandlerAdapter(方法)
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter ha : this.handlerAdapters) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler adapter [" + ha + "]");
}
if (ha.supports(handler)) {
return ha;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
从代码上看到,我们的HandlerAdapter 是从handlerAdapters取来的,那么handlerAdapters又是什么呢?通过DispatcherServlet的源码可以知道,handlerAdapters是它的一个类属性。
那么HandlerAdapter(适配器)又是干嘛用的呢?
前面,我们通过handlerMapping找到了handler,但是handler他不止一个,所以相对应的执行方式就不同了,这时候,我们对应不同的handler就要执行不同的方案。
这样讲可能不好理解,咱们从我们开发中来理解 ,首先,通过handlerMapping找到获取请求的controller,比如说登录模块的UserController,找到这个Controller后,我要运行里面的方法啊,对吧,这时候,我们就需要用到HandlerAdapter然后通过反射去执行里面的方法,执行完毕后返回相应的ModelAndView。
个人理解与总结:
SpringMvc就是一种思想,他把以前的Servlet一个一个的配置,映射,改成了直接通过dispatchServlet来做一个处理,首先调用HandlerMapping来去找对应的控制器,然后找到相应的控制器(Controller)适配的适配器,再通过HandlerAdapter去执行里面的逻辑代码,最后返回我们想要的视图,或者Json串等等。