Insight springmvc常用的入参解析器

controller方法常用的两种入参解析

springmvc 对于controller 方法的入参解析,常用到的有两种:

1.基于request请求参数、Form表单参数实现解析功能,如简单类或者自定义类入参;

2.基于request body实现解析功能,如@RequestBody 注解类入参。

......

springmvc 实现的两种方法入参解析器

1.针对上述的简单类和自定义类,springmvc 提供不同的解析器实现,下文详述;

列表A:

ServletModelAttributeMethodProcessor(自定义类解析)

RequestParamMethodArgumentResolver(简单类解析(primitive、String、Number、Date、URL等))

2.针对application/json 请求解析,springmvc 直接委托给JSON 解析库实现入参的反序列化。

列表B:

RequestResponseBodyMethodProcessor

......

基于请求参数的方法入参解析器

决定采用上述列表A中哪个解析器,核心在于需要解析的clazz类型。

 

/**
 * 检测指定的clazz是否为’简单‘类型。
 * 定义为:primitive、String、CharSequence、Number、Date、URI、URL、Locale、Class 或者这些类型的Array
 * 用途:决定注入类解析或者controller 方法入参类解析。
 */
public static boolean isSimpleProperty(Class clazz) {
    Assert.notNull(clazz, "Class must not be null");
    return isSimpleValueType(clazz) || (clazz.isArray() && isSimpleValueType(clazz.getComponentType()));
}

如果入参类型为自定义类,首先需要new instance,由此决定使用调用简单的DataBinder.convert还是AbstractPropertyAccessor.setPropertyValue。

 

DataBinder和 AbstractPropertyAccessor 都实现了TypeConverter 接口,基础的转换逻辑是相同的实现。

 

/**
 * 调度PropertyEditor、Converter,实现执行String To 指定类型转换
 **/
public  T convertIfNecessary(String propertyName, Object oldValue, Object newValue, Class requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException {

    // 优先使用Custom editor
    PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);
    
    // 其次使用配置的 conversionService,内置了n多converter,基本可以支持所有的类型转换
    ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
    if (editor == null && conversionService != null && convertedValue != null && typeDescriptor != null) {
        if (conversionService.canConvert(sourceTypeDesc, targetTypeDesc)) {
            try {
                return (T) conversionService.convert(convertedValue, sourceTypeDesc, targetTypeDesc);
            }
            catch (ConversionFailedException ex) {
            }
        }
    }
    
    // 优先使用Custom editor情况下,首先尝试进行简单的StringToCollection转换,再使用editor进行转换
    if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
        if (requiredType != null && Collection.class.isAssignableFrom(requiredType) && convertedValue instanceof String) {
            TypeDescriptor elementType = typeDescriptor.getElementTypeDescriptor();
            if (elementType != null && Enum.class.isAssignableFrom(elementType.getType())) {
                convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
            }
        }
        convertedValue = doConvertValue(oldValue, convertedValue, requiredType, editor);
    }
    
    // 以下代码正常情况不可能覆盖到...
    return (T) convertedValue;
}自定义表单请求解析Editor

 

Converter列表

之前推荐过PropertyEditor的实现,现在看看spring 内置的Converter,更加强大,如下:

 

// 能想到的类型转换都包括了,完美!
// 1.标准类型Converter
converterRegistry.addConverter(new StringToBooleanConverter());
converterRegistry.addConverter(Boolean.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverterFactory(new StringToNumberConverterFactory());
converterRegistry.addConverter(Number.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverterFactory(new NumberToNumberConverterFactory());
converterRegistry.addConverter(new StringToCharacterConverter());
converterRegistry.addConverter(Character.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new NumberToCharacterConverter());
converterRegistry.addConverterFactory(new CharacterToNumberFactory());
converterRegistry.addConverterFactory(new StringToEnumConverterFactory());
converterRegistry.addConverter(Enum.class, String.class, new EnumToStringConverter(conversionService));
converterRegistry.addConverter(new StringToLocaleConverter());
converterRegistry.addConverter(Locale.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new PropertiesToStringConverter());
converterRegistry.addConverter(new StringToPropertiesConverter());
converterRegistry.addConverter(new StringToUUIDConverter());
converterRegistry.addConverter(UUID.class, String.class, new ObjectToStringConverter());
// 2.集合类转换Converter,内部实现迭代处理
converterRegistry.addConverter(new ArrayToCollectionConverter(conversionService));
converterRegistry.addConverter(new CollectionToArrayConverter(conversionService));
converterRegistry.addConverter(new ArrayToArrayConverter(conversionService));
converterRegistry.addConverter(new CollectionToCollectionConverter(conversionService));
converterRegistry.addConverter(new MapToMapConverter(conversionService));
converterRegistry.addConverter(new ArrayToStringConverter(conversionService));
converterRegistry.addConverter(new StringToArrayConverter(conversionService));
converterRegistry.addConverter(new ArrayToObjectConverter(conversionService));
converterRegistry.addConverter(new ObjectToArrayConverter(conversionService));
converterRegistry.addConverter(new CollectionToStringConverter(conversionService));
converterRegistry.addConverter(new StringToCollectionConverter(conversionService));
converterRegistry.addConverter(new CollectionToObjectConverter(conversionService));
converterRegistry.addConverter(new ObjectToCollectionConverter(conversionService));
// 3.回调类型处理Converter
converterRegistry.addConverter(new ObjectToObjectConverter());
converterRegistry.addConverter(new IdToEntityConverter(conversionService));
converterRegistry.addConverter(new FallbackObjectToStringConverter());

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值