若是這是你第二次看到師長,說明你在覬覦個人美色!java
點贊+關注再看,養成習慣mysql
沒別的意思,就是須要你的窺屏^_^ios
該趟專車是開往Spring Boot請求處理源碼分析專車,主要用來分析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請求,接下里咱們會結合示例進行源碼分析web
這次分析主要從2個大的方面進行分析:請求初始化、請求處理面試
一次完成的請求流程就是請求--->處理--->響應,業務邏輯處理最終交由咱們建立的Servlet來進行處理。之前在使用Spring MVC框架的時候,咱們都會在web.xml中配置一個DispathcherServlet。接下來就讓咱們來看看DispathcherServlet的類圖
redis
從如上圖能夠清晰的看到DispatcherServlet的繼承關係。其中一個名爲HttpServlet的類,若是寫過Servlet的應該都比較的熟悉,以往基於Servlet開發,都會建立一個Servlet實現類,繼承HttpServlet並重寫service方法,最後在web.xml中配置咱們咱們建立的Servlet實現類,這樣咱們就能夠使用建立的Servlet實現類來處理咱們的web請求了。sql
在咱們第一次請求的時候會進行Servlet的初始化,主要用來初始化資源。HttpServlet的init方法由父類GenericServlet聲明,由子類HttpServletBean實現。session
初始化方法:HttpServletBean#initmysql優化
@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的聲明
@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對象建立初始化就結束了
建立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; }
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); } }
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
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. // 一、獲取handler mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. // 二、獲取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); } } } }
一次請求原理以下:
若是是基於微服務開發,那麼該如何定義咱們的服務?
定義微服務接口:
@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進階架構師】)