2.1、DispatcherServlet
DispatcherServlet作为SpringMVC的核心所在,我们需要消息的了解它。它和Servlet相似,内部也是通过 doService 方法处理HTTP请求的,我们可以观看它内部处理的步骤,可以更好的帮助我们理解SpringMVC的整个流程
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
logRequest(request);
// 在包含的情况下保留请求属性的快照,以便能够在包含后恢复原始属性。
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<>();
Enumeration<?> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}
// 使框架对象可用于处理程序和视图对象。
//设置WEB IOC容器
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());
//FlashMap开发才用的到这块
if (this.flashMapManager != null) {
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);
}
//上一个请求路径
RequestPath previousRequestPath = null;
if (this.parseRequestPath) {
previousRequestPath = (RequestPath) request.getAttribute(ServletRequestPathUtils.PATH_ATTRIBUTE);
ServletRequestPathUtils.parseAndCache(request);
}
try {
//分发处理,对处理程序的实际调度。将通过依次应用 servlet 的 HandlerMappings 来获取处理程序。
doDispatch(request, response);
}
finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
//恢复原始属性快照,以防包含
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
if (this.parseRequestPath) {
ServletRequestPathUtils.setParsedRequestPath(previousRequestPath, request);
}
}
}
doService在进行快照处理后,就进行了分发操作 doDispatch(request, response)。此方法将将通过依次应用 servlet 的 HandlerMappings 来获取处理程序。
//处理程序将通过依次应用 servlet 的 HandlerMappings 来获得。 HandlerAdapter 将通过查询 servlet 的已安装 HandlerAdapter 来获得,以找到第一个支持处理程序类的。
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);
// 确定当前请求的处理程序,以获取相应的执行链,如果没有直接退出
mappedHandler = getHandler(processedRequest);
//没有获取到,直接退出
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// 获取到了执行链,调用HandlerAdapter适配器。
//确定当前请求的处理程序适配器(HandlerAdapter)
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 如果处理程序支持,则处理最后修改的标头
//判断此请求时get、还是post
String method = request.getMethod();
boolean isGet = HttpMethod.GET.matches(method);
//是get请求
if (isGet || HttpMethod.HEAD.matches(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
//执行拦截器前的预处理方法,返回false直接结束
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 执行处理器,返回ModelAndView
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 {
if (asyncManager.isConcurrentHandlingStarted()) {on
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
springMVC在一开始就初始化了处理器映射器,并将所有的处理器映射器封装到了 handlerMappings中,它通过遍历获取对应的处理器映射器,并将其封装成HandlerExecutionChain对象,这个对象就是处理程序执行链,由处理程序对象和任何处理程序拦截器组成。
private List<HandlerMapping> handlerMappings;
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
DispatcherServlet获取到了执行链,就应该去找相应的HandlerAdapter去执行这个执行链了,同handlerMapping类似,HandlerAdapter适配器一样也是在启动时被封装到List中,遍历看哪一个适配器支持这个执行链,就返回那个。
private List<HandlerAdapter> handlerAdapters;
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
//看哪一个适配器支持这个执行链
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
适配器执行完成后,得到ModelAndView,就会开始进行视图的解析,
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {
boolean errorView = false;
//如果处理器发生了异常
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()) {
//进行渲染视图
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
//没有视图渲染,返回 null ModelAndView
if (logger.isTraceEnabled()) {
logger.trace("No view rendering, null ModelAndView returned.");
}
}
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// 在转发期间开始并发处理
return;
}
if (mappedHandler != null) {
// 异常(如果有)已被处理..
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
根据逻辑视图和真实视图进行不同操作。
//渲染给定的 ModelAndView。
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
//确定请求的语言环境并将其应用于响应。国际化
Locale locale =
(this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
response.setLocale(locale);
View view;
String viewName = mv.getViewName();
//是否是逻辑视图,如果是则转换成真实视图
if (viewName != null) {
// 我们需要解析视图名称,将逻辑视图,转化成真实视图
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
if (view == null) {
throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
"' in servlet with name '" + getServletName() + "'");
}
}
//非逻辑视图的处理
else {
// 无需查找:ModelAndView 对象包含实际的 View 对象
view = mv.getView();
if (view == null) {
throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
"View object in servlet with name '" + getServletName() + "'");
}
}
// 委托给 View 对象进行渲染。
if (logger.isTraceEnabled()) {
logger.trace("Rendering view [" + view + "] ");
}
try {
if (mv.getStatus() != null) {
response.setStatus(mv.getStatus().value());
}
//渲染视图 mv.getModelInternal()数据模型。view为视图
view.render(mv.getModelInternal(), request, response);
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error rendering view [" + view + "]", ex);
}
throw ex;
}
}