【原创】005 | 搭上SpringBoot请求处理源码分析专车
前言
如果这是你第二次看到师长,说明你在觊觎我的美色!
点赞+关注再看,养成习惯
没别的意思,就是需要你的窥屏^_^
专车介绍
该趟专车是开往Spring Boot请求处理源码分析专车,主要用来分析Spring Boot是如何将我们的请求路由到指定的控制器方法以及调用执行。
专车问题
- 为什么我们在控制器中添加一个方法,使用@RequestMapping注解标注,指定一个路径,就可以用来处理一个web请求?
- 如果多个方法的请求路径一致,Spring Boot是如何处理的?
专车示例
@RestController @RequestMapping("/persons") public class PersonController { private static List<Person> personList = new ArrayList<>(); static { personList.add(new Person(10001, "test1")); personList.add(new Person(10002, "test2")); personList.add(new Person(10003, "test3")); personList.add(new Person(10004, "test4")); personList.add(new Person(10005, "test5")); } @GetMapping("/") public List<Person> list() { return personList; } @GetMapping("/{id}") public Person get(@PathVariable("id") Integer id) { Person defaultPerson = new Person(88888, "default"); return personList.stream().filter(person -> Objects.equals(person.getId(), id)).findFirst().orElse(defaultPerson); } @PostMapping("/") public void add(@RequestBody Person person) { personList.add(person); } @PutMapping("/") public void update(@RequestBody Person person) { personList.removeIf(p -> Objects.equals(p.getId(), person.getId())); personList.add(person); } }
示例代码提供了GET、POST、PUT请求,接下里我们会结合示例进行源码分析
专车分析
此次分析主要从2个大的方面进行分析:请求初始化、请求处理
请求初始化
请求流程
一次完成的请求流程就是请求--->处理--->响应,业务逻辑处理最终交由我们创建的Servlet来进行处理。以前在使用Spring MVC框架的时候,我们都会在web.xml中配置一个DispathcherServlet。接下来就让我们来看看DispathcherServlet的类图
从如上图可以清晰的看到DispatcherServlet的继承关系。其中一个名为HttpServlet的类,如果写过Servlet的应该都比较的熟悉,以往基于Servlet开发,都会创建一个Servlet实现类,继承HttpServlet并重写service方法,最后在web.xml中配置我们我们创建的Servlet实现类,这样我们就可以使用创建的Servlet实现类来处理我们的web请求了。
HttpServlet初始化
在我们第一次请求的时候会进行Servlet的初始化,主要用来初始化资源。HttpServlet的init方法由父类GenericServlet声明,由子类HttpServletBean实现。
初始化方法:HttpServletBean#init
@Override public final void init() throws ServletException { // ...省略部分代码 // Let subclasses do whatever initialization they like. // 暴露出去一个方法,可以让子类初始化一些自己想要初始化的内容 initServletBean(); }
创建WebApplicationContext:FrameworkServlet#initServletBean
@Override protected final void initServletBean() throws ServletException { // ...省略部分代码 try { // 初始化WebApplicationContext对象 this.webApplicationContext = initWebApplicationContext(); // 空实现 initFrameworkServlet(); } // ...省略部分代码 }
初始化WebApplicationContext对象:FrameworkServlet#initWebApplicationContext
protected WebApplicationContext initWebApplicationContext() { // 获取WebApplicationContext对象 WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); WebApplicationContext wac = null; // ... 省略部分代码 if (!this.refreshEventReceived) { // Either the context is not a ConfigurableApplicationContext with refresh // support or the context injected at construction time had already been // refreshed -> trigger initial onRefresh manually here. synchronized (this.onRefreshMonitor) { // 刷新资源 onRefresh(wac); } } if (this.publishContext) { // Publish the context as a servlet context attribute. String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); } return wac; }
刷新资源:DispatcherServlet#onRefresh
@Override protected void onRefresh(ApplicationContext context) { initStrategies(context); }
初始化策略:DispatcherServlet#initStrategies
protected void initStrategies(ApplicationContext context) { // 初始化多文件解析器 initMultipartResolver(context); // 初始化本地化解析器 initLocaleResolver(context); // 初始化主题解析器 initThemeResolver(context); // 初始化HandlerMapping initHandlerMappings(context); // 初始化HandlerAdapter initHandlerAdapters(context); // 初始化异常解析器 initHandlerExceptionResolvers(context); // 初始化请求到视图名称翻译器 initRequestToViewNameTranslator(context); // 初始化视图解析器 initViewResolvers(context); initFlashMapManager(context); }
来看一下初始化HandlerMapping实现:DispatcherServlet#initHandlerMappings
private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; if (this.detectAllHandlerMappings) { // Find all HandlerMappings in the ApplicationContext, including ancestor contexts. // 从IOC容器中获取类型为HandlerMapping的bean // 对应的bean有RequestMappingHandlerMapping、SimpleUrlHandlerMapping、WelcomePageHandlerMapping Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerMappings = new ArrayList<>(matchingBeans.values()); // We keep HandlerMappings in sorted order. // 对HandlerMapping进行排序 AnnotationAwareOrderComparator.sort(this.handlerMappings); } } }
通过对初始化HandlerMapping实现的分析,我们可以得出,所有的初始化操作就是从IOC容器中获取相应类型的Bean,然后进行属性赋值。
既然能从IOC容器中获取到HandlerMapping bean,那么一定存在定义bean 的地方。打开WebMvcAutoConfiguration类,可以看到如下代码
/** * Configuration equivalent to {@code @EnableWebMvc}. * 此配置等同于使用@EnableWebMvc注解 */ @Configuration public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration { private final WebMvcProperties mvcProperties; private final ListableBeanFactory beanFactory; private final WebMvcRegistrations mvcRegistrations; public EnableWebMvcConfiguration( ObjectProvider<WebMvcProperties> mvcPropertiesProvider, ObjectProvider<WebMvcRegistrations> mvcRegistrationsProvider, ListableBeanFactory beanFactory) { this.mvcProperties = mvcPropertiesProvider.getIfAvailable(); this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique(); this.beanFactory = beanFactory; } // 声明RequestMappingHandlerAdapter bean @Bean @Override public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter(); adapter.setIgnoreDefaultModelOnRedirect(this.mvcProperties == null || this.mvcProperties.isIgnoreDefaultModelOnRedirect()); return adapter; } // 声明RequestMappingHandlerMapping bean @Bean @Primary @Override public RequestMappingHandlerMapping requestMappingHandlerMapping() { // Must be @Primary for MvcUriComponentsBuilder to work return super.requestMappingHandlerMapping(); } }
在如上代码中可以看到HandlerAdapter和HandlerMapping bean的声明
创建RequestMappingHandlerMapping
@Bean public RequestMappingHandlerMapping requestMappingHandlerMapping() { // 创建RequestMappingHandlerMapping对象 RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping(); // 设置属性 mapping.setOrder(0); // 设置拦截器 mapping.setInterceptors(getInterceptors()); mapping.setContentNegotiationManager(mvcContentNegotiationManager()); mapping.setCorsConfigurations(getCorsConfigurations()); // ...省略部分代码 return mapping; }
可以看到除了创建RequestMappingHandlerMapping对象,其它的都是设置属性信息,接下来重点分析创建对象部分的代码
WebMvcConfigurationSupport#createRequestMappingHandlerMapping
protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() { return new RequestMappingHandlerMapping(); }
可以创建RequestMappingHandlerMapping对象的代码很简单,就是调用了无参数构造进行初始化。但是通过查看RequestMappingHandlerMapping的继承关系,我们可以看到该类实现了InitializingBean接口,这也就告诉我们当看到很简单的代码的时候,我们就要看看类的继承关系,来看看是否使用其他形式进行逻辑实现。
既然实现了InitializingBean接口,那就看看创建bean后的初始化方法afterPropertiesSet
@Override public void afterPropertiesSet() { this.config = new RequestMappingInfo.BuilderConfiguration(); this.config.setUrlPathHelper(getUrlPathHelper()); this.config.setPathMatcher(getPathMatcher()); this.config.setSuffixPatternMatch(this.useSuffixPatternMatch); this.config.setTrailingSlashMatch(this.useTrailingSlashMatch); this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch); this.config.setContentNegotiationManager(getContentNegotiationManager()); // 调用父类的初始化方法 super.afterPropertiesSet(); }
@Override **public** **void** **afterPropertiesSet**() { // 初始化处理方法 initHandlerMethods(); }
初始化处理方法:AbstractHandlerMethodMapping#initHandlerMethods
protected void initHandlerMethods() { // 获取并遍历候选bean名称,候选bean就是从IOC容器中获取类型为Object的bean名称,也就是所有的Bean名称 for (String beanName : getCandidateBeanNames()) { // 如果bean的名称不以“scopedTarget.”开头,才进行处理 if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { // 处理候选bean名称 processCandidateBean(beanName); } } handlerMethodsInitialized(getHandlerMethods()); }
处理候选bean名称:AbstractHandlerMethodMapping#processCandidateBean
protected void processCandidateBean(String beanName) { Class<?> beanType = null; try { // 根据bean的名称获取对应bean的类型 beanType = obtainApplicationContext().getType(beanName); } catch (Throwable ex) { // An unresolvable bean type, probably from a lazy bean - let's ignore it. if (logger.isTraceEnabled()) { logger.trace("Could not resolve type for bean '" + beanName + "'", ex); } } // 如果bean的类型不为空并且对应类上含有@Controller注解或者@RequestMapping注解 if (beanType != null && isHandler(beanType)) { // 推断处理方法 detectHandlerMethods(beanName); } }
推断处理方法:AbstractHandlerMethodMapping#detectHandlerMethods
protected void detectHandlerMethods(Object handler) { // 根据bean名称获取类型 Class<?> handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass()); if (handlerType != null) { Class<?> userType = ClassUtils.getUserClass(handlerType); // 获取处理方法 Map<Method, T> methods = MethodIntrospector.selectMethods(userType, (MethodIntrospector.MetadataLookup<T>) method -> { try { // selectMethods方法获取当前类中所有的方法,针对PersonController类就有list、get、add、update四个方法,遍历这四个方法,分别创建对应的RequestMappingInfo对象 // 根据method获取RequestMappingInfo对象 return getMappingForMethod(method, userType); } }); if (logger.isTraceEnabled()) { logger.trace(formatMappings(userType, methods)); } methods.forEach((method, mapping) -> { Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); registerHandlerMethod(handler, invocableMethod, mapping); }); } }
根据method获取RequestMappingInfo对象:RequestMappingHandlerMapping#getMappingForMethod
@Override @Nullable protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) { // 根据method对象创建RequestMappingInfo对象 RequestMappingInfo info = createRequestMappingInfo(method); if (info != null) { // 如果当前方法所在的类也含有@RequestMapping对象,那么也创建一个RequestMappingInfo对象 RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType); if (typeInfo != null) { // 将两个RequestMappingInfo对象进行合并,比如我们PersonController上指定@RequestMapping("/persons"),针对list方法,list方法上指定@RequestMapping("/"),那么合并后的映射路径就是/persons/ info = typeInfo.combine(info); } String prefix = getPathPrefix(handlerType); if (prefix != null) { info = RequestMappingInfo.paths(prefix).build().combine(info); } } // 返回RequestMappingInfo对象 return info; }
回到推断处理方法中:AbstractHandlerMethodMapping#detectHandlerMethods
protected void detectHandlerMethods(Object handler) { // 根据bean名称获取类型 Class<?> handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass()); if (handlerType != null) { Class<?> userType = ClassUtils.getUserClass(handlerType); // 获取处理方法,每个方法都有对应的RequestMappingInfo对象 Map<Method, T> methods = MethodIntrospector.selectMethods(userType, (MethodIntrospector.MetadataLookup<T>) method -> { try { // selectMethods方法中当前类中所有的方法,针对PersonController类就有list、get、add、update四个方法,遍历这四个方法,分别创建对应的RequestMappingInfo对象 // 根据method获取RequestMappingInfo对象 return getMappingForMethod(method, userType); } }); if (logger.isTraceEnabled()) { logger.trace(formatMappings(userType, methods)); } // 遍历处理方法 methods.forEach((method, mapping) -> { // 获取可以执行的method对象 Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); // 注册处理方法 registerHandlerMethod(handler, invocableMethod, mapping); }); } }
注册处理方法:AbstractHandlerMethodMapping.MappingRegistry#register
public void register(T mapping, Object handler, Method method) { // 加写锁,加锁是因为我们可以在代码中手动注册处理方法,为了防止并发问题,此处需要加锁处理 this.readWriteLock.writeLock().lock(); try { // 创建HandlerMethod对象 HandlerMethod handlerMethod = createHandlerMethod(handler, method); assertUniqueMethodMapping(handlerMethod, mapping); // 将RequestMappingInfo对象和HandlerMethod对象添加到map集合中 this.mappingLookup.put(mapping, handlerMethod); List<String> directUrls = getDirectUrls(mapping); for (String url : directUrls) { // 将url和RequestMappingInfo对象添加到map集合中 this.urlLookup.add(url, mapping); } String name = null; if (getNamingStrategy() != null) { name = getNamingStrategy().getName(handlerMethod, mapping); addMappingName(name, handlerMethod); } CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping); if (corsConfig != null) { this.corsLookup.put(handlerMethod, corsConfig); } // 将RequestMappingInfo和MappingRegistration对象添加到map集合中 this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name)); } finally { // 释放锁 this.readWriteLock.writeLock().unlock(); } }
所有方法遍历完成后的结果如下:
到此RequestMappingHandlerMapping对象创建初始化就结束了
RequestMappingHandlerMapping对象创建总结
- 调用afterPropertiesSet初始化方法
- 获取所有的bean名称
- 遍历所有的bean名称,如果bean名称不是以”scopedTarget.“开头就继续处理
- 根据bean名称获取bean类型,获取对应的类型上是否含有@Controller注解或@RequestMapping注解,如果有就继续处理
- 获取当前类中所有的方法,遍历所有的方法
- 根据Method对象生成RequestMappingInfo对象,如果类上也很有@RequestMapping注解,那么也生成RequestMappingInfo对象,将这两个RequestMappingInfo对象进行合并
- 遍历Method、RequestMappingInfo对应的map集合并注册到对应的mappingLookup、urlLookup、registry集合中
创建RequestMappingHandlerAdapter
创建RequestMappingHandlerAdapter:WebMvcAutoConfiguration.EnableWebMvcConfiguration#requestMappingHandlerAdapter
@Bean @Override public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { // 调用父类创建RequestMappingHandlerAdapter对象 RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter(); // ...省略部分代码 return adapter; }
调用父类创建RequestMappingHandlerAdapter:WebMvcConfigurationSupport#requestMappingHandlerAdapter
@Bean public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { // 创建RequestMappingHandlerAdapter对象 RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter(); // 省略部分代码 return adapter; }
请求处理
请求处理流程
- 遍历所有的HandlerMapping对象,找到匹配当前请求对应的HandlerMethod
- 将HandlerMethod包装成HandlerExecutionChain对象
- 根据HandlerMethod找到HandlerAdapter
- HandlerAdapter执行HandlerMethod
匹配HandlerMethod并包装成HandlerExecutionChain对象
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HandlerExecutionChain mappedHandler = null; // 匹配HandlerMethod并包装成HandlerExecutionChain对象 mappedHandler = getHandler(processedRequest); }
获取HandlerExecutionChain对象:DispatcherServlet#getHandler
@Nullable protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { // 遍历所有的HandlerMapping for (HandlerMapping mapping : this.handlerMappings) { // 根据HandlerMapping获取HandlerExecutionChain对象,此处的HandlerMapping就是上面分析过的RequestMappingHandlerMapping对象 HandlerExecutionChain handler = mapping.getHandler(request); // 如果获取到HandlerExecutionChain对象,那么直接将HandlerExecutionChain对象返回 if (handler != null) { return handler; } } } return null; }
根据HandlerMapping获取HandlerExecutionChain对象:AbstractHandlerMapping#getHandler
@Override @Nullable public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // 获取HandlerMethod对象 Object handler = getHandlerInternal(request); // ...省略部分代码 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); // ...省略部分代码 return executionChain; }
获取HandlerMethod对象
@Override protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { // 获取请求的路径,假设此处请求的路径为/persons/ String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); // 加锁 this.mappingRegistry.acquireReadLock(); try { // 寻找HandlerMethod对象 HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); // 获取HandlerMethod所在类对应的bean,然后创建HandlerMethod对象 return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null); } finally { // 释放锁 this.mappingRegistry.releaseReadLock(); } }
寻找HandlerMethod对象:AbstractHandlerMethodMapping#lookupHandlerMethod
在该方法之前再看一下上文中对RequestMappingHandlerMapping分析的结果
@Nullable protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { List<Match> matches = new ArrayList<>(); // 从urlLookup属性中找到当前请求路径对应的RequestMappingInfo信息 // 假设请求的路径为/persons/,那么此处得到的结果有3个 List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath); if (directPathMatches != null) { // 寻找最匹配的RequestMappingInfo // 匹配的方式包括:请求方法、请求header、请求参数等 addMatchingMappings(directPathMatches, matches, request); } if (matches.isEmpty()) { // No choice but to go through all mappings... addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request); } if (!matches.isEmpty()) { Comparator<Match> comparator = new MatchComparator(getMappingComparator(request)); matches.sort(comparator); Match bestMatch = matches.get(0); if (matches.size() > 1) { if (logger.isTraceEnabled()) { logger.trace(matches.size() + " matching mappings: " + matches); } if (CorsUtils.isPreFlightRequest(request)) { return PREFLIGHT_AMBIGUOUS_MATCH; } Match secondBestMatch = matches.get(1); // 如果存在多个匹配结果,就报错 if (comparator.compare(bestMatch, secondBestMatch) == 0) { Method m1 = bestMatch.handlerMethod.getMethod(); Method m2 = secondBestMatch.handlerMethod.getMethod(); String uri = request.getRequestURI(); throw new IllegalStateException( "Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}"); } } request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod); handleMatch(bestMatch.mapping, lookupPath, request); // 返回匹配的HandlerMethod return bestMatch.handlerMethod; } else { return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request); } }
获取HandlerAdapter
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { // Determine handler adapter for the current request. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); }
获取HandlerAdapter:DispatcherServlet#getHandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { for (HandlerAdapter adapter : this.handlerAdapters) { // 如果当前HandlerAdapter支持当前要处理的HnadlerMethod,那么就返回此HandlerAdapter if (adapter.supports(handler)) { return adapter; } } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); }
匹配方法:此处拿RequestMappingHandlerAdapter举例,调用AbstractHandlerMethodAdapter#supports
public final boolean supports(Object handler) { // 如果当前的hander是HandlerMethod,则返回true;后一个表达式直接返回的就是true return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler)); }
从如上分析可以得出的结论就是最终返回的HandlerAdapter为RequestMappingHandlerAdapter
HandlerAdapter执行HandlerMethod
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); }
处理目标方法:RequestMappingHandlerAdapter#handleInternal
@Override protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; checkRequest(request); // Execute invokeHandlerMethod in synchronized block if required. if (this.synchronizeOnSession) { // ...省略部分代码 } else { // No synchronization on session demanded at all... // 调用HandlerMethod方法 mav = invokeHandlerMethod(request, response, handlerMethod); } // ...省略部分代码 return mav; }
调用HandlerMethod方法:RequestMappingHandlerAdapter#invokeHandlerMethod
@Nullable protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest(request, response); try { WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); // 创建ServletInvocableHandlerMethod对象,就是把handlerMethod对象的属性赋值给ServletInvocableHandlerMethod对象的属性 ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); // ...省略部分代码 // 调用方法并处理返回值 invocableMethod.invokeAndHandle(webRequest, mavContainer); if (asyncManager.isConcurrentHandlingStarted()) { return null; } return getModelAndView(mavContainer, modelFactory, webRequest); } finally { webRequest.requestCompleted(); } }
调用方法并处理返回值:ServletInvocableHandlerMethod#invokeAndHandle
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // 执行请求,获取返回值 Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); setResponseStatus(webRequest); // ...省略部分代码 mavContainer.setRequestHandled(false); Assert.state(this.returnValueHandlers != null, "No return value handlers"); try { // 处理返回值 this.returnValueHandlers.handleReturnValue( returnValue, getReturnValueType(returnValue), mavContainer, webRequest); } }
执行请求:InvocableHandlerMethod#invokeForRequest
@Nullable public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // 获取方法参数 Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); if (logger.isTraceEnabled()) { logger.trace("Arguments: " + Arrays.toString(args)); } // 目标方法调用 return doInvoke(args); }
目标方法调用:InvocableHandlerMethod#doInvoke
@Nullable protected Object doInvoke(Object... args) throws Exception { ReflectionUtils.makeAccessible(getBridgedMethod()); try { // 通过反射执行目标方法 return getBridgedMethod().invoke(getBean(), args); } // ...省略部分代码 }
到此请求处理的源码分析就结束了,最终再来看看doDispatch完整的方法:DispatcherServlet#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. // 1、获取handler mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. // 2、获取HandlerAdapter 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); } 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); } } } }
专车总结
一次请求原理如下:
- 请求初始化
- 请求处理
请求初始化
- 初始化RequestMappingHandlerMapping
- 初始化RequestMappingHandlerAdapter
请求处理
- 获取HandlerMethod,组装HandlerExecutionChain对象
- 获取HandlerAdapter
- 使用HandlerAdapter执行HandlerMethod
专车回顾
- 为什么我们在控制器中添加一个方法,使用@RequestMapping注解标注,指定一个路径,就可以用来处理一个web请求?因为在初始化过程中,会将请求路径和处理方法进行绑定,我们在请求ulr的时候,匹配到我们对应的处理方法,然后调用处理方法,就可以执行此次的ewb请求了。
- 如果多个方法的请求路径一致,Spring Boot是如何处理的?如果多个方法的请求路径一致,会拿请求方法、请求参数、请求header等,最终会匹配出最符合的一个处理方法,如果匹配出多个结果,就会报错。
专车遗漏问题
- SpringBoot如何处理请求参数
- SpringBoot如何处理返回结果
- SpringBoot拦截器如何工作
专车扩展
如果是基于微服务开发,那么该如何定义我们的服务?
定义微服务接口:
@RequestMapping("/persons") public interface PersonApi { /** * list * * @return */ @GetMapping("/") List<Person> list(); /** * get * * @param id * @return */ @GetMapping("/{id}") Person get(@PathVariable("id") Integer id); /** * add * * @param person * @return */ @PostMapping("/") void add(@RequestBody Person person); /** * update * * @param person * @return */ @PutMapping("/") void update(@RequestBody Person person); }
定义接口实现:
@RestController public class PersonController implements PersonApi { private static List<Person> personList = new ArrayList<>(); static { personList.add(new Person(10001, "test1")); personList.add(new Person(10002, "test2")); personList.add(new Person(10003, "test3")); personList.add(new Person(10004, "test4")); personList.add(new Person(10005, "test5")); } @Override public List<Person> list() { return personList; } @Override public Person get(Integer id) { Person defaultPerson = new Person(88888, "default"); return personList.stream().filter(person -> Objects.equals(person.getId(), id)).findFirst().orElse(defaultPerson); } @Override public void add(Person person) { personList.add(person); } @Override public void update(Person person) { personList.removeIf(p -> Objects.equals(p.getId(), person.getId())); personList.add(person); } }
本专车系列文章
【原创】001 | 搭上SpringBoot自动注入源码分析专车
【原创】002 | 搭上SpringBoot事务源码分析专车
【原创】003 | 搭上基于SpringBoot事务思想实战专车
【原创】004 | 搭上SpringBoot事务诡异事件分析专车
最后
师长,【java进阶架构师】号主,短短一年在各大平台斩获15W+程序员关注,专注分享Java进阶、架构技术、高并发、微服务、BAT面试、redis专题、JVM调优、Springboot源码、mysql优化等20大进阶架构专题。
转载说明:请务必注明来源(本文首发于公众号:【java进阶架构师】)