SpringBoot中接口调用流程是如何详细解析的?
- 内容介绍
- 文章标签
- 相关推荐
本文共计2030个文字,预计阅读时间需要9分钟。
本文主要通过调试方法分析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 的 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的`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 的 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将返回值写入响应对象中。

