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进行请求处理