springboot 第十期 自定义对象参数

自定义封装的对象

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

为什么页面提交的请求数据会被封装到我们的自定义对象里面?

我们的自定义对象是被这个处理的
在这里插入图片描述
在这里插入图片描述
我们的自定义对象就是用它来封装的
在这里插入图片描述
这里面会判断是不是简单的数据类型

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 binder = binderFactory.createBinder(webRequest, attribute, name);

我们看一下这个 binder
在这里插入图片描述

在这里插入图片描述
这里就是创建的用来放数据的对象
在这里插入图片描述
我们传过来的都是http传过来的 也就是传来的都是String类型的
这个就是我们的转换器
在这里插入图片描述

在这里插入图片描述
我们看这里有124个转换器 比如我们选定的这个就是把 String给转换成Enum的
在这里插入图片描述
这还有String转成Object的
在这里插入图片描述

下面的框是负责把接收到的request字符串数据转换成我们指定的对象里面的数据的类型
比如 String 转换成 Integer
在这里插入图片描述

这一步 这里面的 binder 是我们创建好的放我们对象 还有原生的请求

在这里插入图片描述
我们经过了这一步 我们就绑定好了数据
里面就是通过反射调用方法 绑定我们数据里面带的值
在这里插入图片描述
封装过程用到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 利用它里面的 Converters 将请求数据转成指定的数据类型。再次封装到JavaBean中

GenericConversionService:在设置每一个值的时候,找它里面的所有converter那个可以将这个数据类型(request带来参数的字符串)转换到指定的类型(JavaBean – Integer)

自定义Converter原理

在这里插入图片描述
我们用 , 来间隔
我们自定义一个解析器

 @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个 我们自定义的解析器放到这里面了
在这里插入图片描述

在这里插入图片描述
这里我们就转好了
在这里插入图片描述
发过去了
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot 中,我们可以通过实现 Converter 接口来自定义类型转换器,但是有时候我们发现自定义的转换器并没有生效。这可能是因为 Spring Boot 默认使用的是 GenericConversionService,而不是我们自定义的 ConversionService。 解决这个问题的方法有两种: 1. 在自定义转换器上添加 @Component 注解,将其注册到 Spring 容器中,并在需要使用该转换器的地方使用 @Autowired 注入。这样就可以确保我们自定义的转换器会被使用。 2. 自定义一个 ConversionService,将其注册到 Spring 容器中,并在需要使用该转换器的地方使用 @Qualifier 注解指定使用我们自定义的转换器。这种方法需要手动配置 ConversionService,但是可以更灵活地控制转换器的使用。 下面是第二种方法的示例代码: ```java @Configuration public class ConversionConfig { @Bean public ConversionService conversionService() { DefaultConversionService conversionService = new DefaultConversionService(); // 注册自定义转换器 conversionService.addConverter(new MyConverter()); return conversionService; } } ``` 在需要使用自定义转换器的地方,可以使用 @Qualifier 注解指定使用我们自定义的 ConversionService,例如: ```java @RestController public class DemoController { @Autowired @Qualifier("conversionService") private ConversionService conversionService; @GetMapping("/test") public String test(@RequestParam("myParam") MyParam myParam) { // 使用自定义转换器将字符串转换为自定义类型 MyParam // ... return "success"; } } ``` 希望能帮助到你!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值