SpringMVC之处理请求

接下来将会分析SpringMVC是怎么处理请求的,首先会分析HttpServletBean、FrameServlet和DispatcherServlet,然后再看一下核心方法doDispatch
HttpServletBean主要参与创建工作,没有涉及请求的处理
FrameworkServlet:
servlet的处理流程是:首先从Servlet接口的service方法开始,然后在HttpServlet的service方法中根据请求的类型路由到doGet、doPost等方法上:

protected void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//获取请求的方法
		String method = request.getMethod();
		//根据是否是PATCH类型
		if (method.equalsIgnoreCase(RequestMethod.PATCH.name())) {
			processRequest(request, response);
		}
		else {
			super.service(request, response);
		}
	}

我们发现在service方法中对于除了PATCH类型,都交给了父类去处理,processRequest方法是处理请求的核心方法:

protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		long startTime = System.currentTimeMillis();
		Throwable failureCause = null;
		//获取LocaleContextHolder中原来保存的LocaleContext
		LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
		//获取当前请求的LocaleContext
		LocaleContext localeContext = buildLocaleContext(request);
		//获取原来保存的requestAttributes 
		RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
		//获取当前请求的requestAttributes 
		ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
		
		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
		asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
		//设置当前请求的requestAttributes和localeContext
		initContextHolders(request, localeContext, requestAttributes);

		try {
			//请求处理的入口
			doService(request, response);
		}
		...
		finally {
			//恢复原来的设置
			resetContextHolders(request, previousLocaleContext, previousAttributes);
			if (requestAttributes != null) {
				requestAttributes.requestCompleted();
			}
			...
			//发布一个请求处理的消息
			publishRequestHandledEvent(request, response, startTime, failureCause);
		}
	}

在这个方法中最终处理还是交给了doService,这个方法留给了DispatcherServlet来实现,在这之前和之后还做了LocaleContext和RequestAttributes的设置及恢复,处理完后发布ServletRequestHandledEvent消息以及使用request获取到了异步管理器并且注册了拦截器。
DispatcherServlet
在处理请求的过程中doService是这个Servlet 的入口方法:

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
		Map<String, Object> attributesSnapshot = null;
		//判断是否是include请求
		if (WebUtils.isIncludeRequest(request)) {
			//对request里面的属性进行快照备份
			attributesSnapshot = new HashMap<String, Object>();
			Enumeration<?> attrNames = request.getAttributeNames();
			while (attrNames.hasMoreElements()) {
				String attrName = (String) attrNames.nextElement();
				if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {
					attributesSnapshot.put(attrName, request.getAttribute(attrName));
				}
			}
		}

		// 设置一些属性
		request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
		request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
		request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
		request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
		//用于redirect是的参数传递
		FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
		if (inputFlashMap != null) {
			request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
		}
		request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
		request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);

		try {
			//处理请求的核心方法
			doDispatch(request, response);
		}
		finally {
			if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
				// 如果是保存的快照属性不为空,需要个request恢复快照属性
				if (attributesSnapshot != null) {
					restoreAttributesAfterInclude(request, attributesSnapshot);
				}
			}
		}
	}

在这个方法中首先判断当前request是否是include类型的,如果是需要对他里面的属性进行快照备份,然后个request设置上一些必要的属性,然后调用doDispatch处理请求,最后如果是include类型的request,需要给它恢复属性
doDispatch方法最核心的代码只有四句:

mappedHandler = getHandler(processedRequest);
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException)

1、根据request找到对应的handler
2、根据handler找到对应的handlerAdapter
3、用handlerAdapter处理handler
4、调用processDispatchResult处理上面处理之后的结果
Handler:处理器,直接对应着MVC中的controller层,标注了RequestMapping的所有方法都可以看成一个Handler。只要可以实际处理请求就可以使Handler
HandlerMapping:用来查找Handler
HandlerAdapter:让固定的Servlet处理方法调用灵活的Handler来进行处理
View:展示数据
ViewResolver:查找View
来看一下doDispatch的代码:

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);

				// 根据request找到对应的Handler
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// 根据Handler找到对应的HandlerAdapter
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				//处理get、head请求的Last-Modified
				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;
					}
				}
				//执行拦截器的preHandle
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// HandlerAdapter使用handler处理请求
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
				//如果需要异步处理直接返回
				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}
				//如果view为空,根据request设置默认的view
				applyDefaultViewName(request, mv);
				//执行拦截器的postHandle方法
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			//处理上面的处理结果。包括异常处理,渲染页面,发出完成通知触发拦截器的afterCompletion
			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 {
				// 删除上传请求的资源
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}

doDispatch首先会检查是不是上传请求,如果是上传请求,则将request转换为MultipartHttpServletRequest,并将multipartRequestParsed标志设置为true,然后通过getHandler方法获取Handler处理器链:

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		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;
	}

在返回的处理器链中,包含着一些拦截器和handler就像Pipline中的处理过程一样
在请求处理完成之后,就要使用processDispatchResult方法处理之前返回的结果:

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
			HandlerExecutionChain mappedHandler, ModelAndView mv, 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);
			}
		}
		else {
			if (logger.isDebugEnabled()) {
				logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
						"': assuming HandlerAdapter completed request handling");
			}
		}
		//如果启动了异步处理则返回
		if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
			return;
		}
		//请求处理完成之后触发拦截器AfterCompletion
		if (mappedHandler != null) {
			mappedHandler.triggerAfterCompletion(request, response, null);
		}
	}

在处理错误的时候会将错误信息设置到view中,然后通过render方法渲染页面,最后触发拦截器的拦截的事件。

猜你喜欢

转载自blog.csdn.net/m0_37343985/article/details/84345864