首页 > 其他分享 >springMVC 请求流程解析

springMVC 请求流程解析

时间:2024-08-11 12:26:57浏览次数:9  
标签:请求 springMVC 流程 request response handler 解析 mappedHandler processedRequest

@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

标签:请求,springMVC,流程,request,response,handler,解析,mappedHandler,processedRequest
From: https://www.cnblogs.com/jichenghui/p/18353250

相关文章

  • 电子商务图像生成技术:AI驱动的自动化流程
    摘要:本文介绍了一种基于人工智能技术的电子商务图像生成系统,该系统能够自动化地完成商品图像的生成过程。通过简单的三个步骤,用户可以快速生成高质量的电商主图和头图,从而提高工作效率并降低成本。**关键词:**人工智能,电商图像,自动化生成,图像处理1.引言在电子商务领域,高质......
  • java流程控制:用户交互Scanner
    1.首先输入newScanner然后Alt+回车建立一个扫描器2.选择使用next方式或者nextLine方式进行接收3.使用if判断用户是否输入字符串,有hasNext和hasNextLine两种4.定义一个变量为next或nextLine方式5.输出该方式6.关闭IO类,防止占用资源next和nextLine方式的区别next......
  • 深入解析CustomerInfoServiceImpl和CustomerServiceImpl:微信小程序登录功能的实现
    文章目录一、CustomerInfoServiceImpl类详解二、CustomerServiceImpl类详解三、总结在现代移动应用开发中,微信小程序已经成为了许多企业的重要选择。为了支持小程序的用户登录功能,我们需要与微信的认证服务进行集成。这篇文章将带大家深入解析两个关键的服务实现类......
  • wechat crawler url拼接 url解析 微信爬虫 json序列化 反序列化
    WechatPublicRequest\Program.csusingSystem.Collections.Specialized;usingSystem.Diagnostics;usingSystem.Web;usingNewtonsoft.Json;classProgram{staticasyncTaskMain(){varlatestTxtFilePath=GetLatestTxtFilePath();......
  • openai 的各个模型比较(关于英语句子解析)
    最近在使用chatgpt帮助学习英语,主要是进行语法分析和难点解释。为了找到最适合的模型,我比较了多个模型的回答。语法分析问题这是我在实际中理解有困难的句子,尽管比较简短,但从内容上理解,它涉及了倒装。各个模型回答gpt-3.-5-turbo-1106是经过微调的3.5-turbogpt-4o-m......
  • 3.makefile运行流程分析并使用变量改写项目
    3.makefile运行流程分析并使用变量改写项目GNUmake用来构建和管理自己的工程Makefile文件描述了整个工程的编译、连接等规则3.1makefile变量的使用命令格式含义CXXC++编译器的名称,默认值为g++CXXFLAGSC++编译器的选项,无默认值$*不包含扩展名的目标文件......
  • java实现解析pdf格式发票
    为了减少用户工作量及误操作的可能性,需要实现用户上传PDF格式的发票,系统通过解析PDF文件获取发票内容,并直接将其写入表单。以下文章记录了功能实现的代码。发票样式发票内容解析引用Maven使用pdfbox<dependency><groupId>org.apache.pdfbox</groupId><artif......
  • spring启动流程
    ` publicvoidrefresh()throwsBeansException,IllegalStateException{this.startupShutdownLock.lock();try{//启动关闭线程,这个线程用来表示启动当前容器使用的线程//该成员变量在之前的版本中并不存在,也是为了支持后续的并发实例化bean的情况this.startupShutdown......
  • 【解决】Python运行中卡住不动-深度解析
    【解决】Python运行中卡住不动-深度解析在Python编程的广阔世界里,遇到程序运行中突然卡住不动的情况并不罕见。这种情况可能源于多种原因,从简单的代码逻辑错误到复杂的系统资源问题。本文将深入探讨Python程序卡住不动的现象,分析其可能的原因,并提供实用的解决思路和......
  • TypeError: ‘list’ object is not callable 深度解析
    TypeError:‘list’objectisnotcallable深度解析概述:在Python编程中,遇到“TypeError:‘list’objectisnotcallable”这一错误通常意味着你尝试以函数或方法的方式调用了一个列表对象。这种错误往往是由于编码疏忽或理解偏差导致的。本文将深度解析这一......