点击回顾SpringMVC请求响应流程
前置控制器类
前置控制器DispatcherServlet,间接继承自HttpServlet,本质上还是Servlet
当请求的url符合前置控制器DispatcherServlet的映射路径时,Servlet容器(Tomcat)会调用其service方法,其实现在父类FrameworkServlet中
- 查看FrameworkServlet的service方法(看看它怎么处理请求)
@Override
protected void service(...) throws ... {
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
//增加对 PATCH 请求的处理
if (HttpMethod.PATCH == httpMethod || httpMethod == null) {
processRequest(request, response);
}
else {
super.service(request, response);
}
}
//重写doGet()方法
@Override
protected final void doGet(...) throws ... {
processRequest(request, response);
}
//重写doPost()方法
@Override
protected final void doPost(...) throws ... {
processRequest(request, response);
}
FrameworkServlet的service方法处理了Patch、Get、Post三种类型请求(通过调用processRequest方法)
- 查看FrameworkServlet的processRequest方法(进一步看看请求如何被处理)
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
//获取之前的Locale上下文,同时从request中获取Locale上下文
//Locale上下文接口用于获取对象Locale(用于构造Java国际化情景),只有一个方法——getLocale()
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
LocaleContext localeContext = buildLocaleContext(request);
//获取之前的Request属性数据,同时从request中获取新的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() FramworkServlet没有实现,只是简单定义,交由 DispatchServlet实现
doService(request, response);
}
//异常处理,采用捕获,记录然后再抛出给高层的处理策略
catch (ServletException ex) {
failureCause = ex;
throw ex;
}
catch (IOException ex) {
failureCause = ex;
throw ex;
}
catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}
finally {
//如果失败,恢复上一次请求的上下文
...
省略
...
}
}
可以看到FrameworkServlet的processRequest方法的职责是切换上下文(通过request设置上下文,遭遇异常会恢复原上下文),然后调用子类(DispatcherServlet)的doService方法
-
查看DispatcherServlet的doService方法(看看请求到底怎么被处理)
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { ... //为request设置上下文及其他属性,方便其他方法需要时从request获取 //... request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext()); //省略 //... try { //将请求进行分派处理 doDispatch(request, response); } finally { //... //省略 //... } }
DispatcherServlet的doService方法给request装填更多数据(),然后调用doDispatch方法最终将请求进行分派处理
-
查看DispatcherServlet的doDispatch方法(看请求如何被分派并处理)
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; //定义Handler执行链 HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { //定义ModelAndView ModelAndView mv = null; Exception dispatchException = null; try { //检查请求是否为文件上传请求,如果是使文件上传解析器可用 processedRequest = checkMultipart(request); //如果是文件上传请求multipartRequestParsed值为true multipartRequestParsed = (processedRequest != request); //获取请求对应的handler执行链 //getHandler方法在Handler映射器环节讲解 mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; } // 为Handler执行链中的Handler构建适配器 // mappedHandler.getHandler()获取的是Handler执行链的Handler——在Handler执行链环节讲解 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // request的类型 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; } // 适配器执行Handler执行链,返回ModelAndView //适配器的handle方法在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) { 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 { //... //省略 //... } }
可以看出doDispatch方法将请求分派给Handler执行链(调用Handler映射器得到Handler执行链、获取并调用Handler适配器执行Handler执行链),之后调用processDispatchResult对结果ModelAndView进行解析并装填响应结果
-
查看processDispatchResult方法(看看结果ModelAndView如何被装填进响应中)
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception { boolean errorView = false; //若之前的流程存在异常,使用异常ModelAndView填装参数(此处重构手段是:使用特例对象取代null值) 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()) { // 通过ModelAndView渲染视图并填装至response render(mv, request, response); if (errorView) { WebUtils.clearErrorRequestAttributes(request); } } else { if (logger.isTraceEnabled()) { logger.trace("No view rendering, null ModelAndView returned."); } } if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Concurrent handling started during a forward return; } if (mappedHandler != null) { mappedHandler.triggerAfterCompletion(request, response, null); } } protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { // 获取请求的Locale对象并装入响应 Locale locale = (this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale()); response.setLocale(locale); View view; String viewName = mv.getViewName(); if (viewName != null) { // ModelAndView指定了视图名称 // 解析指定名称的视图 view = resolveViewName(viewName, mv.getModelInternal(), locale, request); if (view == null) { throw new ServletException(略); } } else { // ModelAndView未指定视图名称 // 从ModelAndView中取出View,此View由Handler(Controller)写入 view = mv.getView(); if (view == null) { throw new ServletException(略); } } // Delegate to the View object for rendering. if (logger.isTraceEnabled()) { logger.trace("Rendering view [" + view + "] "); } try { if (mv.getStatus() != null) { response.setStatus(mv.getStatus().value()); } //将View装入响应中 view.render(mv.getModelInternal(), request, response); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("Error rendering view [" + view + "]", ex); } throw ex; } } protected View resolveViewName(String viewName, @Nullable Map
model, Locale locale, HttpServletRequest request) throws Exception { if (this.viewResolvers != null) { //调用视图解析器生成指定名称的View for (ViewResolver viewResolver : this.viewResolvers) { //视图解析器的resolveViewName方法在视图解析器环节讲解 View view = viewResolver.resolveViewName(viewName, locale); if (view != null) { return view; } } } return null; } processDispatchResult方法通过调用render方法渲染视图(View)并装填响应结果(异常情况也被封装成ModelAndView进行渲染),render方法则会根据ModelAndView的数据决定是使用指定视图名加载并填充视图(resolveViewName方法)还是直接从ModelAndView取出视图,然后用视图填装结果