mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
Merge branch 'v5-dev' of gitee.com:loolly/hutool into v5-dev
This commit is contained in:
commit
945a631f2b
@ -32,8 +32,10 @@ import cn.hutool.core.convert.impl.URLConverter;
|
|||||||
import cn.hutool.core.convert.impl.UUIDConverter;
|
import cn.hutool.core.convert.impl.UUIDConverter;
|
||||||
import cn.hutool.core.date.DateTime;
|
import cn.hutool.core.date.DateTime;
|
||||||
import cn.hutool.core.lang.TypeReference;
|
import cn.hutool.core.lang.TypeReference;
|
||||||
|
import cn.hutool.core.util.ClassUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.ReflectUtil;
|
import cn.hutool.core.util.ReflectUtil;
|
||||||
|
import cn.hutool.core.util.ServiceLoaderUtil;
|
||||||
import cn.hutool.core.util.TypeUtil;
|
import cn.hutool.core.util.TypeUtil;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@ -59,6 +61,7 @@ import java.time.temporal.TemporalAccessor;
|
|||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Currency;
|
import java.util.Currency;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@ -107,6 +110,22 @@ public class ConverterRegistry implements Serializable{
|
|||||||
|
|
||||||
public ConverterRegistry() {
|
public ConverterRegistry() {
|
||||||
defaultConverter();
|
defaultConverter();
|
||||||
|
putCustomBySpi();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
private void putCustomBySpi() {
|
||||||
|
List<Converter> list = ServiceLoaderUtil.loadList(Converter.class);
|
||||||
|
list.forEach(converter->{
|
||||||
|
try {
|
||||||
|
Type type = TypeUtil.getTypeArgument(ClassUtil.getClass(converter));
|
||||||
|
putCustom(type, converter);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 忽略注册失败的
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
package cn.hutool.core.convert;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*枚举元素通用接口,在自定义枚举上实现此接口可以用于数据转换<br>
|
||||||
|
*数据库保存时建议保存 intVal()而非ordinal()防备需求变更<br>
|
||||||
|
* @param <E>
|
||||||
|
*/
|
||||||
|
public interface EnumItem<E extends EnumItem<E>> extends Serializable{
|
||||||
|
|
||||||
|
String name();
|
||||||
|
/**
|
||||||
|
* 在中文语境下,多数时间枚举会配合一个中文说明
|
||||||
|
*/
|
||||||
|
default String text() {
|
||||||
|
return name();
|
||||||
|
}
|
||||||
|
|
||||||
|
int intVal();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
default E[] items() {
|
||||||
|
return (E[]) this.getClass().getEnumConstants();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 通过int类型值查找兄弟其他枚举
|
||||||
|
* @param intVal
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
default E fromInt(Integer intVal) {
|
||||||
|
if(intVal==null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
E[] vs = items();
|
||||||
|
for (E enumItem : vs) {
|
||||||
|
if(enumItem.intVal()==intVal.intValue()) {
|
||||||
|
return enumItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 通过String类型的值转换,根据实现可以用name/text
|
||||||
|
* @param intVal
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
default E fromStr(String strVal) {
|
||||||
|
if(strVal==null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
E[] vs = items();
|
||||||
|
for (E enumItem : vs) {
|
||||||
|
if(strVal.equalsIgnoreCase(enumItem.name())) {
|
||||||
|
return enumItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
|||||||
package cn.hutool.core.convert.impl;
|
package cn.hutool.core.convert.impl;
|
||||||
|
|
||||||
import cn.hutool.core.convert.AbstractConverter;
|
import cn.hutool.core.convert.AbstractConverter;
|
||||||
|
import cn.hutool.core.convert.EnumItem;
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.util.ClassUtil;
|
import cn.hutool.core.util.ClassUtil;
|
||||||
import cn.hutool.core.util.EnumUtil;
|
import cn.hutool.core.util.EnumUtil;
|
||||||
@ -52,37 +53,55 @@ public class EnumConverter extends AbstractConverter<Object> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 尝试找到类似转换的静态方法调用实现转换
|
* 尝试找到类似转换的静态方法调用实现转换且优先使用<br>
|
||||||
*
|
* 约定枚举类应该提供 valueOf(String) 和 valueOf(Integer)用于转换
|
||||||
|
* oriInt /name 转换托底
|
||||||
|
*
|
||||||
* @param value 被转换的值
|
* @param value 被转换的值
|
||||||
* @param enumClass enum类
|
* @param enumClass enum类
|
||||||
* @return 对应的枚举值
|
* @return 对应的枚举值
|
||||||
*/
|
*/
|
||||||
protected static Enum tryConvertEnum(Object value, Class enumClass) {
|
protected static Enum tryConvertEnum(Object value, Class enumClass) {
|
||||||
|
if(value==null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Enum enumResult = null;
|
Enum enumResult = null;
|
||||||
if (value instanceof Integer) {
|
if(EnumItem.class.isAssignableFrom(enumClass)) {
|
||||||
enumResult = EnumUtil.getEnumAt(enumClass, (Integer)value);
|
EnumItem first = (EnumItem) EnumUtil.getEnumAt(enumClass, 0);
|
||||||
} else if (value instanceof String) {
|
if(value instanceof Integer) {
|
||||||
try {
|
return (Enum) first.fromInt((Integer) value);
|
||||||
enumResult = Enum.valueOf(enumClass, (String) value);
|
}else if(value instanceof String){
|
||||||
} catch (IllegalArgumentException e) {
|
return (Enum) first.fromStr( value.toString());
|
||||||
//ignore
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 用户自定义方法优先,
|
||||||
// 尝试查找其它用户自定义方法
|
final Map<Class<?>, Method> valueOfMethods = getValueOfMethods(enumClass);
|
||||||
if(null == enumResult){
|
if (MapUtil.isNotEmpty(valueOfMethods)) {
|
||||||
final Map<Class<?>, Method> valueOfMethods = getValueOfMethods(enumClass);
|
final Class<?> valueClass = value.getClass();
|
||||||
if (MapUtil.isNotEmpty(valueOfMethods)) {
|
for (Map.Entry<Class<?>, Method> entry : valueOfMethods.entrySet()) {
|
||||||
final Class<?> valueClass = value.getClass();
|
if (ClassUtil.isAssignable(entry.getKey(), valueClass)) {
|
||||||
for (Map.Entry<Class<?>, Method> entry : valueOfMethods.entrySet()) {
|
enumResult = ReflectUtil.invokeStatic(entry.getValue(), value);
|
||||||
if (ClassUtil.isAssignable(entry.getKey(), valueClass)) {
|
}
|
||||||
enumResult = ReflectUtil.invokeStatic(entry.getValue(), value);
|
}
|
||||||
}
|
}
|
||||||
|
//oriInt 应该滞后使用 以 GB/T 2261.1-2003 性别编码为例,对应整数并非连续数字会导致数字转枚举时失败
|
||||||
|
//0 - 未知的性别
|
||||||
|
//1 - 男性
|
||||||
|
//2 - 女性
|
||||||
|
//5 - 女性改(变)为男性
|
||||||
|
//6 - 男性改(变)为女性
|
||||||
|
//9 - 未说明的性别
|
||||||
|
if(null == enumResult){
|
||||||
|
if (value instanceof Integer) {
|
||||||
|
enumResult = EnumUtil.getEnumAt(enumClass, (Integer)value);
|
||||||
|
} else if (value instanceof String) {
|
||||||
|
try {
|
||||||
|
enumResult = Enum.valueOf(enumClass, (String) value);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
//ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return enumResult;
|
return enumResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package cn.hutool.core.util;
|
package cn.hutool.core.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.ServiceConfigurationError;
|
import java.util.ServiceConfigurationError;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
@ -61,7 +63,7 @@ public class ServiceLoaderUtil {
|
|||||||
* @return 服务接口实现列表
|
* @return 服务接口实现列表
|
||||||
*/
|
*/
|
||||||
public static <T> ServiceLoader<T> load(Class<T> clazz) {
|
public static <T> ServiceLoader<T> load(Class<T> clazz) {
|
||||||
return ServiceLoader.load(clazz);
|
return load(clazz,null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,6 +75,37 @@ public class ServiceLoaderUtil {
|
|||||||
* @return 服务接口实现列表
|
* @return 服务接口实现列表
|
||||||
*/
|
*/
|
||||||
public static <T> ServiceLoader<T> load(Class<T> clazz, ClassLoader loader) {
|
public static <T> ServiceLoader<T> load(Class<T> clazz, ClassLoader loader) {
|
||||||
|
if(loader==null) {
|
||||||
|
loader = Thread.currentThread().getContextClassLoader();
|
||||||
|
}
|
||||||
return ServiceLoader.load(clazz, loader);
|
return ServiceLoader.load(clazz, loader);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 加载服务 并已list列表返回
|
||||||
|
* @param <T> 接口类型
|
||||||
|
* @param clazz 服务接口
|
||||||
|
* @return 服务接口实现列表
|
||||||
|
*/
|
||||||
|
public static <T> List<T> loadList(Class<T> clazz){
|
||||||
|
return loadList(clazz);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 加载服务 并已list列表返回
|
||||||
|
* @param <T> 接口类型
|
||||||
|
* @param clazz 服务接口
|
||||||
|
* @param loader {@link ClassLoader}
|
||||||
|
* @return 服务接口实现列表
|
||||||
|
*/
|
||||||
|
public static <T> List<T> loadList(Class<T> clazz, ClassLoader loader){
|
||||||
|
final Iterator<T> iterator = load(clazz).iterator();
|
||||||
|
List<T> list=new ArrayList<>();
|
||||||
|
while(iterator.hasNext()){
|
||||||
|
try {
|
||||||
|
list.add(iterator.next());
|
||||||
|
} catch (ServiceConfigurationError e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1338,7 +1338,7 @@ public class XmlUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<?> getPrefixes(String namespaceURI) {
|
public Iterator<String> getPrefixes(String namespaceURI) {
|
||||||
// Not implemented
|
// Not implemented
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import java.io.File;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Excel工具类
|
* Excel工具类,不建议直接使用index直接操作sheet,在wps/excel中sheet显示顺序与index无关,还有隐藏sheet
|
||||||
*
|
*
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user