SpringMVC有五大核心组件, DispatcherServlet, HandlerMapping, Controller, ModelAndView, ViewResolver; 其中以DispatcherServlet最为核心, 以下简称ds, 类似电脑cpu.
当容器接收到请求后, 会先到xml中找到对应servlet, 本质就是ds, 然后ds父类的service方法进行处理, 最后进入ds的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 {
try {
ModelAndView err = null;
Object 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;
}
// 获取对应的handler适配器
HandlerAdapter err1 = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if(isGet || "HEAD".equals(method)) {
long lastModified = err1.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;
}
}
// 执行调用链中拦截器的pre方法
if(!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 利用反射技术调用Controller中的方法
err = err1.handle(processedRequest, response, mappedHandler.getHandler());
if(asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 获取返回视图全路径
this.applyDefaultViewName(processedRequest, err);
// 执行调用链中拦截器的post方法
mappedHandler.applyPostHandle(processedRequest, response, err);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler dispatch failed", var21);
}
// 视图解析
this.processDispatchResult(processedRequest, response, mappedHandler, err, (Exception)dispatchException);
} catch (Exception var22) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
} catch (Throwable var23) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
}
} finally {
if(asyncManager.isConcurrentHandlingStarted()) {
if(mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if(multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Iterator var2 = this.handlerMappings.iterator();
// 遍历所有的mapping
HandlerExecutionChain handler;
do {
if(!var2.hasNext()) {
return null;
}
HandlerMapping hm = (HandlerMapping)var2.next();
if(this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name \'" + this.getServletName() + "\'");
}
// 获取调用链,如果不为空, 直接返回
handler = hm.getHandler(request);
} while(handler == null);
return handler;
}
// getHandler()方法调用了以下方法, 将拦截器添加到调用链中, 注意此时会添加SpringMVC内置的一个拦截器, 并且顺序为第一个
protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request, HandlerExecutionChain chain, CorsConfiguration config) {
if(CorsUtils.isPreFlightRequest(request)) {
HandlerInterceptor[] interceptors = chain.getInterceptors();
chain = new HandlerExecutionChain(new AbstractHandlerMapping.PreFlightHandler(config), interceptors);
} else {
chain.addInterceptor(new AbstractHandlerMapping.CorsInterceptor(config));
}
return chain;
}
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if(!ObjectUtils.isEmpty(interceptors)) {
// 注意此时是顺序调用拦截器的preHandle方法
for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
HandlerInterceptor interceptor = interceptors[i];
if(!interceptor.preHandle(request, response, this.handler)) {
this.triggerAfterCompletion(request, response, (Exception)null);
return false;
}
}
}
return true;
}
handler方法经过一通调用最后调用以下方法
protected Object doInvoke(Object... args) throws Exception {
...
ReflectionUtils.makeAccessible(this.getBridgedMethod());
return this.getBridgedMethod().invoke(this.getBean(), args);
...
}
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if(!ObjectUtils.isEmpty(interceptors)) {
// 注意此时是逆序调用拦截器的postHandle方法
for(int i = interceptors.length - 1; i >= 0; --i) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
booleanerrorView = false;
if(exception != null) {
if(exception instanceof ModelAndViewDefiningException) {
this.logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException)exception).getModelAndView();
} else {
Object handler = mappedHandler != null?mappedHandler.getHandler():null;
mv = this.processHandlerException(request, response, handler, exception);
errorView = mv != null;
}
}
if(mv != null && !mv.wasCleared()) {
// 解析视图
this.render(mv, request, response);
if(errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
} else if(this.logger.isDebugEnabled()) {
this.logger.debug("Null ModelAndView returned to DispatcherServlet with name \'" + this.getServletName() + "\': assuming HandlerAdapter completed request handling");
}
if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
if(mappedHandler != null) {
// 逆序执行调用链中各拦截器的
mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
}
}
}
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
Locale locale = this.localeResolver.resolveLocale(request);
response.setLocale(locale);
View view;
// 判断本地是否已经加载过视图
if(mv.isReference()) {
// 没有则创建视图解析器解析
view = this.resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
if(view == null) {
throw new ServletException("Could not resolve view with name \'" + mv.getViewName() + "\' in servlet with name \'" + this.getServletName() + "\'");
}
} else {
// 如果有使用本地视图解析器
view = mv.getView();
if(view == null) {
throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a View object in servlet with name \'" + this.getServletName() + "\'");
}
}
if(this.logger.isDebugEnabled()) {
this.logger.debug("Rendering view [" + view + "] in DispatcherServlet with name \'" + this.getServletName() + "\'");
}
try {
if(mv.getStatus() != null) {
response.setStatus(mv.getStatus().value());
}
view.render(mv.getModelInternal(), request, response);
} catch (Exception var7) {
if(this.logger.isDebugEnabled()) {
this.logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name \'" + this.getServletName() + "\'", var7);
}
throw var7;
}
}
protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale, HttpServletRequest request) throws Exception {
Iterator var5 = this.viewResolvers.iterator();
View view;
do {
if(!var5.hasNext()) {
return null;
}
// 获取视图解析器
ViewResolver viewResolver = (ViewResolver)var5.next();
// 解析视图
view = viewResolver.resolveViewName(viewName, locale);
} while(view == null);
return view;
}
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if(!ObjectUtils.isEmpty(interceptors)) {
// 注意此时是逆序调用拦截器的afterCompletion方法
for(int i = this.interceptorIndex; i >= 0; --i) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
} catch (Throwable var8) {
logger.error("HandlerInterceptor.afterCompletion threw exception", var8);
}
}
}
}
由于初次阅读SpringMVC源码, 可能会有很多不足, 如有问题, 欢迎评论指正, 感激不尽!