各种注解类型参数解析原理

从以前的文章中可以知道,在请求进行处理的过程中,要一步步的找到对应的handler,具体的过程见下面的这篇文章。找到handler是找到当前的请求会调用哪个方法。
找到handler的过程
在找到哪个handler处理该请求后,要找一个处理器的适配器。 RequestMappingHandlerAdapter。
在这里插入图片描述
在这里插入图片描述
第一个处理器适配器是支持方法上标注@requestMapping注解的。
第二个是支持函数式编程的。
第三个和第四个是支持其他的。
在这里插入图片描述
下面是看当前的处理器适配器支不支持处理该handler。
在这里插入图片描述
在这里插入图片描述
判断生效
在这里插入图片描述
因此会得到第一个处理器适配器。
然后判断是不是get方法和head,是不是浏览器缓存,然后调用处理器适配器的handle方法进行处理。
在这里插入图片描述
然后调用handleInternal()。
在这里插入图片描述
然后回到了RequestMappingHandlerAdapter这个类里面。
在这里插入图片描述
然后调用这个类里面的invokeHandlerMethod方法。翻译过来是执行处理器方法。
在这里插入图片描述
进入到这个方法中。
在这里插入图片描述
argumentResolvers的意思是参数解析器,在这个类中,会根据参数的类型配置相应的参数解析器。
在这里插入图片描述
一共是27个参数解析器。
参数解析器由两个接口组成。
在这里插入图片描述
因此分为两步,第一步是判断当前的解析器能不能够解析当前的参数,第二步是进行解析。
returnValueHandlers代表的是返回值处理器,也就是说能够处理多少中返回值,一共15种。
在这里插入图片描述
springboot会将这些参数解析器和返回值处理器封装到invocableMethod中。
在这里插入图片描述
然后来到下面的这个方法。
在这里插入图片描述
然后来到下面的这个方法。
在这里插入图片描述
上面的方法是执行请求,下面的这个方法是得到请求中参数的值。
在这里插入图片描述
保存在args这个数组中。
在这里插入图片描述
那么参数的值是如何确定的哪?进入上面的这个方法,具体的过程是下面的这段java代码。

============InvocableHandlerMethod==========================
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;
                    }
                }

从上面的这段代码中我们可以看出来,首先是得到方法的参数数组,然后判断方法的参数数组是否为空,不为空则创建一个和参数数组一样大的数组,然后挨个遍历参数数组,找到合适的参数解析器。

if (!this.resolvers.supportsParameter(parameter)) 

上面的这个代码是判断当前的26个参数解析器是否可以解析当前的参数,进入上面的代码。
在这里插入图片描述
再进入。
在这里插入图片描述
从上面的代码可以看出来while循环是判断26个参数解析器是否可以解析当前的参数,以及哪个可以解析当前参数,并且将参数解析器放到缓存中,当次下一次使用的过程中便会非常的快。
当判断完支持后,便开始进行解析参数。
在这里插入图片描述
深入上面的代码,会进入下面的代码。
在这里插入图片描述
解析器会调用resolveArgument方法,进入这个方法。
上面的这行代码是得到参数的名字。
在这里插入图片描述
在这里插入图片描述
下面的这一行是解析参数的值
在这里插入图片描述
具体过程进入上面的函数,就是下面的方法。
在这里插入图片描述
先进行一个判断,然后将再urlpathhelper中存储的值放到其中,这就是解析参数的值。
在这里插入图片描述

在这里插入图片描述
然后进行上面的遍历循环,看哪个解析器可以解析当前的参数,然后进行解析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值