来自官网:
在网上找到的更加详细的图:
我们搜索下DispatchServlet类看看有没有,果然有一个
看下DispatchServlet的类关系图
1 研究DispatchServlet
看下这个类的全部方法,不用想一定会有一个类似于Servlet中的service方法,果然如此
1.1 DispatchServlet的doService方法
在doService方法中一定是主要处理业务请求的
@Override protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { // 记录日志 logRequest(request); // 保留请求属性的快照,以便在包含之后能够恢复原始属性 Map<String, Object> attributesSnapshot = null; if (WebUtils.isIncludeRequest(request)) { attributesSnapshot = new HashMap<>(); Enumeration<?> attrNames = request.getAttributeNames(); while (attrNames.hasMoreElements()) { String attrName = (String) attrNames.nextElement(); if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) { attributesSnapshot.put(attrName, request.getAttribute(attrName)); } } } // 设置一些request的值,使框架对象对处理程序和视图对象可用 request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext()); ...... try { //最主要的doDispatch方法 doDispatch(request, response); } ...... }
1.2 DispatchServlet的doDispatch方法
doDispatch是被doService方法调用,是处理请求流程的一个主要方法,主要分为一下几个流程
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { ...... try { ModelAndView mv = null; Exception dispatchException = null; try { //检查处理Multipart请求 processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // 确定当前请求的处理,请求Handler mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } // 获取适配器 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // 判断请求方法 String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // 实际的Handler调用 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } // 解析ModelAndView applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } ...... // 渲染视图 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } ...... finally { ...... } }
2 深入源码
2.1 怎样找到Handler的?
先写一个RequestMapping
@ResponseBody @RequestMapping("/helloMvc") public String helloMvc() { return "Hello I am Spring MVC"; }
打断点,debug
请求
开始debug
点进方法内部再看看
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { // 遍历所有的request,直到最后都没有的话返回null for (HandlerMapping mapping : this.handlerMappings) { HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; }
在这之后,请求就会找到对应的Handler进行处理。
2.2 Spring MVC视图解析机制
首先定义一个ViewResolver类型的List
/** List of ViewResolvers used by this servlet. */ @Nullable private List<ViewResolver> viewResolvers;
初始化ViewResolvers
private void initViewResolvers(ApplicationContext context) { this.viewResolvers = null; if (this.detectAllViewResolvers) { // 在ApplicationContext中找到所有的viewresolver,包括全部上下文 Map<String, ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false); if (!matchingBeans.isEmpty()) { this.viewResolvers = new ArrayList<>(matchingBeans.values()); // 保持viewresolver的排序。 AnnotationAwareOrderComparator.sort(this.viewResolvers); } } ...... }
然后进行视图解析
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception { boolean errorView = false; // 判断有无异常 if (exception != null) { // 如果异常不为空,则返回一个错误的页面 if (exception instanceof ModelAndViewDefiningException) { logger.debug("ModelAndViewDefiningException encountered", exception); mv = ((ModelAndViewDefiningException) exception).getModelAndView(); }else { Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); mv = processHandlerException(request, response, handler, exception); errorView = (mv != null); } } if (mv != null && !mv.wasCleared()) { // 视图渲染 render(mv, request, response); if (errorView) { WebUtils.clearErrorRequestAttributes(request); } } ...... }
视图渲染
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { // 确定请求的区域设置并将其应用于响应 Locale locale = (this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale()); response.setLocale(locale); View view; String viewName = mv.getViewName(); if (viewName != null) { // 获取视图名称 view = resolveViewName(viewName, mv.getModelInternal(), locale, request); if (view == null) { throw new ServletException("Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" + getServletName() + "'"); } } else { // No need to lookup: the ModelAndView object contains the actual View object. view = mv.getView(); if (view == null) { throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " + "View object in servlet with name '" + getServletName() + "'"); } } ...... try { if (mv.getStatus() != null) { response.setStatus(mv.getStatus().value()); } view.render(mv.getModelInternal(), request, response); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("Error rendering view [" + view + "]", ex); } throw ex; } }