005java进阶案例_【原创】005 | 搭上SpringBoot请求处理源码分析专车

【原创】005 | 搭上SpringBoot请求处理源码分析专车

发车啦,发车啦,上车要求:

点击左上方的“java进阶架构师”进入页面

选择右上角的“星标公众号”上车!

c63f21ce1bdb1f5f4f6c84dd62e524c6.png

专车介绍

该趟专车是开往Spring Boot请求处理源码分析专车,主要用来分析Spring Boot是如何将我们的请求路由到指定的控制器方法以及调用执行。

专车问题

为什么我们在控制器中添加一个方法,使用@RequestMapping注解标注,指定一个路径,就可以用来处理一个web请求?

如果多个方法的请求路径一致,Spring Boot是如何处理的?

专车示例

@RestController

@RequestMapping("/persons")

public class PersonController {

private static List 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 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的类图

50bb44f5d73daddb4471906e621915ad.png

从如上图可以清晰的看到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 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}.

private final WebMvcProperties mvcProperties;

private final ListableBeanFactory beanFactory;

private final WebMvcRegistrations mvcRegistrations;

public EnableWebMvcConfiguration(

ObjectProvider mvcPropertiesProvider,

ObjectProvider mvcRegistrationsProvider,

ListableBeanFactory beanFactory) {

this.mvcProperties = mvcPropertiesProvider.getIfAvailable();

this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique();

this.beanFactory = beanFactory;

}

> 在如上代码中可以看到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 methods = MethodIntrospector.selectMethods(userType,

(MethodIntrospector.MetadataLookup) 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 methods = MethodIntrospector.selectMethods(userType,

(MethodIntrospector.MetadataLookup) 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 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();

}

}

所有方法遍历完成后的结果如下:

3f3468b2ae6103b16153367452cf0ac2.png

到此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分析的结果

c2442401669dabfe26587907ec3eeb61.png

@Nullable

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {

List matches = new ArrayList<>();

// 从urlLookup属性中找到当前请求路径对应的RequestMappingInfo信息

// 假设请求的路径为/persons/,那么此处得到的结果有3个

List 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 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 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 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 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事务诡异事件分析专车

———— e n d ————

微服务、高并发、JVM调优、面试专栏等20大进阶架构师专题请关注公众号【Java进阶架构师】后在菜单栏查看。

看到这里,说明你喜欢本文

你的转发,是对我最大的鼓励!在看亦是支持↓

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值