SpringBoot中接口调用流程是如何详细解析的?

2026-05-22 09:082阅读0评论SEO教程
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2030个文字,预计阅读时间需要9分钟。

SpringBoot中接口调用流程是如何详细解析的?

本文主要通过调试方法分析SpringBoot接口方法的大致调用过程,从调用流程层面简要地分析源码,不进行深入解读。

本文使用SpringBoot的`2.2.2.RELEASE`版本。

调试方法概述

在SpringBoot中,调试接口方法的主要方法是通过设置断点和使用调试工具。以下是一些常用的调试方法:

1. 设置断点:在IDE中,可以在代码中设置断点,当程序运行到断点位置时,程序将暂停执行,以便进行调试。

2.打印日志:在代码中添加日志输出,可以实时查看程序的执行过程。

3.使用调试工具:如Spring Boot DevTools,可以提供热部署、自动重启等功能,方便调试。

接口方法调用过程

以下是一个简单的接口方法调用过程:

1. 请求到达:客户端发起请求,请求被发送到SpringBoot应用。

2.路由匹配:SpringBoot的DispatcherServlet根据请求的URL和请求方法,找到对应的Controller。

3.执行方法:Controller中的方法被调用,处理请求并返回响应。

4.响应返回:响应被发送回客户端。

调用流程分析

以下是从调用流程层面简要分析源码:

1. DispatcherServlet:SpringBoot中的前端控制器,负责处理所有请求。

2.HandlerMapping:根据请求信息,找到对应的Controller。

3.HandlerAdapter:适配器,负责调用Controller中的方法。

4.Controller:处理请求的类,包含具体的业务逻辑。

5.ModelAndView:封装视图和模型数据的对象,用于生成响应。

总结

本文简要介绍了SpringBoot接口方法的调试方法,并从调用流程层面分析了源码。希望对您有所帮助。

SpringBoot中接口调用流程是如何详细解析的?

本文主要通过调试的方法来分析 SpringBoot 接口方法的大致调用过程,从调用流程层面简单地分析下源码,不进行深入解读。此外,本文调试使用的是 SpringBoot 的 `2.2.2.RELEASE` 版本。 前言

本文主要通过调试的方法来分析 SpringBoot 接口方法的大致调用过程,从调用流程层面简单地分析下源码,不进行深入解读。此外,本文调试使用的是 SpringBoot 的 2.2.2.RELEASE 版本。

调用流程

SpringBoot 接口方法的调用流程主要分为四部分:请求分发、映射处理器、调用处理器方法。下面具体分析大致工作流程。

请求分发

每当 SpringBoot 收到接口请求后,首先就是进入 Tomcat 的DispatcherServlet#doService方法,通过doDispatch进行请求分发。

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { // set attribute to request try { doDispatch(request, response); } finally { } } 映射处理器

请求分发的第一步就是映射处理器。通过getHandler方法遍历handlerMappings,通过HandlerMapping获取请求处理器。对于当前接口请求采用的是RequestMappingHandlerMapping。拿到处理器对象后,就可以调用接口方法。

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); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); } catch (Exception ex) { dispatchException = ex; } } } 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; }

handlerMappings中默认支持5个映射器,它们都是在项目启动时生成的。

调用处理器方法

调用处理器对象时,首先会将处理器对象强转为处理器方法对象HandlerMethod。接着,调用请求处理器方法。通过断点深入发现,主要工作流程如下:

ServletInvocableHandlerMethod#invokeAndHandle -> InvocableHandlerMethod#invokeForRequest

在ServletInvocableHandlerMethod中通过invokeAndHandle调用处理器方法,获取返回值写入response。其中,又会调用父类InvocableHandlerMethod的invokeForRequest。在invokeForRequest中去获取请求的参数列表。

获取参数列表

通过断点深入发现,获取请求参数列表是通过InvocableHandlerMethod#invokeForRequest

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); }

在getMethodArgumentValues中,会遍历每一个参数,尝试获取解析器进行解析。

protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { MethodParameter[] parameters = getMethodParameters(); if (ObjectUtils.isEmpty(parameters)) { return EMPTY_ARGS; } Object[] args = new Object[parameters.length]; for (int i = 0; i < parameters.length; i++) { MethodParameter parameter = parameters[i]; parameter.initParameterNameDiscovery(this.parameterNameDiscoverer); args[i] = findProvidedArgument(parameter, providedArgs); if (args[i] != null) { continue; } if (!this.resolvers.supportsParameter(parameter)) { throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver")); } try { // 解析每一个参数 args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory); } catch (Exception ex) { throw ex; } } return args; }

参数的解析是通过遍历上下文的argumentResolvers来获取支持的解析器,并将解析器缓存,这样后面的参数解析器就可以直接从缓存中获取。

public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { // 获取解析器 HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); if (resolver == null) { throw new IllegalArgumentException("Unsupported parameter type [" + parameter.getParameterType().getName() + "]. supportsParameter should be called first."); } // 解析参数 return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory); } private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) { HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter); if (result == null) { // 获取支持的解析器,并写入缓存 for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) { if (resolver.supportsParameter(parameter)) { result = resolver; this.argumentResolverCache.put(parameter, result); break; } } } return result; }

默认的26个参数解析器如下,本次请求采用的是RequestResponseBodyMethodProcessor解析器。

获取解析器之后,下面就是对参数进行解析。参数的解析通过MessageConverter将文本解析成相应的参数对象。

public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { parameter = parameter.nestedIfOptional(); // 读取MessageConverter解析结果 Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType()); String name = Conventions.getVariableNameForParameter(parameter); return adaptArgumentIfNecessary(arg, parameter); }

总结而言,参数的解析流程就是遍历每一个参数,获取合适的解析器对参数进行解析。程序会缓存参数和对应的解析器,而具体的解析细节依赖MessageConverter来实现。

调用处理器方法

protected Object doInvoke(Object... args) throws Exception { ReflectionUtils.makeAccessible(getBridgedMethod()); try { // 调用处理器方法 return getBridgedMethod().invoke(getBean(), args); } catch (IllegalArgumentException ex) { } } 获取返回结果

获取返回结果首先会解析返回值的类型,通过遍历上下文中的returnValueHandlers获取支持的返回值处理器。

private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) { boolean isAsyncValue = isAsyncReturnValue(value, returnType); for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) { if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) { continue; } if (handler.supportsReturnType(returnType)) { return handler; } } return null; }

默认支持的返回值处理器如下:

拿到返回值处理器后,调用handleReturnValue方法将返回结果写入响应对象中,写入细节还是依赖MessageConverter支持。

// handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest); public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException { mavContainer.setRequestHandled(true); ServletServerHttpRequest inputMessage = createInputMessage(webRequest); ServletServerHttpResponse outputMessage = createOutputMessage(webRequest); // Try even with null return value. ResponseBodyAdvice could get involved. writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage); }

总结而言,获取返回结果的工作流程是获取合适的返回值处理器,然后调用返回值处理器方法,将结果通过MessageConverter写入到响应对象中。

总结

以上介绍了 SpringBoot 接口方法的大致工作流程:
1、Servlet接口分发
2、映射处理器方法
获取上下文的HandlerMapping,根据请求参数映射处理器方法。
3、调用处理器方法
(1)通过上下文的参数解析器解析参数,具体解析细节依赖MessageConverter。
(2)调用处理器方法引用调用方法。
(3)通过上下文的返回结果处理器处理返回值,依赖MessageConverter将返回值写入响应对象中。

本文共计2030个文字,预计阅读时间需要9分钟。

SpringBoot中接口调用流程是如何详细解析的?

本文主要通过调试方法分析SpringBoot接口方法的大致调用过程,从调用流程层面简要地分析源码,不进行深入解读。

本文使用SpringBoot的`2.2.2.RELEASE`版本。

调试方法概述

在SpringBoot中,调试接口方法的主要方法是通过设置断点和使用调试工具。以下是一些常用的调试方法:

1. 设置断点:在IDE中,可以在代码中设置断点,当程序运行到断点位置时,程序将暂停执行,以便进行调试。

2.打印日志:在代码中添加日志输出,可以实时查看程序的执行过程。

3.使用调试工具:如Spring Boot DevTools,可以提供热部署、自动重启等功能,方便调试。

接口方法调用过程

以下是一个简单的接口方法调用过程:

1. 请求到达:客户端发起请求,请求被发送到SpringBoot应用。

2.路由匹配:SpringBoot的DispatcherServlet根据请求的URL和请求方法,找到对应的Controller。

3.执行方法:Controller中的方法被调用,处理请求并返回响应。

4.响应返回:响应被发送回客户端。

调用流程分析

以下是从调用流程层面简要分析源码:

1. DispatcherServlet:SpringBoot中的前端控制器,负责处理所有请求。

2.HandlerMapping:根据请求信息,找到对应的Controller。

3.HandlerAdapter:适配器,负责调用Controller中的方法。

4.Controller:处理请求的类,包含具体的业务逻辑。

5.ModelAndView:封装视图和模型数据的对象,用于生成响应。

总结

本文简要介绍了SpringBoot接口方法的调试方法,并从调用流程层面分析了源码。希望对您有所帮助。

SpringBoot中接口调用流程是如何详细解析的?

本文主要通过调试的方法来分析 SpringBoot 接口方法的大致调用过程,从调用流程层面简单地分析下源码,不进行深入解读。此外,本文调试使用的是 SpringBoot 的 `2.2.2.RELEASE` 版本。 前言

本文主要通过调试的方法来分析 SpringBoot 接口方法的大致调用过程,从调用流程层面简单地分析下源码,不进行深入解读。此外,本文调试使用的是 SpringBoot 的 2.2.2.RELEASE 版本。

调用流程

SpringBoot 接口方法的调用流程主要分为四部分:请求分发、映射处理器、调用处理器方法。下面具体分析大致工作流程。

请求分发

每当 SpringBoot 收到接口请求后,首先就是进入 Tomcat 的DispatcherServlet#doService方法,通过doDispatch进行请求分发。

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { // set attribute to request try { doDispatch(request, response); } finally { } } 映射处理器

请求分发的第一步就是映射处理器。通过getHandler方法遍历handlerMappings,通过HandlerMapping获取请求处理器。对于当前接口请求采用的是RequestMappingHandlerMapping。拿到处理器对象后,就可以调用接口方法。

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); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); } catch (Exception ex) { dispatchException = ex; } } } 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; }

