前言
Spring MVC框架使用了其”模型-视图-控制器”( Model-View-Controller )架构方式,用于开发灵活且松散耦合的 Web 应用程序。我们都使用过SpringMVC来处理信息,并渲染视图到Browser。但需要注意的是,在现在的架构中,大都采用了前后端分离的情况,而我们在使用SpringMVC的时候,只需要关注M(Model),C(Controller)这两个部分,而视图渲染的部分则交给了前端。
流程图
源码解析
(1):用户向服务发送HTTP请求,DispatcherServlet捕获请求。
(2):DispatcherServlet根据URL,调用 HandlerMapping 获得该 Handler 对象以及所对应的拦截器,其返回的是HandlerExecutionChain对象,这个对象中就包含了Handler对象以及这个Handler所对应的拦截器。
(3):DispatcherServlet根据获得的 Handler,选择一个合适的HandlerAdapter 。(附注:如果成功获得 HandlerAdapter 后,此时将开始执行拦截器的 preHandler 方法),然后获取Request请求数据,填充Handler,执行Handler。
(4):上一步获取到HandlerAdapter后,会执行Handler,并返回ModelAndView
(5):根据返回的 ModelAndView ,选择一个适合的 ViewResolver(必须是已经注册到 Spring 容器中的 ViewResolver),解析出View对象,然后返回给 DispatcherServlet。
(6):ViewResolver通过render()方法结合 Model 和 View,来渲染视图。
(7):ViewResolver通过render()方法写回给Browser。
流程详解
看完以上没有看过源码的童靴可能会一脸懵逼,此上也是围绕流程图进行了部分截取,方便大家理解,下面我们来搭建一个测试Demo来进一步了解。
(1):测试Controller(模拟用户真实情况)
(2):在解析DispatcherServlet之前,我们先来看一下DispatcherServlet的父类FrameworkServlet。
(3):通过上图我们不难看到一些敏感内容,如doGet(...)、doPost(…)、doPut(…)、doDelete(…)等等,我们通过这些方法可以看到,这些方法都指向了同一个方法,processRequest(…)
(4):我们来看一下FrameworkServlet的service(…)方法。
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String method = request.getMethod();//获取请求方法
if (method.equalsIgnoreCase(RequestMethod.PATCH.name())) {//判断请求方法
this.processRequest(request, response);
} else {
super.service(request, response);//调用父类的service(…)方法
}
}
(5):我们来看一下父类HttpServlet所包含的方法。
(6):通过service(…)我们可以看出,此方法是根据方法类型,分发请求的。
(7):我们继续跟进方法,就不难发现这些请求处理的方法就回到了(3)中所示。
(8):我们重点关注一下,processRequest(…)方法,(代码已作删减)
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//线程绑定
/**
*封装Locale对象、属性到LocaleContextHolder
*封装Locale对象、属性到RequestContextHolder
*/
…
this.doService(request, response);//请求处理
} catch (ServletException var17) {
failureCause = var17;
throw var17;
} catch (IOException var18) {
failureCause = var18;
throw var18;
} catch (Throwable var19) {
failureCause = var19;
throw new NestedServletException("Request processing failed", var19);
} finally {
//解除绑定
//……
this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause);
}
}
(9):通过上述代码,请求处理doService(…)方法。我们可以看到父类中是一个抽象方法,Spring中很多地方运用了这种方法,由父类抽象流程,交由子类在实现具体的方法,看到这里也就明白了,这个地方就是DispatcherServlet的入口方法,
(10):DispatcherServlet中doService(…)方法
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
//DEBUG日志输出
//封装属性
//…
try {
this.doDispatch(request, response);//请求处理分发
} finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {
this.restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
(11):请求处理,DispatcherServlet核心方法。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
//核心对象,包含处理器,以及拦截器数组等等。
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
//校验是否是文件上传请求
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
//获取处理器、拦截器数组对象。
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
//获取不到,异常处理。
this.noHandlerFound(processedRequest, response);
return;
}
//获取当前处理器所对应的HandlerAdapter对象。
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());//获取
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (this.logger.isDebugEnabled()) {
this.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;
}
//调用处理器目标方法,并返回视图对象。
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
//如果有视图,则从响应中获取视图,如果没有,则使用默认视图
this.applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var19) {
dispatchException = var19;
}
//处理结果(包括异常),渲染视图等等,
this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
} catch (Exception var20) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var20);
} catch (Error var21) {
this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var21);
}
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}