springMVC流程解析
一、springMVC流程分析
1、一次请求的url流程
- (1)客户端发起的请求request通过核心处理器DispatcherServlet进行处理
- (2-3)核心处理器DispatcherServlet通过注册在spring中的HandlerMapping找到对应的Handler(其实是HandlerMethod,可以认为是我们编写的某个Controller对象的具体的某个方法 即通过映射器将请求映射到Controller的方法上),同时将注册在spring中的所有拦截器和Handler包装成执行链HandlerExecutionChain并返回给核心处理器DispatcherServlet
- (4)核心处理器DispatcherServlet 通过2-3部获取的Handler来查找对应的处理器适配器HandlerAdapter
- (5-7) 适配器调用实现对应接口的处理器,并将结果返回给适配器,结果中包含数据模型和视图对象,再由适配器返回给核心控制器
- (8-9)核心控制器将获取的数据和视图结合的对象传递给视图解析器,获取解析得到的结果,并由视图解析器响应给核心控制器
- (10)核心控制器将结果Response返回给客户端
二、springMVC源码解析
DisplaceServlet的初始化操纵请参考:https://blog.csdn.net/panyongcsd/article/details/52416279L
以下是针对DisplaceServlet初始化后进行的操作
1、springMVC的入口文件DispatcherServlet类 该类在web.xml中进行了配置
2、doService()方法 每一次的http请求都会进行该方法中
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
//如果是debug状态 则打印调试相关日志
if (logger.isDebugEnabled()) {
String requestUri = urlPathHelper.getRequestUri(request);
String resumed = WebAsyncUtils.getAsyncManager(request)
.hasConcurrentResult() ? " resumed" : "";
logger.debug("DispatcherServlet with name '"
+ getServletName() + "'" + resumed +
" processing " + request.getMethod() +
" request for [" + requestUri + "]");
}
// Keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include.
Map<String, Object> attributesSnapshot = null;
//获取该DispatcherServlet中是否含有包含(include)的servlet
//类似于<jsp:incluede page="xxx.jsp"/> 即在该jsp(servlet)中含有 xxx.jsp servlet
if (WebUtils.isIncludeRequest(request)) {
logger.debug("Taking snapshot of request attributes before include");
//将请求中的所有参数放置到快照属性Map
attributesSnapshot = new HashMap<String, Object>();
Enumeration<?> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude ||
attrName.startsWith("org.springframework.web.servlet")) {
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}
// Make framework objects available to handlers and view objects.
//设置上下文环境
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE,
getWebApplicationContext());
//设置本地解析
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
//设置主题解析
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
//设置主题资源信息
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());、
//从session中获取flashmap 属性 不为null的时候 将其添加到request
//flashMap其实是为了重定向的时候隐式的出传递参数使用的
//每次处理请求时,都会先判断一下FlashMap中是否有数据
// 如果有就先设置到 inputFlashMap里面,也就是保存上次转发过来的属性 再设置到Model里面
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(
request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE,
Collections.unmodifiableMap(inputFlashMap));
}
//如果重定向没有传递过来参数,则保存相关的空的对象
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
try {
//执行分发请求的操作
doDispatch(request, response);
}
//最后的请求结束的finally块不知道执行什么操作,应该类似于资源的销毁等相关处理
finally {
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
return;
}
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
3、doDispatch()方法
该方法是springMVC核心流程操作的所涉及的最为关键的方法,主要执行流程也全部在该方法中进行体现。
/**
真正处理转发请求的过程
通过该servlet的注册的所有处理器映射器HandlerMapping中的进行url请求映射到具体的处理器Handler上
即通过HandlerMapping将具体的httpurl请求映射到Controller层对应 的方法上
通过该servlet上注册的处理器适配器HandlerAdapter去查找第一个可以支持处理处理器Handler的HandlerAdapter
通过查询所有的HTTP请求均被该方法处理,它是由HandlerApadaters和处理器解析类来决定该controller层的方法是合理的
*/
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
//处理器执行链HandlerExecutionChain 里面包含handlerMethod和springMVC中所有的拦截器
//参考4HandlerExecutionChain类的介绍
HandlerExecutionChain mappedHandler = null;
//文件上传的处理请求标识
boolean multipartRequestParsed = false;
//将请求包装成异步请求来进行管理,为防止线程阻塞将请求的处理委托给另外一个线程
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
//检查当前request请求是否为文件上传请求,如果是将请求包装为文件上传请求返回,否则返回原请求
//返回的请求和原来请求不一致,则multipartRequestParsed 标识为true
processedRequest = checkMultipart(request);
multipartRequestParsed = processedRequest != request;
// Determine handler for the current request.
//根据当前请求获取HandlerExecutionChain对象(核心关键 在下面进行详细叙述)
mappedHandler = getHandler(processedRequest, false);
if (mappedHandler == null || mappedHandler.getHandler() == 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 (logger.isDebugEnabled()) {
String requestUri = urlPathHelper.getRequestUri(request);
logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
//执行所有拦截器的preHandler方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
try {
// Actually invoke the handler.
//真正的执行我们编写的Controller的某个具体的方法,并返回视图和数据对象
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
}
applyDefaultViewName(request, mv);
//执行所有拦截器postHandler方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion 执行拦截器的afterHandler方法
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
return;
}
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
4、HandlerExecutionChain 类
/**
处理器执行链 所有的http请求通过HandlerMapping都会返回该对象 其中包含handler处理器(Controller层要调用的方法)
还有spring注册的所有拦截器
*/
public class HandlerExecutionChain {
private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
//Controller层具体的某一个方法
private final Object handler;
//spring注册的所有拦截器
private HandlerInterceptor[] interceptors;
//spring注册的所有拦截器
private List<HandlerInterceptor> interceptorList;
//拦截器数组的游标
private int interceptorIndex = -1;
/**
* Apply preHandle methods of registered interceptors.
*执行拦截器的preHandle()方法
*/
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (getInterceptors() != null) {
for (int i = 0; i < getInterceptors().length; i++) {
HandlerInterceptor interceptor = getInterceptors()[i];
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
/**
* Apply postHandle methods of registered interceptors.
* 执行拦截器的postHandle ()方法
*/
void applyPostHandle(HttpServletRequest request, HttpServletResponse response,
ModelAndView mv) throws Exception {
if (getInterceptors() == null) {
return;
}
for (int i = getInterceptors().length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = getInterceptors()[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
/**
* 仅仅在拦截器的preHandle成功调用且返回true,才执行拦截器的afterCompletion ()方法
* Will just invoke afterCompletion for all interceptors whose preHandle invocation
* has successfully completed and returned true.
*/
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
throws Exception {
if (getInterceptors() == null) {
return;
}
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = getInterceptors()[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion
threw exception", ex2);
}
}
}
}
5、获取HandlerExcutorChain对象的方法追踪
5.1 dispatchServlet的getHandler
/**
* Return the HandlerExecutionChain for this request.
从请求中获取HandlerExecutionChain 。遍历该servlet中的所有HandlerMapping
如果在遍历过程中找到对应的HandlerExecutionChain 就直接返回该对象
*/
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {//遍历注册在spring中的HandlerMapping
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
} //通过HandlerMapping获取执行器链
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
5.2 HandlerMapping的getHandler()方法
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//获取对应的HandlerMethod方法 参考5.3
Object handler = getHandlerInternal(request);
if (handler == null) {
//如果没有则获取默认的HandlerMethod方法
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
//如果在xml中配置了bean,或者解析器的 即handler为string
if (handler instanceof String) {
String handlerName = (String) handler;
//从spring的上下文环境中获取bean
handler = getApplicationContext().getBean(handlerName);
}
//获取HandlerExecutionChain的执行链 添加拦截器和handler 参考5.4
return getHandlerExecutionChain(handler, request);
}
5.3 getHandlerInternal() 方法 查找指定的Controller中的请求方法
//根据请求url获取到具体的Conrtroller的方法
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
//获取请求路径 例如: /front/productList.shtml
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
if (logger.isDebugEnabled()) {
logger.debug("Looking up handler method for path " + lookupPath);
}
//通过请求url和请求信息 直接定位到对应Controller层的方法
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
if (logger.isDebugEnabled()) {
if (handlerMethod != null) {
logger.debug("Returning handler method [" + handlerMethod + "]");
}
else {
logger.debug("Did not find handler method for [" + lookupPath + "]");
}
}
return (handlerMethod != null) ? handlerMethod.createWithResolvedBean() : null;
}
5.4 获取 HandlerExecutionChain链
//获取HandlerExecutionChain 链 //getHandlerExecutionChain 获取执行器链(该chain中包含请求对应的方法(HttpMethod)和所有的拦截器)
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
//handler(应该是HttpMethod) 为什么要进行这一步的操作?
//创建执行链HandlerExecutionChain对象
HandlerExecutionChain chain =
(handler instanceof HandlerExecutionChain) ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler);
//添加拦截器到执行链条
chain.addInterceptors(getAdaptedInterceptors());
String lookupPath = urlPathHelper.getLookupPathForRequest(request);
//MappedInterceptors来处理匹配路径的拦截器
//如果当前路径与mappedInterceptor的要求url匹配 如果匹配则将其添加进去
for (MappedInterceptor mappedInterceptor : mappedInterceptors) {
if (mappedInterceptor.matches(lookupPath, pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
return chain;
}
6、对获取HandlerAdapter的追踪
//获取处理器适配器HandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
//遍历用户初始化的所有适配器
for (HandlerAdapter ha : this.handlerAdapters) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler adapter [" + ha + "]");
}
//如果当前的handlerAdapter能够处理Handler则直接返回该处理器适配器
if (ha.supports(handler)) {
return ha;
}
}
//否则抛出异常
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
7、HandlerAdapter执行Handler返回ModelView视图
7.1 AbstractHandlerMethodAdapter的handle方法
//HandlerAdapter调用handle方法 (该方法位于AbstractHandlerMethodAdapter中,具体的实现调用了HandlerInternal方法)
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//该方法为抽像方法,具体交由子类去实现
return handleInternal(request, response, (HandlerMethod) handler);
}
7.2 执行子类的HandleInternal方法(以RequestMappingHandlerAdapter为例子)
@Override
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
//checkAndPrepare方法的介绍 检查给于的请求request和响应response是否符合设置,
//检查是否可以支持handlerMethod具体要执行的controller的方法),和必要的session并设置缓存时间
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
// Always prevent caching in case of session attribute management.
checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
}
else {
// Uses configured default cacheSeconds setting.
checkAndPrepare(request, response, true);
}
//真正的执行处理invokeHandleMethod方法
// Execute invokeHandlerMethod in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
return invokeHandleMethod(request, response, handlerMethod);
}
}
}
return invokeHandleMethod(request, response, handlerMethod);
}
7.3 invokeHandleMethod
//执行invokeHandleMethod方法
private ModelAndView invokeHandleMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
//创建数据类型转换工厂
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
//将handlerMethod方法来进行包装处理
ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory);
//创建存放ModelAndView的容器
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
//RequestContextUtils.getInputFlashMap(request)可以获取到request中的attribute,
// 并且将所有的request中的attribute放置在mavContainer中
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
//会将该HttpMethod对应的controller方法中的使用标记@ModelAttributes的方法都执行一遍
modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
//异步请求以及异步的一下处理(没有跟踪)
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
final WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.setTaskExecutor(this.taskExecutor);
asyncManager.setAsyncWebRequest(asyncWebRequest);
asyncManager.registerCallableInterceptors(this.callableInterceptors);
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
if (asyncManager.hasConcurrentResult()) {
Object result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
if (logger.isDebugEnabled()) {
logger.debug("Found concurrent result value [" + result + "]");
}
requestMappingMethod = requestMappingMethod.wrapConcurrentResult(result);
}
//执行(待续...)
requestMappingMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
//返回ModelAndView对象
return getModelAndView(mavContainer, modelFactory, webRequest);
}