handlerMappings中默认支持5个映射器,它们都是在项目启动时生成的。

调用处理器方法

调用处理器对象时,首先会将处理器对象强转为处理器方法对象HandlerMethod。接着,调用请求处理器方法。通过断点深入发现,主要工作流程如下:

ServletInvocableHandlerMethod#invokeAndHandle -> InvocableHandlerMethod#invokeForRequest

在ServletInvocableHandlerMethod中通过invokeAndHandle调用处理器方法,获取返回值写入response。其中,又会调用父类InvocableHandlerMethod的invokeForRequest。在invokeForRequest中去获取请求的参数列表。

获取参数列表

通过断点深入发现,获取请求参数列表是通过InvocableHandlerMethod#invokeForRequest

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); }

在getMethodArgumentValues中,会遍历每一个参数,尝试获取解析器进行解析。

protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { MethodParameter[] parameters = getMethodParameters(); if (ObjectUtils.isEmpty(parameters)) { return EMPTY_ARGS; } Object[] args = new Object[parameters.length]; for (int i = 0; i < parameters.length; i++) { MethodParameter parameter = parameters[i]; parameter.initParameterNameDiscovery(this.parameterNameDiscoverer); args[i] = findProvidedArgument(parameter, providedArgs); if (args[i] != null) { continue; } if (!this.resolvers.supportsParameter(parameter)) { throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver")); } try { // 解析每一个参数 args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory); } catch (Exception ex) { throw ex; } } return args; }

参数的解析是通过遍历上下文的argumentResolvers来获取支持的解析器,并将解析器缓存,这样后面的参数解析器就可以直接从缓存中获取。

public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { // 获取解析器 HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); if (resolver == null) { throw new IllegalArgumentException("Unsupported parameter type [" + parameter.getParameterType().getName() + "]. supportsParameter should be called first."); } // 解析参数 return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory); } private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) { HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter); if (result == null) { // 获取支持的解析器,并写入缓存 for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) { if (resolver.supportsParameter(parameter)) { result = resolver; this.argumentResolverCache.put(parameter, result); break; } } } return result; }

默认的26个参数解析器如下,本次请求采用的是RequestResponseBodyMethodProcessor解析器。

获取解析器之后,下面就是对参数进行解析。参数的解析通过MessageConverter将文本解析成相应的参数对象。

public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { parameter = parameter.nestedIfOptional(); // 读取MessageConverter解析结果 Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType()); String name = Conventions.getVariableNameForParameter(parameter); return adaptArgumentIfNecessary(arg, parameter); }

总结而言,参数的解析流程就是遍历每一个参数,获取合适的解析器对参数进行解析。程序会缓存参数和对应的解析器,而具体的解析细节依赖MessageConverter来实现。

调用处理器方法

protected Object doInvoke(Object... args) throws Exception { ReflectionUtils.makeAccessible(getBridgedMethod()); try { // 调用处理器方法 return getBridgedMethod().invoke(getBean(), args); } catch (IllegalArgumentException ex) { } } 获取返回结果

获取返回结果首先会解析返回值的类型,通过遍历上下文中的returnValueHandlers获取支持的返回值处理器。

private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) { boolean isAsyncValue = isAsyncReturnValue(value, returnType); for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) { if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) { continue; } if (handler.supportsReturnType(returnType)) { return handler; } } return null; }

默认支持的返回值处理器如下:

拿到返回值处理器后,调用handleReturnValue方法将返回结果写入响应对象中,写入细节还是依赖MessageConverter支持。

// handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest); public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException { mavContainer.setRequestHandled(true); ServletServerHttpRequest inputMessage = createInputMessage(webRequest); ServletServerHttpResponse outputMessage = createOutputMessage(webRequest); // Try even with null return value. ResponseBodyAdvice could get involved. writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage); }

总结而言,获取返回结果的工作流程是获取合适的返回值处理器,然后调用返回值处理器方法,将结果通过MessageConverter写入到响应对象中。

总结

以上介绍了 SpringBoot 接口方法的大致工作流程:
1、Servlet接口分发
2、映射处理器方法
获取上下文的HandlerMapping,根据请求参数映射处理器方法。
3、调用处理器方法
(1)通过上下文的参数解析器解析参数,具体解析细节依赖MessageConverter。
(2)调用处理器方法引用调用方法。
(3)通过上下文的返回结果处理器处理返回值,依赖MessageConverter将返回值写入响应对象中。