当前位置:   article > 正文

SpringMVC源码-流程分析_springmvc 源码流程

springmvc 源码流程

SpringMVC源码-流程分析


在这里插入图片描述
controller其实就是一个servlet
在这里插入图片描述
FrameworkServlet 有一个属性 其实就是spring-mvc的配置文件
在这里插入图片描述
spring-mvc配置文件 扫描controller
在这里插入图片描述
servlet的前端控制器DispatcherServlet类图
在这里插入图片描述
DispatcherServlet 继承FrameworkServlet
FrameworkServlet 继承HttpServletBean
HttpServletBean 继承 HttpServlet

servlet中最重要的方法是service方法servlet调用service方法
从FrameworkServlet的service方法开始看
在这里插入图片描述
可以看到 如果条件成立 调用processRequest方法 如果条件不成立 调用父类的service方法
其实调用父类的某一个方法 如果子类有重写这个方法 最终调用的还是子类的方法
可以从httpservlet中看到 调用本身的service方法 就是调用doget dopost方法等等
在这里插入图片描述
回过头看FrameworkServlet的doget dopost等方法
在这里插入图片描述
可以看到调用的还是processRequest这个方法
所以最终调用的都是processRequest方法
进入processRequest方法
在这里插入图片描述
可以看到 重点代码只有一行
doService(request, response);
进入doservice方法中
在这里插入图片描述
发现doservice方法是abstract抽象的
抽象的方法只能让子类去实现 所以去DispatcherServlet中的doservice方法中
在这里插入图片描述
可以发现 重要代码只有一句
doDispatch(request, response);

这个方法就是真正的入口

进入doDispatch(request, response);方法

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

				// Determine handler for the current request.
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.
				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)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (logger.isDebugEnabled()) {
						logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
					}
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}

				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// Actually invoke the handler.
				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) {
				// 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);
			}
			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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84

上面就是核心代码快
在这里插入图片描述
在这里插入图片描述
mappedHandler = getHandler(processedRequest);
这行代码 得到了返回的handler
进入getHandler()方法
在这里插入图片描述
这段代码是从handlerMappings 中拿到一个handlerMapping后 再来对比当前的请求是哪一个handler 最终返回该handler
handlerMappings 中由springMVC内置了两个handlermapping
这里走了首图中的第二步和第三步 接下来核心控制器DispatcherServlet拿到handler后 执行第四步
在这里插入图片描述
执行getHandlerAdapter()方法; handler适配器
进入getHandlerAdapter方法
在这里插入图片描述
和上面的getHandler()方法一样
这段代码是从handlerAdapters中拿到一个handlerAdapter后 再来对比当前的请求是哪一个handlerAdapter最终返回该HandlerAdapter
handlerAdapters中由springMVC内置了两个handlerAdapter
然后继续执行代码
在这里插入图片描述
在这里插入图片描述
执行之前执行拦截器
在这里插入图片描述
用得到的handlerAdapter执行handler后返回mv 返回一个视图
在这里插入图片描述
在这里插入图片描述
最终 通过反射 执行我们自己写的controller中的代码

handlerAdapters和handlerMappings 是在spring-mvc的jar包中配置好的
在这里插入图片描述
在这里插入图片描述

如果用xml的方式配置controller 就会执行第一个handlermapping
org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
如果使用注解的方式 就会执行第二个handlermapping
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
所以说 自己实现springMVC中的controller有三种方式 因为有三个HandlerAdapter controller适配器
如果用以前接口的方法去实现spring-mvc的话 就会执行上面两个中的一个
如果用反射的话就会执行最后一个
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

在DispatcherServlet加载的时候 这个配置文件就已经加载进去了

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/1015678
推荐阅读
相关标签
  

闽ICP备14008679号