DispatcherServlet逻辑处理

先看一下DispatcherServlet的关系结构图
在这里插入图片描述
HttpServlet大家一定不陌生。
在这里插入图片描述
DispatcherServlet重写了那些doGet、doPost方法。
在这里插入图片描述
进入到processRequest方法
在这里插入图片描述
doService方法,该方法只是做了一些准备工作,例如将localeResolver、themeResolver解析器、xmlWebApplicationContext放入request属性中。紧接着会调用doDispatch方法。
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 {
				//检查request是否为MultipartContent类型,是则通过之前介绍的multipartResolver文件解析器将request类型转换
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

				// Determine handler for the current request.确定当前request的处理器
				//通过注册的handlerMapping映射器来找到对应的Controller
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null) {
					//如果没找到对应的handler,则通过response反馈错误信息。(抛出异常或返回404 我们可配)
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.
				// 循环所有的handlerAdaoter通过supports判断适合的handler,得到合适的HandlerAdapter
				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)) {
					// 如果handler支持last-modified处理
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}
				// 拦截器的preHandler的方法调用,这里会取出所有的拦截器然后挨个执行
				//如果返回false 会执行triggerAfterCompletion方法,并结束doDispatch方法。
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// Actually invoke the handler.
				//真正Controller的逻辑处理并返回视图
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
				// 处理异步通知的??? 
				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}
				// 查看是否返回了视图,没有的话 通过viewNameTranslator 来获取我们配置的默认视图
				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);
			}
			//判断是否有异常,如果Controller存在,则调用拦截器的AfterCompletion方法
			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);
				}
			}
		}
	}

不看代码的话,我再描述一遍流程:
1.判断request是否为MultipartContent类型,如果是则将request转为MultipartHttpServletRequest类型。
2.使用handlerMapping查找request对应的Controller
3.如果没找到对应的Handler(Controller),则通过response向用户返回错误信息。
4.如果找到了,则根据当前handler寻找对应的handlerAdapter。
5.获取到handlerAdapter之后,接下来是对缓存Last-Modified处理。(判断If-modified-Since是否大于当前的getLastModified)
6.接下来是拦截器的preHandler方法的调用。
7.调用控制器适配器的handle方法,这是真正的逻辑处理。
8.如果返回的视图没有,则使用默认视图。
9.然后调用拦截器的postHandle方法。
10.然后执行派发结果处理,有异常处理异常,没有render渲染视图。

这里详细描述getHandler过程
在这里插入图片描述
看一下getHandlerInternal方法
在这里插入图片描述
lookupHandler中会根据urlPath获取对应的handler,匹配不到,会尝试使用通配符匹配Controller。通配符
buildPathExposingHandler方法将配置中对应拦截器加入到执行链中,保证这些拦截器可以有效的作用于目标对象。

在这里插入图片描述
在这里插入图片描述
紧接着获取处理器适配器getHandlerAdapter方法。
在这里插入图片描述
看一下SimpleControllerHandlerAdapter类
在这里插入图片描述
Servlet过滤器可以再servlet处理每个web请求的前后分别对它进行前置处理和后置处理。
SpringMVC允许通过处理拦截web请求,进行前置处理和后置处理。处理拦截是在Spring的web应用程序上下文中配置的。因此它们可以利用各种容器特性,并引用容器中声明的任何bean。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
看一下render方法

在这里插入图片描述

在这里插入图片描述
再看一下createView方法
在这里插入图片描述
解析得到视图时候就可以进一步处理跳转逻辑。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值