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