源码基于SpingBoot 2.6.7
首先web项目的请求会DispatcherServle类,所以从这个类开始直接上代码
DispatcherServle > doDispatch() > mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
AbstractHandlerMethodAdapter > handle() > return handleInternal(request, response, (HandlerMethod) handler);
// 执行目标方法
RequestMappingHandlerAdapter > handleInternal() > mav = invokeHandlerMethod(request, response, handlerMethod);
RequestMappingHandlerAdapter > invokeHandlerMethod() > invocableMethod.invokeAndHandle(webRequest, mavContainer);
ServletInvocableHandlerMethod > invokeAndHandle() > Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
InvocableHandlerMethod > invokeForRequest() > Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
InvocableHandlerMethod > getMethodArgumentValues() > this.resolvers.supportsParameter(parameter)
HandlerMethodArgumentResolverComposite > supportsParameter() > return getArgumentResolver(parameter) != null;
HandlerMethodArgumentResolverComposite > getArgumentResolver() > resolver.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;
}
ModelAttributeMethodProcessor > supportsParameter() > BeanUtils.isSimpleProperty(parameter.getParameterType())
BeanUtils > isSimpleProperty() return isSimpleValueType(type) || type.isArray() && isSimpleValueType(type.getComponentType());
// 如果不是简单类型
// 确定为 ServletModelAttributeMethodProcessor 这个参数解析器
public static boolean isSimpleValueType(Class<?> type) {
return (Void.class != type && void.class != type &&
(ClassUtils.isPrimitiveOrWrapper(type) ||
Enum.class.isAssignableFrom(type) ||
CharSequence.class.isAssignableFrom(type) ||
Number.class.isAssignableFrom(type) ||
Date.class.isAssignableFrom(type) ||
Temporal.class.isAssignableFrom(type) ||
URI.class == type ||
URL.class == type ||
Locale.class == type ||
Class.class == type));
}
InvocableHandlerMethod > getMethodArgumentValues() > args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
HandlerMethodArgumentResolverComposite > resolveArgument() > return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
ModelAttributeMethodProcessor > resolveArgument
// 核心方法解析这个参数的值
@Override
@Nullable
public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
Assert.state(mavContainer != null, "ModelAttributeMethodProcessor requires ModelAndViewContainer");
Assert.state(binderFactory != null, "ModelAttributeMethodProcessor requires WebDataBinderFactory");
String name = ModelFactory.getNameForParameter(parameter);
ModelAttribute ann = parameter.getParameterAnnotation(ModelAttribute.class);
if (ann != null) {
mavContainer.setBinding(name, ann.binding());
}
Object attribute = null;
BindingResult bindingResult = null;
if (mavContainer.containsAttribute(name)) {
attribute = mavContainer.getModel().get(name);
}
else {
// Create attribute instance
try {
attribute = createAttribute(name, parameter, binderFactory, webRequest);
}
catch (BindException ex) {
if (isBindExceptionRequired(parameter)) {
// No BindingResult parameter -> fail with BindException
throw ex;
}
// Otherwise, expose null/empty value and associated BindingResult
if (parameter.getParameterType() == Optional.class) {
attribute = Optional.empty();
}
else {
attribute = ex.getTarget();
}
bindingResult = ex.getBindingResult();
}
}
if (bindingResult == null) {
// Bean property binding and validation;
// skipped in case of binding failure on construction.
WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);
if (binder.getTarget() != null) {
if (!mavContainer.isBindingDisabled(name)) {
bindRequestParameters(binder, webRequest);
}
validateIfApplicable(binder, parameter);
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
throw new BindException(binder.getBindingResult());
}
}
// Value type adaptation, also covering java.util.Optional
if (!parameter.getParameterType().isInstance(attribute)) {
attribute = binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter);
}
bindingResult = binder.getBindingResult();
}
// Add resolved attribute and BindingResult at the end of the model
Map<String, Object> bindingResultModel = bindingResult.getModel();
mavContainer.removeAttributes(bindingResultModel);
mavContainer.addAllAttributes(bindingResultModel);
return attribute;
}
// WebDataBinder
> WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);
// 创建空的自定义类型参数
DefaultDataBinderFactory > createBinder() > WebDataBinder dataBinder = createBinderInstance(target, objectName, webRequest);
// 找到转化器 GenericConversionService:在设置每一个值的时候,找它里面的所有converter那个可以将这个数据类型(request带来参数)转换到指定的类型(如String 转 Integer)
> this.initializer.initBinder(dataBinder, webRequest);
> bindRequestParameters(binder, webRequest);
ServletModelAttributeMethodProcessor > bindRequestParameters() > servletBinder.bind(servletRequest);
ServletRequestDataBinder > bind() > addBindValues(mpvs, request);