SpingBoot 自定义对象参数处理

源码基于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);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值