SpringMVC一次请求过程源码分析

今天来探索SpringMVC一次请求过程的源码,首先需要找到程序运行的类及主要方法:

我们使用StringMVC首先需要在web.xml中设置一个前端控制器来处理请求,这个前端控制器是:org.springframework.web.servlet.DispatcherServlet

那么我们程序运行的入口就在这里。

从这里可以看出前端控制器是一个Servlet,我们寻找他的service方法,在DispatherServlet中并没有找到service方法,在其父类FrameworkServlet中找到service方法。如下:


FrameworkServlet

@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {


	String method = request.getMethod();
	if (method.equalsIgnoreCase(RequestMethod.PATCH.name())) {
		// 处理请求
		processRequest(request, response);
	}
	else {
		super.service(request, response);
	}
}

调用本类的processRequest方法
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {


	long startTime = System.currentTimeMillis();
	Throwable failureCause = null;


	LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
	LocaleContext localeContext = buildLocaleContext(request);


	RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
	ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);


	WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
	asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());


	initContextHolders(request, localeContext, requestAttributes);


	try {
		// 调用doService方法处理请求
		doService(request, response);
	}
	...	


调用本类的doService方法
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
	...
	try {
		// 调用doDispatch方法处理请求
		doDispatch(request, response);
	}
	...


调用 DispatherServlet的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;


			// Determine handler for the current request.
			// 通过processedRequest,决定使用哪个handler来处理请求
			mappedHandler = getHandler(processedRequest);
			if (mappedHandler == null || mappedHandler.getHandler() == null) {
				noHandlerFound(processedRequest, response);
				return;
			}


			// Determine handler adapter for the current request.
			// 决定使用那个适配器处理请求(适配器模式)
			HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());


			// Process last-modified header, if supported by the handler.
			String method = request.getMethod();
			boolean isGet = "GET".equals(method);
			if (isGet || "HEAD".equals(method)) {
				long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
				if (logger.isDebugEnabled()) {
					String requestUri = urlPathHelper.getRequestUri(request);
					logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
				}
				if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
					return;
				}
			}


			// 执行预处理方法
			if (!mappedHandler.applyPreHandle(processedRequest, response)) {
				return;
			}


			try {
				// Actually invoke the handler.
				// 使用适配器执行目标方法,返回ModleAndView
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
			}
			finally {
				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}
			}


			applyDefaultViewName(request, mv);
			mappedHandler.applyPostHandle(processedRequest, response, mv);
		}
		catch (Exception ex) {
			dispatchException = ex;
		}
		// 处理业务逻辑执行以后的返回结果,即处理视图
		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
			mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
			return;
		}
		// Clean up any resources used by a multipart request.
		if (multipartRequestParsed) {
			cleanupMultipart(processedRequest);
		}
	}
}


到这里我们可以看出这个前端控制器主要工作是在 DispatherServletdoDispatch方法中完成。

大致流程如下:


通过processedRequest,决定使用哪个handler来处理请求

HandlerExecutionChain mappedHandler = null;
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);

决定使用那个适配器处理请求(适配器模式)
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

执行预处理方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
	return;
}


使用适配器执行目标方法,返回ModleAndView
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());


执行目标后处理方法
mappedHandler.applyPostHandle(processedRequest, response, mv);


处理业务逻辑执行以后的返回结果,即处理视图,

调用本类的processDispatchResult方法

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);//渲染视图
		if (errorView) {
			WebUtils.clearErrorRequestAttributes(request);
		}
	}	
	..


调用本类的render(mv, request, response);渲染视图。是将方法的返回值,最终变为一个View对象。
这个View对象正是我们在xml中配置的InternalResourceView
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);
	response.setLocale(locale);


	// View对象
	View view;
	if (mv.isReference()) {
		// We need to resolve the view name.
		view = resolveViewName(mv.getViewName(), 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对象
		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() + "'");
		}
	}
	// Delegate to the View object for rendering.
	if (logger.isDebugEnabled()) {
		logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
	}
	try {
		// 内部视图解析器继续解析视图:
		view.render(mv.getModelInternal(), request, response);
	}
	catch (Exception ex) {
		if (logger.isDebugEnabled()) {
			logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '"
					+ getServletName() + "'", ex);
		}
		throw ex;
	}
}


调用 AbstractView类中的render方法
@Override
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);
	}


	Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);


	prepareResponse(request, response);
	// 渲染模型
	renderMergedOutputModel(mergedModel, request, response);
}	


调用 InternalResourceView类中的renderMergedOutputModel方法进行渲染模型、转发操作:
//拿到转发器,进行转发
@Override
protected void renderMergedOutputModel(
		Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {


	// Determine which request handle to expose to the RequestDispatcher.
	HttpServletRequest requestToExpose = getRequestToExpose(request);


	// Expose the model object as request attributes.
	exposeModelAsRequestAttributes(model, requestToExpose);


	// Expose helpers as request attributes, if any.
	exposeHelpers(requestToExpose);


	// Determine the path for the request dispatcher.
	String dispatcherPath = prepareForRendering(requestToExpose, response);
	
	//获得转发器
	// Obtain a RequestDispatcher for the target resource (typically a JSP).
	RequestDispatcher rd = getRequestDispatcher(requestToExpose, dispatcherPath);
	if (rd == null) {
		throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
				"]: Check that the corresponding file exists within your web application archive!");
	}


	// If already included or response already committed, perform include, else forward.
	if (useInclude(requestToExpose, response)) {
		response.setContentType(getContentType());
		if (logger.isDebugEnabled()) {
			logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
		}
		rd.include(requestToExpose, response);
	}


	else {
		// Note: The forwarded resource is supposed to determine the content type itself.
		if (logger.isDebugEnabled()) {
			logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
		}
		//进行转发
		rd.forward(requestToExpose, response);
	}
}


  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值