当前位置:   article > 正文

SpringBoot --请求映射原理分析_springboot http请求原理

springboot http请求原理

请求映射原理

我们在进行web开发中,每次发请求是如何找到哪个方法去处理这个请求的。SpringBoot中,每一个请求都会来到DispatcherServlet,底层还是使用SpringMVC,DispatcherServlet是处理所有请求的开始。

DispatcherServlet继承树

在这里插入图片描述
DispatcherServlet继承了FrameworkServlet,其中FrameworkServlet中重写了doGet()、doPost()方法

public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
	...省略...
	@Override
	protected final void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		processRequest(request, response);
	}

	/**
	 * Delegate POST requests to {@link #processRequest}.
	 * @see #doService
	 */
	@Override
	protected final void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		processRequest(request, response);
	}
	...省略
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

doGet()、doPost()方法又调用了processRequest()方法

protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		...省略...
		try {
			doService(request, response);
		}
		...省略...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这个方法关键又调用了一个doService()方法去处理,找到这个方法,发现在FrameworkServlet 中并没有实现

protected abstract void doService(HttpServletRequest request, HttpServletResponse response)
			throws Exception;
  • 1
  • 2

那就去找子类DispatcherServlet中是否实现了这个方法,发现果然实现了

@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
	...省略....
		logRequest(request);
	try {
			doDispatch(request, response);
			}
	...省略....
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

其中关键是doDispatch()方法。
这里总结一下源码调用方法的流程:一个请求过来,首先到HttpServlet的doGet()方法,这个方法被FrameworkServlet重写,进而调用FrameworkServlet中的processRequest()方法,然后调用了DispatcherServlet实现的doService()方法,最后交给doDispatch()方法处理。

doDispatch()方法

我们在debug模式下查看处理流程,首先controller


@RestController
public class HelloController {

    Person person;
    @RequestMapping("/person")
    public Person person(){
        return person;
    }
    @RequestMapping("/hello")
    public String hello(){
        return "hello";
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

浏览器发送一个请求:http://localhost:8080/hello,找到断点处:
在这里插入图片描述
我们继续看doDispatch()方法的源码:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		.....省略一些初始化的内容.....
			try {
				processedRequest = checkMultipart(request);//直到这个方法,是有功能的方法,判断是不是关于文件上传的请求
				multipartRequestParsed = (processedRequest != request);

				// Determine handler for the current request.
				//这个方法决定哪个handler处理当前请求
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == 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 (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);
			}
  • 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

我们让代码走到mappedHandler = getHandler(processedRequest)这一行,这个方法决定哪个handler(controller中的方法)处理当前请求。然后放行,查看handler是什么
在这里插入图片描述
那么它是怎么找到的呢,我们把断点打到这个方法上,在重新发送一遍请求
在这里插入图片描述
如图,方法参数中的请求确实是我们发送的hello请求,然后step into进入
在这里插入图片描述
这里有一个handlerMapping,这是一个处理器映射器,SpringMVC根据它中的映射规则知道了哪个请求应该由哪个处理器处理。默认的handlerMapping有5个(如图),其中第一个RequestMappingHandlerMapping中保存了@RequestMapping和handler的映射规则。当我们的应用一启动,SpringMVC自动扫描所有的Controller并解析注解,把注解信息保存在handlerMapping里面。 然后通过循环遍历着5个handlerMapping,看哪个可以处理当前请求。
在这里插入图片描述
如上图,发现我们自己在controller中写的路径都存到了这里面。然后通过mapping.getHandler(request)把请求对应的handler找到(也就是controller中对应的方法)完成映射。
在这里插入图片描述

最后,此文章介绍了请求映射的原理,只是个人的一些理解,欢迎指正。

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

闽ICP备14008679号