SpringBoot核心技术-Web开发-请求参数解析原理

SpringBoot核心技术-Web开发-请求参数解析原理,第1张

SpringBoot核心技术-Web开发-请求参数解析原理
  • HandlerMapping中找到能处理请求的Handler(Controller.method())
  • 为当前Handler 找一个适配器 HandlerAdapter; RequestMappingHandlerAdapter
  • 适配器执行目标方法并确定方法参数的每一个值 
1、HandlerAdapter

第一个:支持方法上标注的@RequestMapping

第二个:支持函数式编程

.....

2、执行目标方法 2.1 DispatcherServlet -- doDispatch
// Actually invoke the handler.
//DispatcherServlet -- doDispatch
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
2.2 RequestMappingHandlerAdapter--handleInternal
=====RequestMappingHandlerAdapter类中的handleInternal方法==========
mav = invokeHandlerMethod(request, response, handlerMethod); //执行目标方法

=====invokeHandlerMethod的关键代码===========================
if (this.argumentResolvers != null) {//设置参数解析器
     invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
if (this.returnValueHandlers != null) {//设置返回值处理器
                        
     invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]);

设置参数解析器:

参数解析器:确定将要执行的目标方法的每个参数的值是什么

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

 supportParameter:当前解析器是否支持这种参数

支持就调用resolveArgument

设置返回值处理器:

 2.3 invokeAndHandle

invocableMethod为ServletInvocableHandlerMethod对象

invokeForRequest:真正执行目标方法

=====ServletInvocableHandlerMethod中invokeAndHandle方法中的核心代码==============
Object returnValue = this.invokeForRequest(webRequest, mavContainer, providedArgs);
this.setResponseStatus(webRequest);
2.4 invokeForRequest
=====invokeForRequest方法=====
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
        //获取方法参数所有的值
        Object[] args = this.getMethodArgumentValues(request, mavContainer, providedArgs);
        if (logger.isTraceEnabled()) {
            logger.trace("Arguments: " + Arrays.toString(args));
        }
        //反射执行Controller中的方法
        return this.doInvoke(args);
    }
2.5  getMethodArgumentValues:确定每个参数的值

上一步获取参数值的具体代码

============InvocableHandlerMethod类==========================
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {

		MethodParameter[] parameters = getMethodParameters();
		if (ObjectUtils.isEmpty(parameters)) {
			return EMPTY_ARGS;
		}
        
        //核心代码,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;
			}
            //1、遍历26个参数解析器是否支持parameter类型的参数
			if (!this.resolvers.supportsParameter(parameter)) {
				throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
			}
			try {
                //2、开始解析参数值
				args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
			}
			catch (Exception ex) {
				// Leave stack trace for later, exception may actually be resolved and handled...
				if (logger.isDebugEnabled()) {
					String exMsg = ex.getMessage();
					if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
						logger.debug(formatArgumentError(parameter, exMsg));
					}
				}
				throw ex;
			}
		}
		return args;
	}

 上图代码的细节:

2.5.1 判断所有参数解析器是否支持当前参数

找到能解析的解析器,加入缓存,方便下一步解析该参数时直接获取。

======if (!this.resolvers.supportsParameter(parameter))底层实现=====	
@Nullable
	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;
	}
 2.5.2  解析参数的值

解析请求的值给到参数。

======args[i] = this.resolvers.resolveArgument======
 public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
        HandlerMethodArgumentResolver resolver = this.getArgumentResolver(parameter);
        if (resolver == null) {
            throw new IllegalArgumentException("Unsupported parameter type [" + parameter.getParameterType().getName() + "]. supportsParameter should be called first.");
        } else {
            return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
        }
    }

=====最终调用AbstractNamedValueMethodArgumentResolver的resolveArgument方法=====

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4828562.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-10
下一篇 2022-11-10

发表评论

登录后才能评论

评论列表(0条)

保存