springMVC系列源码之请求处理过程――12(一)

2014-11-24 02:25:31 · 作者: · 浏览: 0

springMVC系列源码之请求处理过程――12


摘要:上次主要分析springMVC启动时是如何加载配置文件以及做好初始化工作的、这里主要是分析请求处理过程、包括浏览器发送一个请求到服务器、服务器内部如何处理、又如何将处理结果返回、服务器做出响应的一个过程。

1、简介


当springMVC的初始化完成之后、就进入到Servlet的第二个阶段“Service“时期、当浏览器发送一个request的到服务器的时候、Servlet容器启动一个线程、通过service()方法将请求转到doGet或者doPost来处理。

此时springMVC已经建立了一个子上下文、此上下文中存放着通过依赖注入的各种编程元素。Struts2采取的是一种完全和Web容器隔离和解耦的事件机制。诸如Action对象、Result对象、Interceptor对象,这些都是完全脱离Servlet容器的编程元素。Struts2将数据流和事件处理完全剥离开来,从Http请求中读取数据后,下面的事件处理流程就只依赖于这些数据,而完全不知道有Web环境的存在。

反观SpringMVC,无论HandlerMapping对象、HandlerAdapter对象还是View对象,这些核心的接口所定义的方法中,HttpServletRequest和HttpServletResponse对象都是直接作为方法的参数出现的。这也就意味着,框架的设计者,直接将SpringMVC框架和容器绑定到了一起。或者说,整个SpringMVC框架,都是依托着Servlet容器元素来设计的。

DispatcherServlet作为一个标准的Servlet、那么当一个请求过来时、我们就可以按照Servlet的执行过程去分析、他是如何处理request的。对于springMVC的模版化设计模式、我们时常要去父类中寻找我们需要的方法。下面就从DispatcherServlet入手、来分析一个request的请求过程。


2、具体过程

2.1 浏览器发送一个请求(这里以一次GET方式的请求为例、POST一样!)。

2.2 请求到达服务器、进入DispatcherServlet中的doGet或者doPost中处理。


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

		processRequest(request, response);
	}

	/**
	 * Delegate POST requests to {@link #processRequest}.
	 * @see #doService
	 */
	@Override
	protected final void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		processRequest(request, response);
	}


上面代码中都没有对request进行具体的处理、都是转由processRequest(request, response)处理。代码:


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

		Throwable failureCause = null;

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

		RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
		ServletRequestAttributes requestAttributes = null;
		if (previousAttributes == null || (previousAttributes instanceof ServletRequestAttributes)) {
			requestAttributes = new ServletRequestAttributes(request);
		}

		initContextHolders(request, localeContext, requestAttributes);

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

			doService(request, response);

			resetContextHolders(request, previousLocaleContext, previousAttributes);
			if (requestAttributes != null) {
				requestAttributes.requestCompleted();
			}
			if (this.publishEvents) {
				// Whether or not we succeeded, publish an event.
				long processingTime = System.currentTimeMillis() - startTime;
				this.webApplicationContext.publishEvent(
						new ServletRequestHandledEvent(this,
								request.getRequestURI(), request.getRemoteAddr(),
								request.getMethod(), getServletConfig().getServletName(),
								WebUtils.getSessionId(request), getUsernameForRequest(request),
								processingTime, failureCause));
			}
		}
	}


很长但是都不是重点:processRequest()方法只是做了一些线程安全的隔离,真正的请求处理,发生在doService()方法中。doService()是将服务器启动时初始化的各种属性设置到r