SpringBoot原理探究——各种类型参数请求原理

探究springBoot是如何去解析获取各种类型参数请求的原理

[1]测试请求地址:http://localhost:8080/car/5/owner/6

对应的控制器代码

@RestController
public class TestController {
    @GetMapping("/car/{id}/owner/{username}")
    public Map<String, Object> test(@PathVariable("id") String id,
                          @PathVariable("username") String username) {
        Map<String, Object> map = new HashMap();
        //返回请求路径中的参数
         map.put("id", id);
        map.put("username", username);
        return map;
    }
}

[2]打断点{启动debug调试}

通过全局搜索{ps:快捷键是按两下shift} 查询DispatcherServlet整个类

{ps:DispatcherServlet相当于一个分发器(就是一个Servlet)}

  找到doDispatch方法{ps:该方法就相当与做一个调度}

记得打上断点{在WebAsyncManager-Web异步管理器这里(主要用来管理异步请求的处理。)}

[3]开始启动调试

启动程序

 输入网址

[4]获得执行程序执行链(关于如何映射到方法的)

 {ps:所有的映射地址对应的方法都在这个mappingRegistry注册中心当中}

[5]核心部分--处理器的适配器

①HandlerAdapter

 getHandlerAdapter方法

  • 0 - 支持方法上标注@RequestMapping
  • 1 - 支持函数式编程
  • ...

适配器判断(通过判断当前传入的是否是Handler类型,来判断是否支持适配器)

最后为其找个一个适配器 RequestMappingHandlerAdapter

②执行目标方法

 查看内部处理细节(进入RequestMappingHandlerAdapter)

RequestMappingHandlerAdapter-开始执行目标方法了

进入invokeHandlerMethod中查看目标方法如何执行的

我们会发现在可执行方法invocableMethod中设置了一个参数解析器

参数解析器-HandlerMethodArgumentResolver

HandlerMethodArgumentResolver参数解析器核心如下

确定将要执行的目标方法的每一个参数的值是什么;

SpringMVC目标方法能写多少种参数类型。取决于参数解析器。

HandlerMethodArgumentResolver接口的中的两个方法如下

  • supportsParameter判断当前解析器是否支持这种参数
  • 支持就调用解析方法resolveArgument

返回值处理器-HandlerMethodReturnValueHandler

RequestMappingHandlerAdapter-真正执行目标执行方法

如何确定目标方法每一个参数的值(核心代码如下)
============InvocableHandlerMethod==========================
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
    MethodParameter[] parameters = this.getMethodParameters();
    if (ObjectUtils.isEmpty(parameters)) {
        return EMPTY_ARGS;
    } else {
        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) {
                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 var10) {
                    if (logger.isDebugEnabled()) {
                        String exMsg = var10.getMessage();
                        if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
                            logger.debug(formatArgumentError(parameter, exMsg));
                        }
                    }

                    throw var10;
                }
            }
        }

        return args;
    }
}
挨个判断所有参数解析器哪个支持解析找个参数
PS:在得到参数解析器是会先找缓存
===================HandlerMethodArgumentResolverComposite==========================
@Nullable
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
    HandlerMethodArgumentResolver result = (HandlerMethodArgumentResolver)this.argumentResolverCache.get(parameter);
    if (result == null) {
        Iterator var3 = this.argumentResolvers.iterator();

        while(var3.hasNext()) {
            HandlerMethodArgumentResolver resolver = (HandlerMethodArgumentResolver)var3.next();
            if (resolver.supportsParameter(parameter)) {
                result = resolver;
                this.argumentResolverCache.put(parameter, resolver);
                break;
            }
        }
    }

    return result;
}
解析找个参数的值

调用各自 HandlerMethodArgumentResolver 的 resolveArgument 方法即可

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值