萌新学习SpringMVC (2)

我们在DispatcherServlet类上可以看到很多熟悉的成员变量(组件),所以看下来,我们要的东西,DispatcherServlet可全都有

// 文件处理器 private MultipartResolver multipartResolver; // 映射器 private List<HandlerMapping> handlerMappings; // 适配器 private List<HandlerAdapter> handlerAdapters; // 异常处理器 private List<HandlerExceptionResolver> handlerExceptionResolvers; // 视图解析器 private List<ViewResolver> viewResolvers;

然后我们会发现它们在initStrategies()上初始化:

protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); }

请求进到DispatcherServlet,其实全部都会打到doService()方法上。我们看看这个doService()方法做了啥:

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { // 设置一些上下文...(省略一大部分) request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); try { // 调用doDispatch doDispatch(request, response); } finally { if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { if (attributesSnapshot != null) { restoreAttributesAfterInclude(request, attributesSnapshot); } } } }

所以请求会走到doDispatch(request, response);里边,我们再进去看看:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { 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); // 找到HandlerExecutionChain mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; } // 得到对应的hanlder适配器 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // 拦截前置处理 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // 真实处理请求 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); // 视图解析器处理 applyDefaultViewName(processedRequest, mv); // 拦截后置处理 mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } } }

这里的流程跟我们上面的图的流程几乎是一致的了。我们从源码可以知道的是,原来SpringMVC的拦截器是在MappingHandler的时候一齐返回的,返回的是一个HandlerExecutionChain对象。这个对象也不难,我们看看:

public class HandlerExecutionChain { private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class); // 真实的handler private final Object handler; // 拦截器List private HandlerInterceptor[] interceptors; private List<HandlerInterceptor> interceptorList; private int interceptorIndex = -1; }

OK,整体的流程我们是已经看完了,顺便要不我们去看看它是怎么找到handler的?**三歪带着你们冲!**我们点进去getHandler()后,发现它就把默认实现的Handler遍历一遍,然后选出合适的:

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // 遍历一遍默认的Handler实例,选出合适的就返回 for (HandlerMapping hm : this.handlerMappings) { HandlerExecutionChain handler = hm.getHandler(request); if (handler != null) { return handler; } } return null; }

再进去getHandler里边看看呗,里边又有几层,我们最后可以看到它根据路径去匹配,走到了lookupHandlerMethod这么一个方法

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { List<Match> matches = new ArrayList<Match>(); // 获取路径 List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath); // 对匹配的排序,找到最佳匹配的 if (!matches.isEmpty()) { Comparator<Match> comparator = new MatchComparator(getMappingComparator(request)); Collections.sort(matches, comparator); if (logger.isTraceEnabled()) { logger.trace("Found " + matches.size() + " matching mapping(s) for [" + lookupPath + "] : " + matches); } Match bestMatch = matches.get(0); if (matches.size() > 1) { if (CorsUtils.isPreFlightRequest(request)) { return PREFLIGHT_AMBIGUOUS_MATCH; } Match secondBestMatch = matches.get(1); if (comparator.compare(bestMatch, secondBestMatch) == 0) { Method m1 = bestMatch.handlerMethod.getMethod(); Method m2 = secondBestMatch.handlerMethod.getMethod(); throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" + request.getRequestURL() + "': {" + m1 + ", " + m2 + "}"); } } handleMatch(bestMatch.mapping, lookupPath, request); return bestMatch.handlerMethod; } else { return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjszg.html