add alias

This commit is contained in:
Looly 2019-12-26 08:01:57 +08:00
parent 8932801137
commit 377cd55a3c
13 changed files with 156 additions and 71 deletions

View File

@ -7,6 +7,10 @@
### 新特性
* 【core 】 ClassUtil.isSimpleValueType增加TemporalAccessor支持issue#I170HK@Gitee
* 【core 】 增加Convert.toPrimitiveByteArray方法Convert支持对象序列化和反序列化
* 【core 】 DateUtil增加isExpired(Date startDate, Date endDate, Date checkDate)issue#687@Github
* 【core 】 增加Alias注解
### Bug修复
-------------------------------------------------------------------------------------------------------------

View File

@ -0,0 +1,20 @@
package cn.hutool.core.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 别名注解使用此注解的字段方法参数等会有一个别名用于Bean拷贝Bean转Map等
*
* @author Looly
* @since 5.1.1
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface Alias {
String value();
}

View File

@ -1,5 +1,9 @@
package cn.hutool.core.annotation;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
@ -13,11 +17,6 @@ import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.lang.Filter;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
/**
* 注解工具类<br>
* 快速获取注解对象注解值等工具封装
@ -116,19 +115,16 @@ public class AnnotationUtil {
return null;
}
final Method[] methods = ReflectUtil.getMethods(annotationType, new Filter<Method>() {
@Override
public boolean accept(Method t) {
if (ArrayUtil.isEmpty(t.getParameterTypes())) {
// 只读取无参方法
final String name = t.getName();
// 跳过自有的几个方法
return (false == "hashCode".equals(name)) //
&& (false == "toString".equals(name)) //
&& (false == "annotationType".equals(name));
}
return false;
final Method[] methods = ReflectUtil.getMethods(annotationType, t -> {
if (ArrayUtil.isEmpty(t.getParameterTypes())) {
// 只读取无参方法
final String name = t.getName();
// 跳过自有的几个方法
return (false == "hashCode".equals(name)) //
&& (false == "toString".equals(name)) //
&& (false == "annotationType".equals(name));
}
return false;
});
final HashMap<String, Object> result = new HashMap<>(methods.length, 1);

View File

@ -136,6 +136,17 @@ public class Convert {
return convert(Byte[].class, value);
}
/**
* 转换为Byte数组
*
* @param value 被转换的值
* @return Byte数组
* @since 5.1.1
*/
public static byte[] toPrimitiveByteArray(Object value) {
return convert(byte[].class, value);
}
/**
* 转换为Short<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<br>

View File

@ -317,6 +317,11 @@ public class ConverterRegistry implements Serializable{
return (T) value;
}
// 枚举转换
if (rowType.isEnum()) {
return (T) new EnumConverter(rowType).convert(value, defaultValue);
}
// 数组转换
if (rowType.isArray()) {
final ArrayConverter arrayConverter = new ArrayConverter(rowType);
@ -327,11 +332,6 @@ public class ConverterRegistry implements Serializable{
}
}
// 枚举转换
if (rowType.isEnum()) {
return (T) new EnumConverter(rowType).convert(value, defaultValue);
}
// 表示非需要特殊转换的对象
return null;
}

View File

@ -1,16 +1,18 @@
package cn.hutool.core.convert.impl;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.convert.AbstractConverter;
import cn.hutool.core.convert.ConverterRegistry;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
/**
* 数组转换器包括原始类型数组
*
@ -129,6 +131,9 @@ public class ArrayConverter extends AbstractConverter<Object> {
for (int i = 0; i < list.size(); i++) {
Array.set(result, i, converter.convert(targetComponentType, list.get(i)));
}
}else if (value instanceof Serializable && byte.class == targetComponentType) {
// 用户可能想序列化指定对象
result = ObjectUtil.serialize(value);
} else {
// everything else:
result = convertToSingleElementArray(value);

View File

@ -6,6 +6,7 @@ import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.bean.copier.ValueProvider;
import cn.hutool.core.convert.AbstractConverter;
import cn.hutool.core.map.MapProxy;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.TypeUtil;
@ -72,6 +73,9 @@ public class BeanConverter<T> extends AbstractConverter<T> {
//限定被转换对象类型
return BeanCopier.create(value, ReflectUtil.newInstanceIfPossible(this.beanClass), this.beanType, this.copyOptions).copy();
} else if(value instanceof byte[]){
// 尝试反序列化
return ObjectUtil.deserialize((byte[])value);
}
return null;
}

View File

@ -527,9 +527,9 @@ public class DateUtil {
}
final SimpleDateFormat sdf = new SimpleDateFormat(format);
if(date instanceof DateTime){
if (date instanceof DateTime) {
final TimeZone timeZone = ((DateTime) date).getTimeZone();
if(null != timeZone) {
if (null != timeZone) {
sdf.setTimeZone(timeZone);
}
}
@ -1774,16 +1774,34 @@ public class DateUtil {
/**
* 判定给定开始时间经过某段时间后是否过期
*
* @param startDate 开始时间
* @param dateField 时间单位
* @param timeLength 时长
* @param checkedDate 被比较的时间即有效期的截止时间如果经过时长后的时间晚于被检查的时间就表示过期
* @param startDate 开始时间
* @param dateField 时间单位
* @param timeLength 经过时长
* @param endDate 被比较的时间即有效期的截止时间如果经过时长后的时间晚于截止时间就表示过期
* @return 是否过期
* @since 3.1.1
*/
public static boolean isExpired(Date startDate, DateField dateField, int timeLength, Date checkedDate) {
final Date endDate = offset(startDate, dateField, timeLength);
return endDate.after(checkedDate);
public static boolean isExpired(Date startDate, DateField dateField, int timeLength, Date endDate) {
final Date offsetDate = offset(startDate, dateField, timeLength);
return offsetDate.after(endDate);
}
/**
* 判定在指定检查时间是否过期
*
* <p>
* 以商品为例startDate即生产日期endDate即保质期的截止日期checkDate表示在何时检查是否过期一般为当前时间<br>
* endDate和startDate的差值即为保质期按照毫秒计checkDate和startDate的差值即为实际经过的时长实际时长大于保质期表示超时
* </p>
*
* @param startDate 开始时间
* @param endDate 被比较的时间即有效期的截止时间如果经过时长后的时间晚于被检查的时间就表示过期
* @param checkDate 检查时间可以是当前时间
* @return 是否过期
* @since 5.1.1
*/
public static boolean isExpired(Date startDate, Date endDate, Date checkDate) {
return betweenMs(startDate, checkDate) > betweenMs(startDate, checkDate);
}
/**
@ -2034,7 +2052,7 @@ public class DateUtil {
* @return {@link LocalDateTime}
* @since 5.0.5
*/
public static LocalDateTime toLocalDateTime(Instant instant){
public static LocalDateTime toLocalDateTime(Instant instant) {
return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
}
@ -2045,7 +2063,7 @@ public class DateUtil {
* @return {@link LocalDateTime}
* @since 5.0.5
*/
public static LocalDateTime toLocalDateTime(Calendar calendar){
public static LocalDateTime toLocalDateTime(Calendar calendar) {
return LocalDateTime.ofInstant(calendar.toInstant(), calendar.getTimeZone().toZoneId());
}
@ -2056,12 +2074,13 @@ public class DateUtil {
* @return {@link LocalDateTime}
* @since 5.0.5
*/
public static LocalDateTime toLocalDateTime(Date date){
public static LocalDateTime toLocalDateTime(Date date) {
final DateTime dateTime = date(date);
return LocalDateTime.ofInstant(dateTime.toInstant(), dateTime.getZoneId());
}
// ------------------------------------------------------------------------ Private method start
/**
* 获得指定日期年份和季节<br>
* 格式[20131]表示2013年第一季度

View File

@ -1,22 +1,5 @@
package cn.hutool.core.util;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import cn.hutool.core.convert.BasicType;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.io.FileUtil;
@ -27,6 +10,22 @@ import cn.hutool.core.lang.ClassScanner;
import cn.hutool.core.lang.Filter;
import cn.hutool.core.lang.Singleton;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.URL;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
/**
* 类工具类 <br>
*

View File

@ -377,10 +377,17 @@ public class ObjectUtil {
* @param <T> 对象类型
* @param bytes 反序列化的字节码
* @return 反序列化后的对象
* @see #unserialize(byte[])
*/
@SuppressWarnings("unchecked")
public static <T> T deserialize(byte[] bytes) {
return unserialize(bytes);
ObjectInputStream ois;
try {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bais);
return (T) ois.readObject();
} catch (Exception e) {
throw new UtilException(e);
}
}
/**
@ -390,17 +397,12 @@ public class ObjectUtil {
* @param <T> 对象类型
* @param bytes 反序列化的字节码
* @return 反序列化后的对象
* @see #deserialize(byte[])
* @deprecated 请使用 {@link #deserialize(byte[])}
*/
@SuppressWarnings("unchecked")
@Deprecated
public static <T> T unserialize(byte[] bytes) {
ObjectInputStream ois;
try {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bais);
return (T) ois.readObject();
} catch (Exception e) {
throw new UtilException(e);
}
return deserialize(bytes);
}
/**

View File

@ -1,15 +1,18 @@
package cn.hutool.core.convert;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.junit.Assert;
import org.junit.Test;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 类型转换工具单元测试
*
*
* @author Looly
*
*/
@ -25,7 +28,7 @@ public class ConvertTest {
public void toStrTest() {
int a = 1;
long[] b = { 1, 2, 3, 4, 5 };
Assert.assertEquals("[1, 2, 3, 4, 5]", Convert.convert(String.class, b));
String aStr = Convert.toStr(a);
@ -33,7 +36,7 @@ public class ConvertTest {
String bStr = Convert.toStr(b);
Assert.assertEquals("[1, 2, 3, 4, 5]", Convert.toStr(bStr));
}
@Test
public void toStrTest2() {
String result = Convert.convert(String.class, "aaaa");
@ -206,4 +209,26 @@ public class ConvertTest {
Assert.assertEquals(1, list3.get(0).intValue());
Assert.assertEquals(2, list3.get(1).intValue());
}
@Test
public void toByteArrayTest(){
// 测试Serializable转换为bytes调用序列化转换
final byte[] bytes = Convert.toPrimitiveByteArray(new Product("zhangsan", "张三", "5.1.1"));
Assert.assertNotNull(bytes);
final Product product = Convert.convert(Product.class, bytes);
Assert.assertEquals("zhangsan", product.getName());
Assert.assertEquals("张三", product.getCName());
Assert.assertEquals("5.1.1", product.getVersion());
}
@Data
@AllArgsConstructor
public static class Product implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String cName;
private String version;
}
}

View File

@ -2,7 +2,6 @@ package cn.hutool.core.date;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.BetweenFormater.Level;
import cn.hutool.core.lang.Console;
import org.junit.Assert;
import org.junit.Test;

View File

@ -56,6 +56,7 @@ public class ExcelSaxUtil {
case SSTINDEX:
try {
final int index = Integer.parseInt(value);
//noinspection deprecation
result = new XSSFRichTextString(sharedStringsTable.getEntryAt(index)).getString();
} catch (NumberFormatException e) {
result = value;