mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix code
This commit is contained in:
parent
df180b2e12
commit
3d0e42f653
@ -27,13 +27,12 @@ import java.lang.reflect.Type;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 复合转换器,融合了所有支持类型和自定义类型的转换规则
|
||||
* <p>
|
||||
* 将各种类型Convert对象放入符合转换器,通过convert方法查找目标类型对应的转换器,将被转换对象转换之。
|
||||
* </p>
|
||||
* <p>
|
||||
* 在此类中,存放着默认转换器和自定义转换器,默认转换器是Hutool中预定义的一些转换器,自定义转换器存放用户自定的转换器。
|
||||
* </p>
|
||||
* 复合转换器,融合了所有支持类型和自定义类型的转换规则<br>
|
||||
* 在此类中,存放着默认转换器和自定义转换器,默认转换器是Hutool中预定义的一些转换器,自定义转换器存放用户自定的转换器。<br>
|
||||
* 转换过程类似于转换链,过程如下:
|
||||
* <pre>{@code
|
||||
* 处理null、Opt、Optional --> 自定义匹配转换器 --> 自定义类型转换器 --> 预注册的标准转换器 --> Map、集合、Enum等特殊转换器 --> Bean转换器
|
||||
* }</pre>
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
@ -143,7 +142,7 @@ public class CompositeConverter extends RegisterConverter {
|
||||
}
|
||||
|
||||
// 标准转换器
|
||||
final Converter converter = getConverter(type, isCustomFirst);
|
||||
final Converter converter = getConverter(type, value, isCustomFirst);
|
||||
if (null != converter) {
|
||||
return converter.convert(type, value, defaultValue);
|
||||
}
|
||||
|
@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.convert;
|
||||
|
||||
import org.dromara.hutool.core.collection.set.ConcurrentHashSet;
|
||||
import org.dromara.hutool.core.stream.StreamUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 用户自定义转换器<br>
|
||||
* 通过自定义实现{@link MatcherConverter},可以通过{@link MatcherConverter#match(Type, Class, Object)} 检查目标类型是否匹配<br>
|
||||
* 如果匹配,则直接转换,否则使用默认转换器转换。
|
||||
*
|
||||
* @author Looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class CustomConverter implements Converter, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
|
||||
*/
|
||||
private static class SingletonHolder {
|
||||
/**
|
||||
* 静态初始化器,由JVM来保证线程安全
|
||||
*/
|
||||
private static final CustomConverter INSTANCE = new CustomConverter();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得单例的 CustomConverter
|
||||
*
|
||||
* @return CustomConverter
|
||||
*/
|
||||
public static CustomConverter getInstance() {
|
||||
return CustomConverter.SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户自定义类型转换器
|
||||
*/
|
||||
private volatile Set<MatcherConverter> converterSet;
|
||||
|
||||
@Override
|
||||
public Object convert(final Type targetType, final Object value) throws ConvertException {
|
||||
final Converter customConverter = getCustomConverter(targetType, value);
|
||||
return null == customConverter ? null : customConverter.convert(targetType, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得匹配类型的自定义转换器
|
||||
*
|
||||
* @param type 类型
|
||||
* @param value 被转换的值
|
||||
* @return 转换器
|
||||
*/
|
||||
public Converter getCustomConverter(final Type type, final Object value) {
|
||||
return getConverterFromSet(this.converterSet, type, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登记自定义转换器
|
||||
*
|
||||
* @param converter 转换器
|
||||
* @return ConverterRegistry
|
||||
*/
|
||||
public CustomConverter add(final MatcherConverter converter) {
|
||||
if (null == this.converterSet) {
|
||||
synchronized (this) {
|
||||
if (null == this.converterSet) {
|
||||
this.converterSet = new ConcurrentHashSet<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
this.converterSet.add(converter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从指定集合中查找满足条件的转换器
|
||||
*
|
||||
* @param type 类型
|
||||
* @return 转换器
|
||||
*/
|
||||
private static Converter getConverterFromSet(final Set<? extends MatcherConverter> converterSet, final Type type, final Object value) {
|
||||
return StreamUtil.of(converterSet).filter((predicate) -> predicate.match(type, value)).findFirst().orElse(null);
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
|
||||
package org.dromara.hutool.core.convert;
|
||||
|
||||
import org.dromara.hutool.core.collection.set.ConcurrentHashSet;
|
||||
import org.dromara.hutool.core.convert.impl.*;
|
||||
import org.dromara.hutool.core.lang.Opt;
|
||||
import org.dromara.hutool.core.lang.tuple.Pair;
|
||||
@ -23,6 +24,7 @@ import org.dromara.hutool.core.lang.tuple.Triple;
|
||||
import org.dromara.hutool.core.lang.tuple.Tuple;
|
||||
import org.dromara.hutool.core.map.concurrent.SafeConcurrentHashMap;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.core.stream.StreamUtil;
|
||||
|
||||
import javax.xml.datatype.XMLGregorianCalendar;
|
||||
import java.io.Serializable;
|
||||
@ -42,10 +44,12 @@ import java.util.concurrent.atomic.AtomicLongArray;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* 基于类型注册的转换器<br>
|
||||
* 即转换的目标类型和转换器一一对应,转换器只针对目标类型,不针对源类型<br>
|
||||
* 转换器默认提供一些固定的类型转换,用户可调用{@link #putCustom(Type, Converter)} 注册自定义转换规则<br>
|
||||
* 注意:注册的转换器要求目标类型必须一致,不能是子类等
|
||||
* 基于类型注册的转换器,提供两种注册方式,按照优先级依次为:
|
||||
* <ol>
|
||||
* <li>按照匹配注册,使用{@link #register(MatcherConverter)}。
|
||||
* 注册后一旦给定的目标类型和值满足{@link MatcherConverter#match(Type, Class, Object)},即可调用对应转换器转换。</li>
|
||||
* <li>按照类型注册,使用{@link #register(Type, Converter)},目标类型一致,即可调用转换。</li>
|
||||
* </ol>
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
@ -72,14 +76,19 @@ public class RegisterConverter implements Converter, Serializable {
|
||||
return RegisterConverter.SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户自定义类型转换器,存储自定义匹配规则的一类对象的转换器
|
||||
*/
|
||||
private volatile Set<MatcherConverter> converterSet;
|
||||
/**
|
||||
* 用户自定义精确类型转换器<br>
|
||||
* 主要存储类型明确(无子类)的转换器
|
||||
*/
|
||||
private volatile Map<Type, Converter> customConverterMap;
|
||||
/**
|
||||
* 默认类型转换器
|
||||
*/
|
||||
private Map<Class<?>, Converter> defaultConverterMap;
|
||||
/**
|
||||
* 用户自定义类型转换器
|
||||
*/
|
||||
private volatile Map<Type, Converter> customConverterMap;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
@ -91,7 +100,7 @@ public class RegisterConverter implements Converter, Serializable {
|
||||
@Override
|
||||
public Object convert(final Type targetType, final Object value) throws ConvertException {
|
||||
// 标准转换器
|
||||
final Converter converter = getConverter(targetType, true);
|
||||
final Converter converter = getConverter(targetType, value, true);
|
||||
if (null != converter) {
|
||||
return converter.convert(targetType, value);
|
||||
}
|
||||
@ -104,19 +113,26 @@ public class RegisterConverter implements Converter, Serializable {
|
||||
* 获得转换器<br>
|
||||
*
|
||||
* @param type 类型
|
||||
* @param value 转换的值
|
||||
* @param isCustomFirst 是否自定义转换器优先
|
||||
* @return 转换器
|
||||
*/
|
||||
public Converter getConverter(final Type type, final boolean isCustomFirst) {
|
||||
public Converter getConverter(final Type type, final Object value, final boolean isCustomFirst) {
|
||||
Converter converter;
|
||||
if (isCustomFirst) {
|
||||
converter = this.getCustomConverter(type);
|
||||
converter = this.getCustomConverter(type, value);
|
||||
if(null == converter){
|
||||
converter = this.getCustomConverter(type);
|
||||
}
|
||||
if (null == converter) {
|
||||
converter = this.getDefaultConverter(type);
|
||||
}
|
||||
} else {
|
||||
converter = this.getDefaultConverter(type);
|
||||
if (null == converter) {
|
||||
converter = this.getCustomConverter(type, value);
|
||||
}
|
||||
if(null == converter){
|
||||
converter = this.getCustomConverter(type);
|
||||
}
|
||||
}
|
||||
@ -135,7 +151,21 @@ public class RegisterConverter implements Converter, Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得自定义转换器
|
||||
* 获得匹配类型的自定义转换器
|
||||
*
|
||||
* @param type 类型
|
||||
* @param value 被转换的值
|
||||
* @return 转换器
|
||||
*/
|
||||
public Converter getCustomConverter(final Type type, final Object value) {
|
||||
return StreamUtil.of(converterSet)
|
||||
.filter((predicate) -> predicate.match(type, value))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得指定类型对应的自定义转换器
|
||||
*
|
||||
* @param type 类型
|
||||
* @return 转换器
|
||||
@ -145,13 +175,13 @@ public class RegisterConverter implements Converter, Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 登记自定义转换器
|
||||
* 登记自定义转换器,登记的目标类型必须一致
|
||||
*
|
||||
* @param type 转换的目标类型
|
||||
* @param converter 转换器
|
||||
* @return ConverterRegistry
|
||||
*/
|
||||
public RegisterConverter putCustom(final Type type, final Converter converter) {
|
||||
public RegisterConverter register(final Type type, final Converter converter) {
|
||||
if (null == customConverterMap) {
|
||||
synchronized (this) {
|
||||
if (null == customConverterMap) {
|
||||
@ -163,6 +193,24 @@ public class RegisterConverter implements Converter, Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登记自定义转换器,符合{@link MatcherConverter#match(Type, Class, Object)}则使用其转换器
|
||||
*
|
||||
* @param converter 转换器
|
||||
* @return ConverterRegistry
|
||||
*/
|
||||
public RegisterConverter register(final MatcherConverter converter) {
|
||||
if (null == this.converterSet) {
|
||||
synchronized (this) {
|
||||
if (null == this.converterSet) {
|
||||
this.converterSet = new ConcurrentHashSet<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
this.converterSet.add(converter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册默认转换器
|
||||
*/
|
||||
|
@ -15,12 +15,18 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* 万能类型转换器以及各种类型转换的实现类,其中Convert为转换器入口,提供各种toXXX方法和convert方法
|
||||
* 万能类型转换器以及各种类型转换的实现类,其中Convert为转换器入口,提供各种toXXX方法和convert方法<br>
|
||||
* 转换器是典型的策略模式应用,可自定义转换策略。Hutool提供了常用类型的转换策略,自定义转换接口包括:
|
||||
* <ul>
|
||||
* <li>{@link org.dromara.hutool.core.convert.Converter},标准转换接口,通过类型匹配策略后调用使用。</li>
|
||||
* <li>{@link org.dromara.hutool.core.convert.MatcherConverter},带有match方法的Converter,通过自身匹配判断调用转换。</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* 转换器是典型的策略模式应用,通过实现{@link org.dromara.hutool.core.convert.Converter} 接口,
|
||||
* 自定义转换策略。Hutool提供了常用类型的转换策略。
|
||||
* </p>
|
||||
* 公共的转换器封装有两种:
|
||||
* <ul>
|
||||
* <li>{@link org.dromara.hutool.core.convert.RegisterConverter},提供预定义的转换规则,也可以注册自定义转换规则。</li>
|
||||
* <li>{@link org.dromara.hutool.core.convert.CompositeConverter},复合转换器,封装基于注册的、特别转换(泛型转换)等规则,实现万能转换。</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
|
@ -38,7 +38,7 @@ public class CompositeConverterTest {
|
||||
|
||||
@Test
|
||||
public void getConverterTest() {
|
||||
final Converter converter = CompositeConverter.getInstance().getConverter(CharSequence.class, false);
|
||||
final Converter converter = CompositeConverter.getInstance().getConverter(CharSequence.class, null, false);
|
||||
assertNotNull(converter);
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@ public class CompositeConverterTest {
|
||||
|
||||
//此处做为示例自定义CharSequence转换,因为Hutool中已经提供CharSequence转换,请尽量不要替换
|
||||
//替换可能引发关联转换异常(例如覆盖CharSequence转换会影响全局)
|
||||
compositeConverter.putCustom(CharSequence.class, new CustomConverter());
|
||||
compositeConverter.register(CharSequence.class, new CustomConverter());
|
||||
result = (CharSequence) compositeConverter.convert(CharSequence.class, a);
|
||||
assertEquals("Custom: 454553", result);
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ import java.util.Optional;
|
||||
* JSON转换器,实现Object对象转换为{@link JSON},支持的对象:
|
||||
* <ul>
|
||||
* <li>任意支持的对象,转换为JSON</li>
|
||||
* <li>JSOn转换为指定对象Bean</li>
|
||||
* <li>JSON转换为指定对象Bean</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author looly
|
||||
@ -61,8 +61,8 @@ public class JSONConverter implements Converter, Serializable {
|
||||
|
||||
static {
|
||||
final RegisterConverter converter = RegisterConverter.getInstance();
|
||||
converter.putCustom(JSONObject.class, INSTANCE);
|
||||
converter.putCustom(JSONArray.class, INSTANCE);
|
||||
converter.register(JSONObject.class, INSTANCE);
|
||||
converter.register(JSONArray.class, INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -188,7 +188,7 @@ public class JSONConverter implements Converter, Serializable {
|
||||
// RFC8259,JSON字符串值、number, boolean, or null
|
||||
final JSONParser jsonParser = JSONParser.of(new JSONTokener(jsonStr), config);
|
||||
final Object value = jsonParser.nextValue();
|
||||
if(jsonParser.getTokener().nextClean() != JSONTokener.EOF){
|
||||
if (jsonParser.getTokener().nextClean() != JSONTokener.EOF) {
|
||||
// 对于用户提供的未转义字符串导致解析未结束,报错
|
||||
throw new JSONException("JSON format error: {}", jsonStr);
|
||||
}
|
||||
@ -197,7 +197,7 @@ public class JSONConverter implements Converter, Serializable {
|
||||
case '\'':
|
||||
return InternalJSONUtil.quote((CharSequence) value);
|
||||
default:
|
||||
if(ObjUtil.equals(jsonStr, value)){
|
||||
if (ObjUtil.equals(jsonStr, value)) {
|
||||
// 对于直接的字符串,如abc,按照字符串处理
|
||||
return InternalJSONUtil.quote((CharSequence) value);
|
||||
}
|
||||
@ -208,7 +208,10 @@ public class JSONConverter implements Converter, Serializable {
|
||||
// ----------------------------------------------------------- Private method start
|
||||
|
||||
/**
|
||||
* JSON转Bean
|
||||
* JSON转Bean,流程为:
|
||||
* <pre>{@code
|
||||
* 自定义反序列化 --> 尝试转Kotlin --> 基于注册的标准转换器 --> Collection、Map等含有泛型的特殊转换器 --> 普通Bean转换器
|
||||
* }</pre>
|
||||
*
|
||||
* @param <T> 目标类型
|
||||
* @param targetType 目标类型,
|
||||
@ -236,18 +239,18 @@ public class JSONConverter implements Converter, Serializable {
|
||||
return KClassUtil.newInstance(rawType, new JSONGetterValueProvider<>((JSONGetter<String>) json));
|
||||
}
|
||||
|
||||
// 标准转换器
|
||||
final Converter converter = RegisterConverter.getInstance().getConverter(targetType, json, true);
|
||||
if (null != converter) {
|
||||
return (T) converter.convert(targetType, json);
|
||||
}
|
||||
|
||||
// 特殊类型转换,包括Collection、Map、强转、Array等
|
||||
final T result = (T) SpecialConverter.getInstance().convert(targetType, rawType, json);
|
||||
if (null != result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// 标准转换器
|
||||
final Converter converter = RegisterConverter.getInstance().getConverter(targetType, true);
|
||||
if (null != converter) {
|
||||
return (T) converter.convert(targetType, json);
|
||||
}
|
||||
|
||||
// 尝试转Bean
|
||||
if (BeanUtil.isWritableBean(rawType)) {
|
||||
return BeanCopier.of(json,
|
||||
|
Loading…
x
Reference in New Issue
Block a user