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進行請求處理