springmvc请求流程

一些内容直接以注释的方式写在源码里了。

一般流程:

(一)
     用户请求首先发送到前端控制器DispatcherServlet,DispatcherServlet根据请求的信息来决定使用哪个页面控制器Controller(也就是我们通常编写的Controller,实际上就是那个handler控制器)来处理该请求。找到控制器之后,DispatcherServlet将请求委托给控制器去处理。
(二)

    接下来页面控制器开始处理用户请求,页面控制器会根据请求信息进行处理,调用业务层等等,处理完成之后,会把结果封装成一个ModelAndView返回给DispatcherServlet。
(三)
     前端控制器DispatcherServlet接到页面控制器的返回结果后,根据返回的视图名选择相应的视图模板,并根据返回的数据进行渲染。
(四)
     最后前端控制器DispatcherServlet将结果返回给用户。


详细的请求流程描述:

1、用户请求发送到前端控制器DispatcherServlet。

2、 DispatcherServlet 接收到请求后,DispatcherServlet 会使用 HandlerMapping 来处理,HandlerMapping 会查找到具体进行处理请求的 Handler 对象。

3、HandlerMapping 找到对应的 Handler 之后,并不是返回一个 Handler 原始对象,而是一个 Handler 执行链,在这个执行链中包括了拦截器和处理请求的 Handler。HandlerMapping 返回一个执行链给 DispatcherServlet。

4、DispatcherServlet 接收到执行链之后,会调用 Handler 适配器去执行Handler。

5、Handler 适配器执行完成 Handler(也就是我们写的 Controller)之后会得到一个 ModelAndView,并返回给 DispatcherServlet。

6、DispatcherServlet 接收到 Handler 适配器返回的 ModelAndView 之后,会根据其中的视图名调用视图解析器。

7、视图解析器根据逻辑视图名解析成一个真正的 View 视图,并返回给 DispatcherServlet。

8、DispatcherServlet 接收到视图之后,会根据上面的 ModelAndView 中的 model 来进行视图中数据的填充,也就是所谓的视图渲染。

9、渲染完成之后,DispatcherServlet 就可以将结果返回给用户了。

源码分析:

    DispatcherServlet是一个Servlet,我知道在Servlet在处理一个请求的时候会交给service方法进行处理,DispatcherServlet继承了FrameworkServlet,首先进入FrameworkServlet的service方法:

protected void service(HttpServletRequest request, HttpServletResponse response) 
		throws ServletException, IOException {
    //请求方法
    HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
	
    //processRequest使用处理PATCH请求方法,而其他请求类型的方法则使用父类,即HttpServlet处理
    if(HttpMethod.PATCH != httpMethod && httpMethod != null) {
        super.service(request, response);
    } else {
        this.processRequest(request, response);
    }
}
    HttpServlet中会根据请求类型的不同分别调用doGet或者doPost等方法,FrameworkServlet中已经重写了这些方法,在这些方法中会调用processRequest进行处理,在processRequest中会调用doService方法(图1),这个doService方法就是在DispatcherServlet中实现的。

图(1)
   
 
  接下来研究一下DispatcherServlet中的doService方法的实现:

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
	if (logger.isDebugEnabled()) {
		String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
		logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
				" processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
	}

	// Keep a snapshot of the request attributes in case of an include,
	//给request中的属性做一份快照
	// to be able to restore the original attributes after the include.
	Map<String, Object> attributesSnapshot = null;
	if (WebUtils.isIncludeRequest(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));
			}
		}
	}

	// Make framework objects available to handlers and view objects.
	//如果没有配置类似本地化或者主题处理器之类的
	//springMVC会使用默认值
	//默认配置文件是DispatcherServlet.properties
	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());

	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()) {
			// Restore the original attribute snapshot, in case of an include.
			if (attributesSnapshot != null) {
				restoreAttributesAfterInclude(request, attributesSnapshot);
			}
		}
	}
}

可以看出来,Dispatcher真正开始是调用了doDispatch方法,再继续找doDispatch方法:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
	HttpServletRequest processedRequest = request;
	HandlerExecutionChain mappedHandler = null;
	boolean multipartRequestParsed = false;

	//springMVC中异步请求,另开文章学习
	WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

	try {
		ModelAndView mv = null;
		Exception dispatchException = null;

		try {
			//先检查请求是不是Multipart类型的,例如上传
			//如果确定是Multipart类型的,则转换为MultipartHttpServletRequest(见图2)
			processedRequest = checkMultipart(request);
			multipartRequestParsed = (processedRequest != request);

			// Determine handler for the current request.
			//获取当前请求的Handler
			mappedHandler = getHandler(processedRequest);
			if (mappedHandler == null || mappedHandler.getHandler() == null) {
				noHandlerFound(processedRequest, response);
				return;
			}

			// Determine handler adapter for the current request.
			//获取当前请求的Handler适配器
			HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

			// Process last-modified header, if supported by the handler.
			//对于hander请求头中的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;
				}
			}

			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;
		}
		catch (Throwable err) {
			// As of 4.3, we're processing Errors thrown from handler methods as well,
			// making them available for @ExceptionHandler methods and other scenarios.
			dispatchException = new NestedServletException("Handler dispatch failed", err);
		}
		processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
	}
	catch (Exception ex) {
		triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
	}
	catch (Throwable err) {
		triggerAfterCompletion(processedRequest, response, mappedHandler,
				new NestedServletException("Handler processing failed", 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);
			}
		}
	}
}
可以看出来在该方法中,会检查请求的类型是不是Multipart类型的,如果是的话呢,就转换成MultipartHttpServletRequest

