Spring MVC中的MVC即模型-视图-控制器,该框架围绕一个DispatcherServlet设计而成,DispatcherServlet会把请求分发给各个处理器,并支持可配置的处理器映射和视图渲染等功能。Spring MVC的具体工作流程如下:
(1)客户端发起HTTP请求:客户端将请求提交到DispatcherServlet
(2)寻找处理器:由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理该请求的Controller
(3)调用处理器:DispatcherServlet将请求提交到Controller
(4)调用业务处理逻辑并返回结果;Controller在调用业务处理逻辑后,返回ModelAndView
(5)处理视图映射并返回模型:DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图
(6)HTTP响应:视图负责将结果在客户端浏览器上渲染和展示。
核心代码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.
/*
mappedHandler:调用链
包含handler、interceptorList、interceptorIndex
handler:浏览器发送的请求所匹配的控制器方法
interceptorList:处理控制器方法的所有拦截器集合
interceptorIndex:拦截器索引,控制拦截器afterCompletion()的执行
*/
mappedHandler = getHandler(processedRequest);
if (mappedHandler == 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 (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// 调用拦截器的preHandle()
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// 由处理器适配器调用具体的控制器方法,最终获得ModelAndView对象
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
// 调用拦截器的postHandle()
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
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 {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
HandlerMapping在这个SpringMVC体系结构中有着举足轻重的地位,充当着url和Controller之间映射关系配置的角色。HandlerMapping是接口,Spring MVC提供了一系列HandlerMapping的实现,根据一定的规则选择controller。如果当前的HandlerMappign实现中没有能够满足你所需要的规则是,可以通过实现HandlerMapping接口进行扩展。它主要有三部分组成:HandlerMapping映射注册、根据url获取对应的处理器、拦截器注册。
总结:
HandlerMapping是处理器映射器,根据请求找到处理器Handler,但并不是简单的返回处理器,而是将处理器和拦截器封装,形成一个处理器执行链(HandlerExecuteChain)。
核心伪代码如下:
getHandler伪代码
1 // 获取处理器执行链对象
2 protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
3 // SpringMVC默认实现三种类型的HandlerMapping:
4 // RequestMappingHandlerMapping、BeanNameUrlHandlerMapping、SimpleUrlHandlerMapping
5 if (this.handlerMappings != null) {
6 // 遍历MVC容器中的处理器映射器
7 for (HandlerMapping mapping : this.handlerMappings) {
8 // 获取请求对应的处理器执行链
9 HandlerExecutionChain handler = mapping.getHandler(request);
10 // 处理器执行链不为空
11 if (handler != null) {
12 // 返回匹配到的处理器执行链
13 return handler;
14 }
15 }
16 }
17 // 返回null
18 return null;
19 }
getHandler获取执行器链
1 // 为请求获取handler处理器,若没有Handler处理器,获取mvc默认的handler处理器
2 public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
3 // 获得处理器(HandlerMethod或者HandlerExecutionChain),该方法是抽象方法,由子类实现
4 Object handler = getHandlerInternal(request);
5 // 获得不到,则使用默认处理器
6 if (handler == null) {
7 handler = getDefaultHandler();
8 }
9 // 获得不到,则返回 null
10 if (handler == null) {
11 return null;
12 }
13
14 // 如果找到的处理器是String类型,则从Spring容器中找到对应的Bean作为处理器
15 if (handler instanceof String) {
16 String handlerName = (String) handler;
17 handler = obtainApplicationContext().getBean(handlerName);
18 }
19
20 // 创建HandlerExecutionChain对象(包含处理器和拦截器)
21 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
22
23 // 跨域请求的处理
24 if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
25 CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
26 CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
27 config = (config != null ? config.combine(handlerConfig) : handlerConfig);
28 executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
29 }
30
31 return executionChain;
32 }
getHandlerExectuionChain 构建执行器链
1 // 为handler处理器构建HandlerExecutionChain对象,包含应用拦截器
2 protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
3 // 创建 HandlerExecutionChain 对象
4 HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
5 (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
6
7 // 获得请求路径
8 String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);
9 // 遍历 adaptedInterceptors 数组,获得请求匹配的拦截器
10 for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
11 // 需要匹配,若路径匹配,则添加到 chain 中
12 if (interceptor instanceof MappedInterceptor) {
13 MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
14 if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
15 chain.addInterceptor(mappedInterceptor.getInterceptor());
16 }
17 }
18 // 无需匹配,直接添加到 chain 中
19 else {
20 chain.addInterceptor(interceptor);
21 }
22 }
23 return chain;
24 }
相关问题:
1.为什么不直接调用对应handler处理请求,而是先找到适配器
提到适配器,就知道它应用了适配器模式。
为什么要用适配器模式呢?
因为控制器接受请求的方式不同,即实现Controller的方式不同。有三种实现方式,一种是实现Controller接口方式,一种是用@Controller注解的方式,还有一种是直接接受的Http请求。
不同的Controller的实现方式,如果用if…else判断去处理的话,就会违背开放封闭原则 。
if(controller typeof @Controller){
处理@Controller注解逻辑
}
if(controller typeof ControllerInterface){
处理实现controller接口的逻辑
}
if(controller typeof http){
处理实现http请求类型的逻辑
}
因为多加一种controller实现方式就得多一个判断。因此SpringMVC就引入了适配器模式
参考:http://www.manongjc.com/detail/41-uiajoseglafvxgf.html
https://blog.csdn.net/shang_0122/article/details/119335479