diff --git a/CHANGELOG.md b/CHANGELOG.md index 67e7085c2..9a0a91e59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,13 @@ ### 新特性 * 【core 】 ServiceLoaderUtil改为使用contextClassLoader(pr#183@Gitee) * 【core 】 NetUtil增加getLocalHostName(pr#1103@Github) +* 【extra 】 FTP增加stat方法(issue#I1W346@Gitee) +* 【core 】 Convert.toNumber支持类似12.2F这种形式字符串转换(issue#I1VYLJ@Gitee) +* 【core 】 使用静态变量替换999等(issue#I1W8IB@Gitee) ### Bug修复 +* 【crypto 】 修复SM2验签后无法解密问题(issue#I1W0VP@Gitee) +* 【core 】 修复新建默认TreeSet没有默认比较器导致的问题(issue#1101@Github) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanCopier.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanCopier.java index d9c5c1f7a..4708a22e6 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanCopier.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/BeanCopier.java @@ -109,6 +109,7 @@ public class BeanCopier implements Copier, Serializable { } } } + return this.dest; } diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java index a8969ec05..be05dc667 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java @@ -1,6 +1,7 @@ package cn.hutool.core.collection; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.comparator.CompareUtil; import cn.hutool.core.comparator.PinyinComparator; import cn.hutool.core.comparator.PropertyComparator; import cn.hutool.core.convert.Convert; @@ -992,8 +993,13 @@ public class CollUtil { } else if (collectionType.isAssignableFrom(LinkedHashSet.class)) { list = new LinkedHashSet<>(); } else if (collectionType.isAssignableFrom(TreeSet.class)) { - //noinspection SortedCollectionWithNonComparableKeys - list = new TreeSet<>(); + list = new TreeSet<>((o1, o2) -> { + // 优先按照对象本身比较,如果没有实现比较接口,默认按照toString内容比较 + if (o1 instanceof Comparable) { + return ((Comparable) o1).compareTo(o2); + } + return CompareUtil.compare(o1.toString(), o2.toString()); + }); } else if (collectionType.isAssignableFrom(EnumSet.class)) { list = (Collection) EnumSet.noneOf((Class) ClassUtil.getTypeArgument(collectionType)); } diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java b/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java index 9c081999b..3fa034c86 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java @@ -106,9 +106,9 @@ public class ConverterRegistry implements Serializable { } /** - * 获得单例的 {@link ConverterRegistry} + * 获得单例的 ConverterRegistry * - * @return {@link ConverterRegistry} + * @return ConverterRegistry */ public static ConverterRegistry getInstance() { return SingletonHolder.INSTANCE; @@ -140,7 +140,7 @@ public class ConverterRegistry implements Serializable { * * @param type 转换的目标类型 * @param converterClass 转换器类,必须有默认构造方法 - * @return {@link ConverterRegistry} + * @return ConverterRegistry */ public ConverterRegistry putCustom(Type type, Class> converterClass) { return putCustom(type, ReflectUtil.newInstance(converterClass)); @@ -151,7 +151,7 @@ public class ConverterRegistry implements Serializable { * * @param type 转换的目标类型 * @param converter 转换器 - * @return {@link ConverterRegistry} + * @return ConverterRegistry */ public ConverterRegistry putCustom(Type type, Converter converter) { if (null == customConverterMap) { @@ -257,6 +257,7 @@ public class ConverterRegistry implements Serializable { } } + // 特殊类型转换,包括Collection、Map、强转、Array等 final T result = convertSpecial(type, rowType, value, defaultValue); if (null != result) { @@ -269,7 +270,7 @@ public class ConverterRegistry implements Serializable { } // 无法转换 - throw new ConvertException("No Converter for type [{}]", rowType.getName()); + throw new ConvertException("Can not Converter from [{}] to [{}]", value.getClass().getName(), type.getTypeName()); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/CollectionConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/CollectionConverter.java index 6dd82da13..a2633e86d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/CollectionConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/CollectionConverter.java @@ -2,6 +2,7 @@ package cn.hutool.core.convert.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Converter; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.TypeUtil; import java.lang.reflect.Type; @@ -60,13 +61,8 @@ public class CollectionConverter implements Converter> { @Override public Collection convert(Object value, Collection defaultValue) throws IllegalArgumentException { - Collection result; - try { - result = convertInternal(value); - } catch (RuntimeException e) { - return defaultValue; - } - return ((null == result) ? defaultValue : result); + final Collection result = convertInternal(value); + return ObjectUtil.defaultIfNull(result, defaultValue); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java index 97fca587f..3054e76a8 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java @@ -207,7 +207,16 @@ public class NumberConverter extends AbstractConverter { @Override protected String convertToStr(Object value) { - return StrUtil.trim(super.convertToStr(value)); + String result = StrUtil.trim(super.convertToStr(value)); + if(StrUtil.isNotEmpty(result)){ + final char c = Character.toUpperCase(result.charAt(result.length() - 1)); + if(c == 'D' || c == 'L' || c == 'F'){ + // 类型标识形式(例如123.6D) + return StrUtil.subPre(result, -1); + } + } + + return result; } @Override diff --git a/hutool-core/src/main/java/cn/hutool/core/date/LocalDateTimeUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/LocalDateTimeUtil.java index c95540f9f..a1745440f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/LocalDateTimeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/LocalDateTimeUtil.java @@ -428,7 +428,7 @@ public class LocalDateTimeUtil { * @return 一天的开始时间 */ public static LocalDateTime beginOfDay(LocalDateTime time) { - return time.with(LocalTime.of(0, 0, 0, 0)); + return time.with(LocalTime.MIN); } /** @@ -438,7 +438,7 @@ public class LocalDateTimeUtil { * @return 一天的结束时间 */ public static LocalDateTime endOfDay(LocalDateTime time) { - return time.with(LocalTime.of(23, 59, 59, 999_999_999)); + return time.with(LocalTime.MAX); } /** diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToNumberTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToNumberTest.java index f8b30cf26..a1600c664 100644 --- a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToNumberTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToNumberTest.java @@ -5,6 +5,7 @@ import cn.hutool.core.date.DateUtil; import org.junit.Assert; import org.junit.Test; +import java.math.BigDecimal; import java.util.concurrent.atomic.AtomicLong; public class ConvertToNumberTest { @@ -31,4 +32,13 @@ public class ConvertToNumberTest { assert date != null; Assert.assertEquals(date.getTime(), dateLong.longValue()); } + + @Test + public void toBigDecimalTest(){ + BigDecimal bigDecimal = Convert.toBigDecimal("1.1f"); + Assert.assertEquals(1.1f, bigDecimal.floatValue(), 1); + + bigDecimal = Convert.toBigDecimal("1L"); + Assert.assertEquals(1L, bigDecimal.longValue()); + } } diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2.java b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2.java index b33f49614..d0315bd61 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2.java @@ -499,8 +499,10 @@ public class SM2 extends AbstractAsymmetricCrypto { */ private SM2Engine getEngine() { if (null == this.engine) { + Assert.notNull(this.digest, "digest must be not null !"); this.engine = new SM2Engine(this.digest, this.mode); } + this.digest.reset(); return this.engine; } @@ -511,8 +513,10 @@ public class SM2 extends AbstractAsymmetricCrypto { */ private SM2Signer getSigner() { if (null == this.signer) { + Assert.notNull(this.digest, "digest must be not null !"); this.signer = new SM2Signer(this.encoding, this.digest); } + this.digest.reset(); return this.signer; } // ------------------------------------------------------------------------------------------------------------------------- Private method end diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java b/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java index 8d4539793..2ae68c917 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java @@ -342,6 +342,20 @@ public class Ftp extends AbstractFtp { } } + /** + * 获取服务端目录状态。 + * @param path 路径 + * @return 状态int,服务端不同,返回不同 + * @since 5.4.3 + */ + public int stat(String path) { + try { + return this.client.stat(path); + } catch (IOException e) { + throw new FtpException(e); + } + } + /** * 判断ftp服务器文件是否存在 * diff --git a/hutool-json/src/test/java/cn/hutool/json/Issue1101Test.java b/hutool-json/src/test/java/cn/hutool/json/Issue1101Test.java new file mode 100644 index 000000000..cdb17b458 --- /dev/null +++ b/hutool-json/src/test/java/cn/hutool/json/Issue1101Test.java @@ -0,0 +1,96 @@ +package cn.hutool.json; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.TypeReference; +import lombok.Data; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Comparator; +import java.util.TreeSet; + +/** + * 测试转换为TreeSet是否成功。 TreeSet必须有默认的比较器 + */ +public class Issue1101Test { + + @Test + public void treeMapConvertTest(){ + String json = "[{\"nodeName\":\"admin\",\"treeNodeId\":\"00010001_52c95b83-2083-4138-99fb-e6e21f0c1277\",\"sort\":0,\"type\":10,\"parentId\":\"00010001\",\"children\":[],\"id\":\"52c95b83-2083-4138-99fb-e6e21f0c1277\",\"status\":true},{\"nodeName\":\"test\",\"treeNodeId\":\"00010001_97054a82-f8ff-46a1-b76c-cbacf6d18045\",\"sort\":0,\"type\":10,\"parentId\":\"00010001\",\"children\":[],\"id\":\"97054a82-f8ff-46a1-b76c-cbacf6d18045\",\"status\":true}]"; + final JSONArray objects = JSONUtil.parseArray(json); + final TreeSet convert = Convert.convert(new TypeReference>() { + }, objects); + Assert.assertEquals(2, convert.size()); + } + + @Test + public void test(){ + String json = "{\n" + + "\t\"children\": [{\n" + + "\t\t\"children\": [],\n" + + "\t\t\"id\": \"52c95b83-2083-4138-99fb-e6e21f0c1277\",\n" + + "\t\t\"nodeName\": \"admin\",\n" + + "\t\t\"parentId\": \"00010001\",\n" + + "\t\t\"sort\": 0,\n" + + "\t\t\"status\": true,\n" + + "\t\t\"treeNodeId\": \"00010001_52c95b83-2083-4138-99fb-e6e21f0c1277\",\n" + + "\t\t\"type\": 10\n" + + "\t}, {\n" + + "\t\t\"children\": [],\n" + + "\t\t\"id\": \"97054a82-f8ff-46a1-b76c-cbacf6d18045\",\n" + + "\t\t\"nodeName\": \"test\",\n" + + "\t\t\"parentId\": \"00010001\",\n" + + "\t\t\"sort\": 0,\n" + + "\t\t\"status\": true,\n" + + "\t\t\"treeNodeId\": \"00010001_97054a82-f8ff-46a1-b76c-cbacf6d18045\",\n" + + "\t\t\"type\": 10\n" + + "\t}],\n" + + "\t\"id\": \"00010001\",\n" + + "\t\"nodeName\": \"测试\",\n" + + "\t\"parentId\": \"0001\",\n" + + "\t\"sort\": 0,\n" + + "\t\"status\": true,\n" + + "\t\"treeNodeId\": \"00010001\",\n" + + "\t\"type\": 0\n" + + "}"; + + final JSONObject jsonObject = JSONUtil.parseObj(json); + + final TreeNode treeNode = JSONUtil.toBean(jsonObject, TreeNode.class); + Assert.assertEquals(2, treeNode.getChildren().size()); + + TreeNodeDto dto = new TreeNodeDto(); + BeanUtil.copyProperties(treeNode, dto, true); + Assert.assertEquals(2, dto.getChildren().size()); + } + + @Data + public static class TreeNodeDto { + private String id; + private String parentId; + private int sort; + private String nodeName; + private int type; + private Boolean status; + private String treeNodeId; + private TreeSet children = new TreeSet<>(Comparator.comparing(o -> o.id)); + } + + @Data + public static class TreeNode implements Comparable { + private String id; + private String parentId; + private int sort; + private String nodeName; + private int type; + private Boolean status; + private String treeNodeId; + private TreeSet children = new TreeSet<>(); + + @Override + public int compareTo(TreeNode o) { + return id.compareTo(o.getId()); + } + } +}