图(2)



我们去找一下这个:

//获取当前请求的Handler
mappedHandler = getHandler(processedRequest);
/**
 * Return the HandlerExecutionChain for this request.
 * <p>Tries all handler mappings in order.
 * @param request current HTTP request
 * @return the HandlerExecutionChain, or {@code null} if no handler could be found
 */
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;
}
从上面代码中可以看出还需要找到这个:
getHandler(request);

在AbstractHandlerMapping类寻找getHandler中:

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
	//根据request获取handler
	Object handler = getHandlerInternal(request);
	if (handler == null) {
		//如果没有找到就是用默认的handler
		handler = getDefaultHandler();
	}
	if (handler == null) {
		return null;
	}
	// Bean name or resolved handler?
	//如果Handler是String,表明是一个bean的名称
	//需要创建对应bean
	if (handler instanceof String) {
		String handlerName = (String) handler;
		handler = getApplicationContext().getBean(handlerName);
	}

	//封装Handler执行链
	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;
}

根据requrst获取handler的方法getHandlerInternal:

AbstractHandlerMethodMapping中:

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
	//获取request中的url,用来匹配handler
	String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
	if (logger.isDebugEnabled()) {
		logger.debug("Looking up handler method for path " + lookupPath);
	}
	this.mappingRegistry.acquireReadLock();
	try {
		//根据路径寻找Handler
		HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
		if (logger.isDebugEnabled()) {
			if (handlerMethod != null) {
				logger.debug("Returning handler method [" + handlerMethod + "]");
			}
			else {
				logger.debug("Did not find handler method for [" + lookupPath + "]");
			}
		}
		//根据HandlerMethod中的bean来实例化Handler并添加HandlerMethod
		return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
	}
	finally {
		this.mappingRegistry.releaseReadLock();
	}
}

根据路径寻找handler的方法lookupHandlerMethod:

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
	List<Match> matches = new ArrayList<Match>();
	//直接匹配
	List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
	//如果匹配成功,那就添加到列表中去
	if (directPathMatches != null) {
		addMatchingMappings(directPathMatches, matches, request);
	}
	//还没匹配上,就遍历所有的处理方法查询
	if (matches.isEmpty()) {
		// No choice but to go through all mappings...
		addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
	}

	//找到了匹配的
	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 + "}");
			}
		}
		//设置request参数
		handleMatch(bestMatch.mapping, lookupPath, request);
		//返回匹配的url的处理方法
		return bestMatch.handlerMethod;
	}
	else {
		//啥也没找到,返回null
		return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
	}
}

获取默认Handler

如果上面没有获取到Handler,就会获取默认的Handler。如果还获取不到就返回null。

处理String类型的Handler

如果上面处理完的Handler是String类型的,就会根据这个handlerName获取bean。

封装Handler执行链

上面获取完Handler,就开始封装执行链了,就是将我们配置的拦截器加入到执行链中去,getHandlerExecutionChain:

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
	//如果当前Handler不是执行类型,就使用一个新的执行链实例封装起来
	HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
			(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

	//当前的url
	String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
	//遍历拦截器,找到跟当前url对应的,添加到执行链中去
	for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
		if (interceptor instanceof MappedInterceptor) {
			MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
			if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
				chain.addInterceptor(mappedInterceptor.getInterceptor());
			}
		}
		else {
			chain.addInterceptor(interceptor);
		}
	}
	return chain;
}

获取对应请求的Handler适配器

getHandlerAdapter:

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
	//遍历所有的HandlerAdapter,执行和当前Handler匹配的就返回
	//我们这里会匹配到RequestMappingHandlerAdapter
	for (HandlerAdapter ha : this.handlerAdapters) {
		if (logger.isTraceEnabled()) {
			logger.trace("Testing handler adapter [" + ha + "]");
		}
		if (ha.supports(handler)) {
			return ha;
		}
	}
	throw new ServletException("No adapter for handler [" + handler +
			"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

缓存的处理

也就是对last-modified的处理

执行拦截器的preHandle方法

就是遍历所有的我们定义的interceptor,执行preHandle方法

使用Handler适配器执行当前的Handler

ha.handle执行当前Handler,我们这里使用的是RequestMappingHandlerAdapter,首先会进入AbstractHandlerMethodAdapter的handle方法:

public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
		throws Exception {
	return handleInternal(request, response, (HandlerMethod) handler);
}
handleInternal方法,在RequestMappingHandlerAdapter中:

protected ModelAndView handleInternal(HttpServletRequest request,
		HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

	ModelAndView mav;
	checkRequest(request);

	// Execute invokeHandlerMethod in synchronized block if required.
	if (this.synchronizeOnSession) {
		HttpSession session = request.getSession(false);
		if (session != null) {
			Object mutex = WebUtils.getSessionMutex(session);
			synchronized (mutex) {
			执行方法,封装ModelAnadView
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
			// No HttpSession available -> no mutex necessary
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}
	}
	else {
		// No synchronization on session demanded at all...
		mav = invokeHandlerMethod(request, response, handlerMethod);
	}

	if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
		if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
			applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
		}
		else {
			prepareResponse(response);
		}
	}

	return mav;
}

组装默认视图名称

前缀和后缀名都加上,执行拦截器的postHandle方法,遍历intercepter的postHandle方法。

处理最后的结果,渲染之类的

processDispatchResult方法:

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

	// Did the handler return a view to render?
	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()) {
		// Concurrent handling started during a forward
		return;
	}

	if (mappedHandler != null) {
		mappedHandler.triggerAfterCompletion(request, response, null);
	}
}







  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值