Springbootの10番目のカスタムオブジェクトパラメータ

カスタムカプセル化されたオブジェクト

ここに画像の説明を挿入

ここに画像の説明を挿入

ここに画像の説明を挿入

ここに画像の説明を挿入

ページによって送信されたリクエストデータがカスタムオブジェクトにカプセル化されているのはなぜですか?

カスタムオブジェクトはこれによって処理され、
ここに画像の説明を挿入
ここに画像の説明を挿入
カスタムオブジェクトはカプセル化され
ここに画像の説明を挿入
、単純なデータ型であるかどうかを判断します。

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));
	}

カスタムタイプのカプセル化のコアはここにあります

@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();
				}
				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バインダー=binderFactory.createBinder(webRequest、属性、名前);

このバインダーを見てみましょう
ここに画像の説明を挿入

ここに画像の説明を挿入
これがデータを置くために作成されたオブジェクトです。
ここに画像の説明を挿入
私たちはすべてhttpから送信されます。つまり、送信されるデータはすべてString型です。
これがコンバーターです。
ここに画像の説明を挿入

ここに画像の説明を挿入
ここには124個のコンバーターがあることがわかります。たとえば、選択したのはStringをEnumに変換する
ここに画像の説明を挿入
ことであり、StringをObjectに変換することもできます。
ここに画像の説明を挿入


次のボックスは、受信したリクエスト文字列データを、 String into Integerなど、指定したオブジェクトのデータ型に変換する役割を果たします。
ここに画像の説明を挿入

このステップのバインダーは、オブジェクトとネイティブリクエストを配置するために作成したものです。

ここに画像の説明を挿入
このステップの後、データ
をバインドしました。これは、リフレクション呼び出しメソッドを介してデータの値をバインドすることです。
ここに画像の説明を挿入
カプセル化プロセスが使用されます。ServletModelAttributeMethodProcessor

public class ServletModelAttributeMethodProcessor extends ModelAttributeMethodProcessor {
    
    
	
    @Override//本方法在ModelAttributeMethodProcessor类,
	public boolean supportsParameter(MethodParameter parameter) {
    
    
		return (parameter.hasParameterAnnotation(ModelAttribute.class) ||
				(this.annotationNotRequired && !BeanUtils.isSimpleProperty(parameter.getParameterType())));
	}

	@Override
	@Nullable//本方法在ModelAttributeMethodProcessor类,
	public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
    
    

		...

		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 (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)) {
    
    
                    //web数据绑定器,将请求参数的值绑定到指定的JavaBean里面**
					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:Webデータ・バインダーは、要求パラメーターの値を指定されたJavaBeanにバインドします

WebDataBinderは、その中のコンバーターを使用して、要求データを指定されたデータ型に変換します。再びJavaBeanにカプセル化

GenericConversionService:各値を設定するときに、このデータ型(要求によってもたらされたパラメーターを含む文字列)を指定された型(JavaBean-整数)に変換できるすべてのコンバーターを検索します。

カスタムコンバーターの原理

ここに画像の説明を挿入

カスタムパーサーを分離するために使用します

 @Bean
    public WebMvcConfigurer webMvcConfigurer(){
    
    
        return new WebMvcConfigurer() {
    
    

            @Override
            public void addFormatters(FormatterRegistry registry) {
    
    
                registry.addConverter(new Converter<String, Pet>() {
    
    

                    @Override
                    public Pet convert(String source) {
    
    
                        if(!StringUtils.isEmpty(source)){
    
    
                            Pet pat = new Pet();
                            String [] split = source.split(",");
                            pat.setName(split[0]);
                            pat.setAge(String.valueOf(Integer.valueOf(split[1])));
                            return pat;
                        }
                        return null;
                    }
                });
            }
        };
    }

パーサーを調べたところ、125は元々カスタムパーサーの124であり、ここに配置しました。
ここに画像の説明を挿入

ここに画像の説明を挿入
ここでそれを裏返し
ここに画像の説明を挿入
、送ります
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/qq_47431361/article/details/123754249