springMVC 请求流程解析

@SuppressWarnings("deprecation")
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
	// 实际处理时用的请求,如果不是上传请求,则直接使用接收到的 request,否则封装成上传的 request
	HttpServletRequest processedRequest = request;
	// 处理请求的处理器链(包括处理器和对应的 interceptor)
	HandlerExecutionChain mappedHandler = null;
	// 上传标志
	boolean multipartRequestParsed = false;

	// 获取异步处理器
	WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

	try {
		ModelAndView mv = null;
		Exception dispatchException = null;

		try {
			// 检查是否是上传请求
			// 如果是上传请求,则将其封装成 multipartRequestParsed
			// 内有九个组件之一 MultipartResolver
			processedRequest = checkMultipart(request);
			// 上传请求标志位
			// 通过对象是否更改过进行判断
			multipartRequestParsed = (processedRequest != request);

			// Determine handler for the current request.
			// 获得请求对应的 HandlerExecutionChain 对象(HandlerMethod(Controller 的具体方法) 和 HandlerInterceptor 拦截器们)
			// 重要 拦截器链
			// 循环遍历三个 HandlerMapping 进行匹配
			mappedHandler = getHandler(processedRequest);
			// 获取不到控制器
			if (mappedHandler == null) {
				noHandlerFound(processedRequest, response);
				return;
			}

			// Determine handler adapter for the current request.
			// 通过适配器的方式进行调用,因为有多个选择。
			// 根据
			// 获取与当前 handler 匹配的 Adapter
			// 重要
			HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

			// Process last-modified header, if supported by the handler.
			// 处理GET、HEAD请求的Last-Modified,当浏览器第一次跟服务器请求资源时,服务器会在返回的请求头里包含一个 last_modified 的属性,
			// last_modified 代表资源最后时什么时候修改的,在浏览器以后发送请求的时候,会同时发送之前接收到的 Last_modified .服务器接收到带last_modified的请求后,
			// 会跟实际资源的最后修改时间做对比,如果过期了返回新的资源,否则直接返回304表示未过期,直接使用之前缓存的结果即可
			// 获取请求方式
			String method = request.getMethod();
			boolean isGet = HttpMethod.GET.matches(method);
			if (isGet || HttpMethod.HEAD.matches(method)) {
				// 为了减少资源重复获取
				long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
				if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
					return;
				}
			}
			// 执行响应的 Interceptor 的 PreHandle
			// 注意:该方法如果有一个拦截器的前置处理器返回 false,则开始倒序触发所有的拦截器的已完成处理
			// mappedHandler 是 HandlerExecutionChain
			// 重要
			if (!mappedHandler.applyPreHandle(processedRequest, response)) {
				return;
			}

			// Actually invoke the handler.
			// mv ModelAndView
			// 使用适配器执行 handler,并返回视图
			// 重要
			// AbstractHandlerMethodAdapter
			mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
			// 如果有异步处理
			if (asyncManager.isConcurrentHandlingStarted()) {
				return;
			}
			// 如果 view 为空,根据 request 设置默认的 view
			// 默认名字为 请求路径名。
			// 组件:RequestToViewNameTranslator
			applyDefaultViewName(processedRequest, mv);
			// 重要  拦截器的后置处理器
			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 ServletException("Handler dispatch failed: " + err, err);
		}
		// 重要
		// 处理返回结果,包括处理异常,页面渲染
		processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
	}
	catch (Exception ex) {
		triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
	}
	catch (Throwable err) {
		triggerAfterCompletion(processedRequest, response, mappedHandler,
				new ServletException("Handler processing failed: " + err, err));
	}
	finally {
		if (asyncManager.isConcurrentHandlingStarted()) {
			// Instead of postHandle and afterCompletion
			if (mappedHandler != null) {
				// 触发 Interceptor 的 afterCompletion
				mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
			}
		}
		else {
			// Clean up any resources used by a multipart request.
			if (multipartRequestParsed) {
				cleanupMultipart(processedRequest);
			}
		}
	}
}`

1.getHandel()

    @Nullable
	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			// 默认有三个
			for (HandlerMapping mapping : this.handlerMappings) {
				// BeanNameUrlHandlerMapping 第一次 匹配不到
				// RequestMappingHandlerMapping - 第二个 通过@Controller生成的
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

通过断点可以看到默认会有两个HandlerMapping的实现:RequestMappingHandlerMapping和BeanNameUrlHandlerMapping;
所有加了@Controller的Controller对象会放在RequestMappingHandlerMapping的父类
HandlerExecutionChain即为控制器与连接器

2.由于SpringMVC提供了4种类型的HandlerAdapter,并且他们没有统一的调用接口,所以需要通过适配器来使用。同样适配器的类型也有4种。如下所示:

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");
}

支持当前Handler类型的适配器并返回
3.执行 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());,
4.执行响应的interceptor的postHandler方法
查找视图,并相应View

posted @   辉辉、  阅读(39)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示