SpringMVC中DispatcherServlet的doService->doDispatch方法

xiaoxiao2021-02-28  40

我们知道Servlet的service方法是被Servlet容器调用的,这个时机是发生的有客户端向servlet请求服务时调用的,而这些都将其委托给DispatcherServlet的doDispatch方法。我们查看其关键代码。

processedRequest = checkMultipart(request); multipartRequestParsed = processedRequest != request; // Determine handler for the current request. mappedHandler = getHandler(processedRequest, false);//1:获得HandlerExecutionChain if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request.参数为HandlerExcutionChain中的handler                                 //handlerAdapter在初始化servlet时就已经设置好了 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());//2:获得HandlerAdapter // Process last-modified header, if supported by the handler. String method = request.getMethod();//获得请求的方法                                 //判定method....做出相关执行                                 //利用chain中的拦截器,调用拦截器的preHandle方法,对请求进行拦截处理,如果出现异常,则直接返回 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } try { // Actually invoke the handler.                                         //真正的对request进行处理,并返回一个ModelAndView对象 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); } finally { if (asyncManager.isConcurrentHandlingStarted()) { return; } }                                 //如果没有设置viewName,则通过方法设置默认的viewName applyDefaultViewName(request, mv);                                 //得到ModelAndView,执行拦截器的postHandle方法                                 mappedHandler.applyPostHandle(processedRequest, response, mv);                                 //将mv或者exception写入response中。。返回给客户端                                 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

1.1首先获取HandlerExcutionChain

protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) throws Exception { return getHandler(request); } protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { for (HandlerMapping hm : this.handlerMappings) {//遍历这个handerMappings,那我们就需要知道handlerMappings是怎么设置 //handlerMappings是在初始化策略中初始化handlerMappings时通过扫描ApplicationContext时获取的                         //其中HandlerMapping类的Bean,其中就包括RequestMappingHandlerMapping实例                         if (logger.isTraceEnabled()) { logger.trace(         "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'"); }//我们暂时讨论其中的RequestMappingHandlerMapping实例 HandlerExecutionChain handler = hm.getHandler(request);//所以关键的需要chain的方法在这 if (handler != null) { return handler; } } return null; }

1.2:跳到RequestMappingHandlerMapping的getHandler方法中

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Object handler = getHandlerInternal(request);//获取内部的handler,如果没有则返回默认的handler,是一个MethodHandler                 //。。。。。。 // Bean name or resolved handler?判定是bean名字还是实例 if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); }                 //通过获得到的HandlerMethod创建一个HandlerExcutionChain。 return getHandlerExecutionChain(handler, request);//1.5 } protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);//获取request的查找路径 if (logger.isDebugEnabled()) { logger.debug("Looking up handler method for path " + lookupPath); }                 //获得存入RequestMappingHandlerMapping中的handlerMethods属性的HandlerMethod HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);                 //。。。。。。。。                                 return (handlerMethod != null) ? handlerMethod.createWithResolvedBean() : null; }

1.3:如何获取HandlerMethod

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { List<Match> matches = new ArrayList<Match>(); List<T> directPathMatches = this.urlMap.get(lookupPath);//直接根据path获取存入urlMap中的MappingInfo if (directPathMatches != null) { addMatchingMappings(directPathMatches, matches, request);//将匹配好的MappingInfo放入matches } if (!matches.isEmpty()) { Comparator<Match> comparator = new MatchComparator(getMappingComparator(request)); Collections.sort(matches, comparator);//排序 Match bestMatch = matches.get(0);//只会返回第一个匹配的Match                         //有多个则比较,相等则抛出异常。。。。                         //将uri中的模板参数暴露在request的属性上 handleMatch(bestMatch.mapping, lookupPath, request); return bestMatch.handlerMethod;//返回HandlerMethod } else { return handleNoMatch(handlerMethods.keySet(), lookupPath, request); } }

1.4:通过传入一个Match的集合引用,将HandlerMethod和MappingInfo封装进Match当中

private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) { for (T mapping : mappings) { T match = getMatchingMapping(mapping, request);//不太懂里面的作用,反正还是返回MappingInfo if (match != null) {                              //通过mappingInfo从handlerMethods那得到HandlerMethod,所以返回的match中有MappingInfo以及HandlerMethod                              matches.add(new Match(match, handlerMethods.get(mapping))); } } }

1.5创建一个HandlerExcutionChain

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain) ?//传入handler (HandlerExecutionChain) handler : new HandlerExecutionChain(handler);//新建一个chain对象 chain.addInterceptors(getAdaptedInterceptors());//往chain中添加拦截器,这个以后再讲                 //这两种拦截器是有区别的,一个应该是全局的,一个是根据正则匹配的,只有符合表达式的chain才能添加拦截器。。 String lookupPath = urlPathHelper.getLookupPathForRequest(request); for (MappedInterceptor mappedInterceptor : mappedInterceptors) { if (mappedInterceptor.matches(lookupPath, pathMatcher)) { chain.addInterceptor(mappedInterceptor.getInterceptor());//往chain中添加拦截器 } } return chain; }

最后对ModelAndView进行渲染

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {                 //异常暂时不考虑其实现细节 // Did the handler return a view to render? if (mv != null && !mv.wasCleared()) { render(mv, request, response);//渲染modelAndView if (errorView) { WebUtils.clearErrorRequestAttributes(request); } }                 //省略。。。 if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Concurrent handling started during a forward return; } if (mappedHandler != null) { mappedHandler.triggerAfterCompletion(request, response, null); } } protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { // Determine locale for request and apply it to the response. Locale locale = this.localeResolver.resolveLocale(request);//通过localResolver解析出request中的local response.setLocale(locale);//对响应设置local,肯定要一致才行不,。。 View view; if (mv.isReference()) {//mv中的view是不是一个字符串, // We need to resolve the view name.//是,则需要通过viewName以及内部数据模型解析得到View view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request); } else { // No need to lookup: the ModelAndView object contains the actual View object. view = mv.getView(); } // Delegate to the View object for rendering.将渲染工作交给view,并传入内部数据模型,所以实际的渲染工作是view完成的 view.render(mv.getModelInternal(), request, response); } public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception { if (logger.isTraceEnabled()) { logger.trace("Rendering view with name '" + this.beanName + "' with model " + model + " and static attributes " + this.staticAttributes); }                 //合并一些静态数据以及requestContext中的数据 Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);                 //预处理request和response prepareResponse(request, response);                 //这个方法的实现每个视图引擎都有不同的处理                 renderMergedOutputModel(mergedModel, request, response);//通过合并完的model进行渲染 }可以预测,最后通过渲染得到的内容会写入到reponse当中。。。。
转载请注明原文地址: https://www.6miu.com/read-2625820.html

最新回复(0)