首页 > 代码库 > spring MVC mybatis dispacherServlet(源码解读)
spring MVC mybatis dispacherServlet(源码解读)
dispacherServlet是servlet的实现类,是spring MVC的前端转发器,是spring MVC的核心。
那么它做了哪些事呢?
它主要做了两件事:
NO1:
看如下源码:
/** * Initialize the strategy objects that this servlet uses. * <p>May be overridden in subclasses in order to initialize further strategy objects. */ protected void initStrategies(ApplicationContext context) { //初始化分段上传解析器(成对文件上传的解析和封装工作),没有默认的实现 initMultipartResolver(context); //初始化地域解析器,默认实现是AcceptHeaderLocaleResolver initLocaleResolver(context); //初始化主题解析器,默认实现是FixedThemeResolver initThemeResolver(context); //初始化处理器映射,这是个集合, 默认实现是BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping initHandlerMappings(context); //初始化处理器适配器,这是个集合,默认实现是HttpRequestHandlerAdapter,SimpleControllerHandlerAdapter和AnnotationMethodHandlerAdapter initHandlerAdapters(context); //初始化处理器异常解析器,这是个集合,默认实现是AnnotationMethodHandlerExceptionResolver,ResponseStatusExceptionResolver和DefaultHandlerExceptionResolver initHandlerExceptionResolvers(context); //初始化请求到视图名解析器,默认实现是DefaultRequestToViewNameTranslator initRequestToViewNameTranslator(context); //初始化视图解析器,这是个集合,默认实现是InternalResourceViewResolver initViewResolvers(context); }
NO2:
每次请求都会调用它的doService方法,在doService方法中调用它的doDispatch方法。
doService方法可看代码中的两处注释:
重点在于调用它的doDispatch方法:
doDispatch(request, response);
首先我们来看方法doDispatch的注释:
可以简单理解成:所有的请求都将在这个方法里映射到指定的handler的指定的方法(前提:请求路径正确)。
我们来一步一步解析这个方法:
以下,为
doDispatch方法的源码:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { // processedRequest是经过checkMultipart方法处理过的request请求 HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (logger.isDebugEnabled()) { logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified); } if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Error err) { triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }
第一行新建的变量processedRequest 会在
后面某一行(在doDispatch方法中,如下:)
processedRequest = checkMultipart(request);
中被方法处理加工,checkMultipart方法也是dispacherServlet类中的一个方法,源码如下:
那么这个方法的作用是什么呢?
关键是下面这一句:
this.multipartResolver != null && this.multipartResolver.isMultipart(request)
这一句代码做了如下两个判断:
1.dispacherServlet中初始化后的multipartResolver是否为空(配置文件中是否配置,初始化dispacherServlet时没有默认实例);
2.multipartResolver的方法isMultipart的作用是判断本次请求是否为文件上传。
如下为isMultipart的源码:
通过注释,可简单理解为:该方法通常以检查content-type是否为multipart/form-data的方式判断本次请求是否为文件上传,但实际功能需要看具体解析器对该方法的实现细节。
checkMultipart方法大致如此,再具体一些的内容在这里我就不赘述了,有兴趣的朋友可以自己看源码。
(多嘴一句:若想使用multipartResolver不要忘了增加jar包支持:commons.fileupload,common.io).
---------------------------------------
方法doDispatch的第二行新建了变量mappedHandler ,
类型为HandlerExecutionChain ,通过查看该类的源码,可清楚请作用,如下:
可理解其为一个处理链,包含了所有的handler和拦截器。
以下两行代码为doDispatch的核心:
// Determine handler for the current request. mappedHandler = getHandler(processedRequest);
// Determine handler adapter for the current request. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
通过注释,可理解前一句的作用:映射到指定的handler,
后一句:映射到指定的handler中具体的一个方法(handler adapter)。
以下是我debug断点的显示数据:
该方法时DispatcherServlet类中的方法getHandler,可以看到这里会对所有handlerMapper进行遍历,后执行HandlerMappering的getHandler方法,
如下:为HandlerMappering的getHandler方法:
这个方法会返回一个handler和所有的拦截器,组装成了一个HandlerExecutionChain类。也就是在方法doDispatch第二行代码里定义的mappedHandler,
该方法的具体实现是在org.springframework.web.servlet.handler.AbstractHandlerMapping中,如下:
/** * Look up a handler for the given request, falling back to the default * handler if no specific one is found. * @param request current HTTP request * @return the corresponding handler instance, or the default handler * @see #getHandlerInternal */ @Override public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); } HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; }
这里的getHandlerInternal是个抽象方法,有具体的HandlerMapping来实现,获取到的handler如果为空,则获取默认配置的handler,若为string类型,则表示要去spring配置容器中去找这个bean。
未结束。
spring MVC mybatis dispacherServlet(源码解读)