Springboot請求映射原理

springboot中的spring-boot-starter-web還是使用的spring-mvc。而spring-mvc中處理所有的請求的入口就是DispatcherServlet.

而DispatcherServlet就一定要重寫doGet或者doPost,但是在springboot中的DispatcherServlet中沒有這兩個方法。

 

 

 而是在DispatcherServlet的父類FrameworkServlet中找到了。

 

 

 

@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
	processRequest(request, response);
}


@Override
protected final void doPost(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
	processRequest(request, response);
}

  看出不管是doGet還是doPost都是執行的processRequest這個方法。

processRequest方法
 1 protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3 
 4         long startTime = System.currentTimeMillis();
 5         Throwable failureCause = null;
 6 
 7         LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
 8         LocaleContext localeContext = buildLocaleContext(request);
 9 
10         RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
11         ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
12 
13         WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
14         asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
15 
16         initContextHolders(request, localeContext, requestAttributes);
17 
18         try {
19             doService(request, response);
20         }
21         catch (ServletException | IOException ex) {
22             failureCause = ex;
23             throw ex;
24         }
25         catch (Throwable ex) {
26             failureCause = ex;
27             throw new NestedServletException("Request processing failed", ex);
28         }
29 
30         finally {
31             resetContextHolders(request, previousLocaleContext, previousAttributes);
32             if (requestAttributes != null) {
33                 requestAttributes.requestCompleted();
34             }
35             logResult(request, response, failureCause, asyncManager);
36             publishRequestHandledEvent(request, response, startTime, failureCause);
37         }
38     }

主要看第19行的doService(request, response);方法,而這個方法中又調用了核心的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 {
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

				// Determine handler for the current request.
				mappedHandler = getHandler(processedRequest);

  通過getHandler方法拿到對應可以處理當前請求的mappedHandler;

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			for (HandlerMapping mapping : this.handlerMappings) {
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

  debug之後發現會有如下幾個HandlerMapping;

 

 而我們需要找到的是

RequestMappingHandlerMapping:保存了所有@RequestMapping 和handler的映射規則。

 

 當有請求進來時,會循環嘗試所有的HandlerMapping看是否有請求信息。

    • 如果有就找到這個請求對應的handler
    • 如果沒有就是下一個 HandlerMapping

Springboot請求映射原理就是其實就是查詢對應HandlerMapping進行請求處理

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章