diff --git a/CHANGELOG.md b/CHANGELOG.md index 82628bad3..506c61ac7 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,27 @@ ------------------------------------------------------------------------------------------------------------- +# 5.8.2 (2022-05-27) + +### 🐣新特性 +* 【core 】 BeanUtil拷贝对象增加空检查(issue#I58CJ3@Gitee) +* 【db 】 Column#size改为long +* 【core 】 ClassUtil增加isInterface等方法(pr#623@Gitee) +* 【socket 】 增加ChannelUtil + +### 🐞Bug修复 +* 【extra 】 修复SshjSftp初始化未能代入端口配置问题(issue#2333@Github) +* 【core 】 修复Convert.numberToSimple转换问题(issue#2334@Github) +* 【core 】 修复TemporalAccessorConverter导致的转换问题(issue#2341@Github) +* 【core 】 修复NumberUtil除法空指针问题(issue#I58XKE@Gitee) +* 【core 】 修复CAR_VIN正则(pr#624@Gitee) +* 【db 】 修复count查询别名问题(issue#I590YB@Gitee) +* 【json 】 修复json中byte[]无法转换问题(issue#I59LW4@Gitee) +* 【core 】 修复NumberUtil.isXXX未判空问题(issue#2350@Github) +* 【core 】 修复Singleton中ConcurrentHashMap在JDK8下的bug引起的可能的死循环问题(issue#2349@Github) + +------------------------------------------------------------------------------------------------------------- + # 5.8.1 (2022-05-16) ### 🐣新特性 @@ -13,7 +34,7 @@ * 【core 】 ByteUtil新增bytesToShort重载(issue#I57FA7@Gitee) * 【core 】 ReflectUtil.invoke方法抛出运行时异常增加InvocationTargetRuntimeException(issue#I57GI2@Gitee) * 【core 】 NumberUtil.parseNumber支持16进制(issue#2328@Github) -* + ### 🐞Bug修复 * 【core 】 MapUtil.map对null友好,且修复了测试用例中分组问题(pr#614@Gitee) * 【core 】 修复BeanUtil.beanToMap中properties为null的空指针问题(issue#2303@Github) diff --git a/README-EN.md b/README-EN.md index 8759c4f23..ba12a55b5 100755 --- a/README-EN.md +++ b/README-EN.md @@ -144,18 +144,18 @@ We provide the T-Shirt and Sweater with Hutool Logo, please visit the shop: cn.hutool hutool-all - 5.8.1 + 5.8.2 ``` ### 🍐Gradle ``` -implementation 'cn.hutool:hutool-all:5.8.1' +implementation 'cn.hutool:hutool-all:5.8.2' ``` ## 📥Download -- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.1/) +- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.2/) > 🔔️note: > Hutool 5.x supports JDK8+ and is not tested on Android platforms, and cannot guarantee that all tool classes or tool methods are available. diff --git a/README.md b/README.md index 278a93ea9..007cc2d02 100755 --- a/README.md +++ b/README.md @@ -144,20 +144,20 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不 cn.hutool hutool-all - 5.8.1 + 5.8.2 ``` ### 🍐Gradle ``` -implementation 'cn.hutool:hutool-all:5.8.1' +implementation 'cn.hutool:hutool-all:5.8.2' ``` ### 📥下载jar 点击以下链接,下载`hutool-all-X.X.X.jar`即可: -- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.1/) +- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.2/) > 🔔️注意 > Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。 diff --git a/bin/version.txt b/bin/version.txt index 1802e771b..5e21ca5a8 100755 --- a/bin/version.txt +++ b/bin/version.txt @@ -1 +1 @@ -5.8.1 +5.8.2 diff --git a/docs/js/version.js b/docs/js/version.js index 5b86fe85e..f4f3726e4 100755 --- a/docs/js/version.js +++ b/docs/js/version.js @@ -1 +1 @@ -var version = '5.8.1' \ No newline at end of file +var version = '5.8.2' \ No newline at end of file diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index 26270b92e..08fef5170 100755 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-all diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml index 9cd1c6eae..fd8204903 100755 --- a/hutool-aop/pom.xml +++ b/hutool-aop/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-aop diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml index 943172ef9..8673937c2 100755 --- a/hutool-bloomFilter/pom.xml +++ b/hutool-bloomFilter/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-bloomFilter diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml index c74f0be10..4ddc45827 100755 --- a/hutool-bom/pom.xml +++ b/hutool-bom/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-bom diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml index ab99b7404..263c43fbd 100755 --- a/hutool-cache/pom.xml +++ b/hutool-cache/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-cache diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml index c3d6548dd..b86c3181b 100755 --- a/hutool-captcha/pom.xml +++ b/hutool-captcha/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-captcha diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index 5e08bcce0..a77075c94 100755 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-core diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java index 84dee2e01..401f1ee3e 100755 --- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java @@ -728,6 +728,9 @@ public class BeanUtil { * @return 目标对象 */ public static T copyProperties(Object source, Class tClass, String... ignoreProperties) { + if(null == source){ + return null; + } T target = ReflectUtil.newInstanceIfPossible(tClass); copyProperties(source, target, CopyOptions.create().setIgnoreProperties(ignoreProperties)); return target; @@ -765,6 +768,9 @@ public class BeanUtil { * @param copyOptions 拷贝选项,见 {@link CopyOptions} */ public static void copyProperties(Object source, Object target, CopyOptions copyOptions) { + if(null == source){ + return; + } BeanCopier.create(source, target, ObjectUtil.defaultIfNull(copyOptions, CopyOptions::create)).copy(); } 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 8d3fd418f..e7a5b47fe 100755 --- 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 @@ -1,5 +1,6 @@ package cn.hutool.core.bean.copier; +import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.copier.Copier; import java.io.Serializable; @@ -62,6 +63,8 @@ public class BeanCopier implements Copier, Serializable { * @param copyOptions 拷贝属性选项 */ public BeanCopier(Object source, T target, Type targetType, CopyOptions copyOptions) { + Assert.notNull(source, "Source bean must be not null!"); + Assert.notNull(target, "Target bean must be not null!"); Copier copier; if (source instanceof Map) { if (target instanceof Map) { diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/NumberWordFormatter.java b/hutool-core/src/main/java/cn/hutool/core/convert/NumberWordFormatter.java index 22c0d057b..e835593e4 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/NumberWordFormatter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/NumberWordFormatter.java @@ -63,7 +63,7 @@ public class NumberWordFormatter { int index = -1; double res = value; while (res > 10 && (false == isTwo || index < 1)) { - if (res > 1000) { + if (res >= 1000) { res = res / 1000; index++; } diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/TemporalAccessorConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/TemporalAccessorConverter.java index 46c5384e8..367d67916 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/TemporalAccessorConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/TemporalAccessorConverter.java @@ -84,6 +84,12 @@ public class TemporalAccessorConverter extends AbstractConverter getTargetType() { + return (Class) this.targetType; + } + @Override protected TemporalAccessor convertInternal(Object value) { if (value instanceof Long) { diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/RegexPool.java b/hutool-core/src/main/java/cn/hutool/core/lang/RegexPool.java index 7258c79dd..a859fddd6 100755 --- a/hutool-core/src/main/java/cn/hutool/core/lang/RegexPool.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/RegexPool.java @@ -168,7 +168,7 @@ public interface RegexPool { * 十七位码、车架号 * 车辆的唯一标示 */ - String CAR_VIN = "^[A-Za-z0-9]{17}$"; + String CAR_VIN = "^[A-HJ-NPR-Z0-9]{8}[0-9X][A-HJ-NPR-Z0-9]{2}\\d{6}$"; /** * 驾驶证 别名:驾驶证档案编号、行驶证编号 * eg:430101758218 diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/Singleton.java b/hutool-core/src/main/java/cn/hutool/core/lang/Singleton.java index 4a60648ad..ab26a662b 100755 --- a/hutool-core/src/main/java/cn/hutool/core/lang/Singleton.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/Singleton.java @@ -52,7 +52,15 @@ public final class Singleton { */ @SuppressWarnings("unchecked") public static T get(String key, Func0 supplier) { - return (T) POOL.computeIfAbsent(key, (k)-> supplier.callWithRuntimeException()); + //return (T) POOL.computeIfAbsent(key, (k)-> supplier.callWithRuntimeException()); + // issues#2349 + // ConcurrentHashMap.computeIfAbsent在某些情况下会导致死循环问题,此处采用Dubbo的解决方案 + Object value = POOL.get(key); + if(null == value){ + POOL.putIfAbsent(key, supplier.callWithRuntimeException()); + value = POOL.get(key); + } + return (T) value; } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ClassUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ClassUtil.java index e697fed49..0d7479b5e 100755 --- a/hutool-core/src/main/java/cn/hutool/core/util/ClassUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ClassUtil.java @@ -1110,4 +1110,26 @@ public class ClassUtil { } return location.getPath(); } + + /** + * 是否为抽象类或接口 + * + * @param clazz 类 + * @return 是否为抽象类或接口 + * @since 5.8.2 + */ + public static boolean isAbstractOrInterface(Class clazz) { + return isAbstract(clazz) || isInterface(clazz); + } + + /** + * 是否为接口 + * + * @param clazz 类 + * @return 是否为接口 + * @since 5.8.2 + */ + public static boolean isInterface(Class clazz) { + return clazz.isInterface(); + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java index 5b40c361f..953131578 100755 --- a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java @@ -719,7 +719,7 @@ public class NumberUtil { if (v1 instanceof BigDecimal && v2 instanceof BigDecimal) { return div((BigDecimal) v1, (BigDecimal) v2, scale, roundingMode); } - return div(v1.toString(), v2.toString(), scale, roundingMode); + return div(StrUtil.toStringOrNull(v1), StrUtil.toStringOrNull(v2), scale, roundingMode); } /** @@ -1238,10 +1238,12 @@ public class NumberUtil { * @return 是否为整数 */ public static boolean isInteger(String s) { - try { - Integer.parseInt(s); - } catch (NumberFormatException e) { - return false; + if(StrUtil.isNotBlank(s)) { + try { + Integer.parseInt(s); + } catch (NumberFormatException e) { + return false; + } } return true; } @@ -1255,10 +1257,12 @@ public class NumberUtil { * @since 4.0.0 */ public static boolean isLong(String s) { - try { - Long.parseLong(s); - } catch (NumberFormatException e) { - return false; + if(StrUtil.isNotBlank(s)) { + try { + Long.parseLong(s); + } catch (NumberFormatException e) { + return false; + } } return true; } @@ -1270,11 +1274,13 @@ public class NumberUtil { * @return 是否为{@link Double}类型 */ public static boolean isDouble(String s) { - try { - Double.parseDouble(s); - return s.contains("."); - } catch (NumberFormatException ignore) { - // ignore + if(StrUtil.isNotBlank(s)) { + try { + Double.parseDouble(s); + return s.contains("."); + } catch (NumberFormatException ignore) { + // ignore + } } return false; } diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java index 60f602fe0..06526b7f5 100755 --- a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java @@ -567,6 +567,11 @@ public class BeanUtilTest { Assert.assertNull(newFood.getCode()); } + @Test + public void copyNullTest() { + Assert.assertNull(BeanUtil.copyProperties(null, Food.class)); + } + @Test public void copyBeanPropertiesFilterTest() { Food info = new Food(); diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java index 18cd78b14..89ab9421f 100755 --- a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java @@ -15,6 +15,8 @@ import org.junit.Test; import java.io.Serializable; import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; @@ -383,4 +385,11 @@ public class ConvertTest { float b = Convert.toFloat(a); Assert.assertEquals(a, b, 5); } + + @Test + public void localDateTimeToLocalDateTest(){ + final LocalDateTime localDateTime = LocalDateTime.now(); + final LocalDate convert = Convert.convert(LocalDate.class, localDateTime); + Assert.assertEquals(localDateTime.toLocalDate(), convert); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/NumberWordFormatTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/NumberWordFormatTest.java index 629205404..802d621c4 100644 --- a/hutool-core/src/test/java/cn/hutool/core/convert/NumberWordFormatTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/convert/NumberWordFormatTest.java @@ -31,4 +31,10 @@ public class NumberWordFormatTest { String format5 = NumberWordFormatter.formatSimple(438); Assert.assertEquals("438", format5); } + + @Test + public void formatSimpleTest2(){ + final String s = NumberWordFormatter.formatSimple(1000); + Assert.assertEquals("1k", s); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/ValidatorTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/ValidatorTest.java index bfd6c7ddb..11da7f5fd 100755 --- a/hutool-core/src/test/java/cn/hutool/core/lang/ValidatorTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/ValidatorTest.java @@ -221,6 +221,7 @@ public class ValidatorTest { public void isCarVinTest(){ Assert.assertTrue(Validator.isCarVin("LSJA24U62JG269225")); Assert.assertTrue(Validator.isCarVin("LDC613P23A1305189")); + Assert.assertFalse(Validator.isCarVin("LOC613P23A1305189")); } @Test diff --git a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java index f3a8e4859..1dd645aa9 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java @@ -439,6 +439,16 @@ public class NumberUtilTest { Assert.assertFalse(NumberUtil.isEven(a[4])); } + @Test + public void divIntegerTest(){ + Assert.assertEquals(1001013, NumberUtil.div(100101300, (Number) 100).intValue()); + } + @Test + public void isDoubleTest(){ + Assert.assertFalse(NumberUtil.isDouble(null)); + Assert.assertFalse(NumberUtil.isDouble("")); + Assert.assertFalse(NumberUtil.isDouble(" ")); + } } diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml index 02d3d1493..a8aeec0a4 100755 --- a/hutool-cron/pom.xml +++ b/hutool-cron/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-cron diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml index 5723a93b5..e95c5f7ba 100755 --- a/hutool-crypto/pom.xml +++ b/hutool-crypto/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-crypto diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index 44776cba6..980de2c18 100755 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-db @@ -22,12 +22,12 @@ 2.9.0 10.0.20 1.2.9 - 2.4.13 + 4.0.3 4.6.0 3.36.0.3 2.5.2 - 4.2.2 + 4.2.3 @@ -62,7 +62,7 @@ com.zaxxer - HikariCP-java7 + HikariCP ${hikariCP.version} @@ -156,7 +156,7 @@ com.microsoft.sqlserver mssql-jdbc - 10.2.0.jre8 + 10.2.1.jre8 test diff --git a/hutool-db/src/main/java/cn/hutool/db/dialect/Dialect.java b/hutool-db/src/main/java/cn/hutool/db/dialect/Dialect.java index 6ad5922bd..7f0ca07a5 100644 --- a/hutool-db/src/main/java/cn/hutool/db/dialect/Dialect.java +++ b/hutool-db/src/main/java/cn/hutool/db/dialect/Dialect.java @@ -1,6 +1,5 @@ package cn.hutool.db.dialect; -import cn.hutool.core.collection.ListUtil; import cn.hutool.db.Entity; import cn.hutool.db.Page; import cn.hutool.db.sql.Order; @@ -134,8 +133,7 @@ public interface Dialect extends Serializable { * @throws SQLException SQL执行异常 */ default PreparedStatement psForCount(Connection conn, Query query) throws SQLException { - query.setFields(ListUtil.toList("count(1)")); - return psForFind(conn, query); + return psForCount(conn, SqlBuilder.create().query(query)); } /** diff --git a/hutool-db/src/main/java/cn/hutool/db/meta/Column.java b/hutool-db/src/main/java/cn/hutool/db/meta/Column.java index 362d20ee8..6a13bec35 100755 --- a/hutool-db/src/main/java/cn/hutool/db/meta/Column.java +++ b/hutool-db/src/main/java/cn/hutool/db/meta/Column.java @@ -37,7 +37,7 @@ public class Column implements Serializable, Cloneable { /** * 大小或数据长度 */ - private int size; + private long size; private Integer digit; /** * 是否为可空 @@ -118,7 +118,7 @@ public class Column implements Serializable, Cloneable { typeName = ReUtil.delLast("\\(\\d+\\)", typeName); this.typeName = typeName; - this.size = columnMetaRs.getInt("COLUMN_SIZE"); + this.size = columnMetaRs.getLong("COLUMN_SIZE"); this.isNullable = columnMetaRs.getBoolean("NULLABLE"); this.comment = columnMetaRs.getString("REMARKS"); this.columnDef = columnMetaRs.getString("COLUMN_DEF"); @@ -238,7 +238,7 @@ public class Column implements Serializable, Cloneable { * * @return 大小或数据长度 */ - public int getSize() { + public long getSize() { return size; } diff --git a/hutool-db/src/test/java/cn/hutool/db/DbTest.java b/hutool-db/src/test/java/cn/hutool/db/DbTest.java index 1002b602e..5419097a2 100644 --- a/hutool-db/src/test/java/cn/hutool/db/DbTest.java +++ b/hutool-db/src/test/java/cn/hutool/db/DbTest.java @@ -70,6 +70,12 @@ public class DbTest { Assert.assertEquals(4, count); } + @Test + public void countByQueryTest() throws SQLException { + final long count = Db.use().count(Entity.create("user")); + Assert.assertEquals(4, count); + } + @Test public void countTest2() throws SQLException { final long count = Db.use().count("select * from user order by name DESC"); diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml index 7fb33051d..1e58ac750 100755 --- a/hutool-dfa/pom.xml +++ b/hutool-dfa/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-dfa diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index f8f9315ec..c454355e7 100755 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-extra diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ssh/SshjSftp.java b/hutool-extra/src/main/java/cn/hutool/extra/ssh/SshjSftp.java index d458420c1..7e59d9077 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/ssh/SshjSftp.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/ssh/SshjSftp.java @@ -102,7 +102,7 @@ public class SshjSftp extends AbstractFtp { this.ssh = new SSHClient(); ssh.addHostKeyVerifier(new PromiscuousVerifier()); try { - ssh.connect(ftpConfig.getHost()); + ssh.connect(ftpConfig.getHost(), ftpConfig.getPort()); ssh.authPassword(ftpConfig.getUser(), ftpConfig.getPassword()); ssh.setRemoteCharset(ftpConfig.getCharset()); this.sftp = ssh.newSFTPClient(); diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index 6a9c1b045..7513e02a6 100755 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-http diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index a87d5ac09..884310ec1 100755 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-json diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java b/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java index 674ee98d1..4e91df9bd 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java @@ -1,6 +1,7 @@ package cn.hutool.json; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.codec.Base64; import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.ConvertException; import cn.hutool.core.convert.Converter; @@ -85,6 +86,9 @@ public class JSONConverter implements Converter { } target.parse(value); return (T) target; + } else if(targetType == byte[].class && value instanceof CharSequence){ + // issue#I59LW4 + return (T) Base64.decode((CharSequence) value); } } diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONGetter.java b/hutool-json/src/main/java/cn/hutool/json/JSONGetter.java index 00e2aa507..b2eb31764 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONGetter.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONGetter.java @@ -190,6 +190,17 @@ public interface JSONGetter extends OptNullBasicTypeFromObjectGetter { return Convert.toLocalDateTime(obj, defaultValue); } + /** + * 获取byte[]数据 + * + * @param key 键 + * @return 值 + * @since 5.8.2 + */ + default byte[] getBytes(K key) { + return get(key, byte[].class); + } + /** * 获取指定类型的对象
* 转换失败或抛出异常 diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java b/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java index 7938ed3c6..97715c113 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java @@ -1,5 +1,6 @@ package cn.hutool.json; +import cn.hutool.core.codec.Base64; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.file.FileReader; import cn.hutool.core.lang.TypeReference; @@ -784,6 +785,12 @@ public class JSONUtil { // JSONArray if (object instanceof Iterable || ArrayUtil.isArray(object)) { + if(object instanceof byte[]){ + // issue#I59LW4 + // json内容中的bytes默认转为Base64 + return Base64.encode((byte[]) object); + } + return new JSONArray(object, jsonConfig); } // JSONObject diff --git a/hutool-json/src/main/java/cn/hutool/json/ObjectMapper.java b/hutool-json/src/main/java/cn/hutool/json/ObjectMapper.java index 6d7f9761e..c8eeea2a1 100755 --- a/hutool-json/src/main/java/cn/hutool/json/ObjectMapper.java +++ b/hutool-json/src/main/java/cn/hutool/json/ObjectMapper.java @@ -144,6 +144,7 @@ public class ObjectMapper { } else if (source instanceof InputStream) { mapFromTokener(new JSONTokener((InputStream) source, jsonArray.getConfig()), jsonArray, filter); } else if (source instanceof byte[]) { + // bytes按照JSON的二进制流对待 mapFromTokener(new JSONTokener(IoUtil.toStream((byte[]) source), jsonArray.getConfig()), jsonArray, filter); } else if (source instanceof JSONTokener) { mapFromTokener((JSONTokener) source, jsonArray, filter); diff --git a/hutool-json/src/main/java/cn/hutool/json/serialize/JSONWriter.java b/hutool-json/src/main/java/cn/hutool/json/serialize/JSONWriter.java index b38a5c7a9..38cce600d 100755 --- a/hutool-json/src/main/java/cn/hutool/json/serialize/JSONWriter.java +++ b/hutool-json/src/main/java/cn/hutool/json/serialize/JSONWriter.java @@ -1,5 +1,6 @@ package cn.hutool.json.serialize; +import cn.hutool.core.codec.Base64; import cn.hutool.core.convert.Convert; import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.TemporalAccessorUtil; @@ -167,7 +168,6 @@ public class JSONWriter extends Writer { if(JSONUtil.isNull(value) && config.isIgnoreNullValue()){ return this; } - return writeKey(key).writeValueDirect(value); } @@ -226,7 +226,13 @@ public class JSONWriter extends Writer { } else if (value instanceof Map || value instanceof Map.Entry) { new JSONObject(value).write(writer, indentFactor, indent); } else if (value instanceof Iterable || value instanceof Iterator || ArrayUtil.isArray(value)) { - new JSONArray(value).write(writer, indentFactor, indent); + if(value instanceof byte[]){ + // issue#I59LW4 + // json内容中的bytes默认转为Base64 + writeStrValue(Base64.encode((byte[]) value)); + }else{ + new JSONArray(value).write(writer, indentFactor, indent); + } } else if (value instanceof Number) { writeNumberValue((Number) value); } else if (value instanceof Date || value instanceof Calendar || value instanceof TemporalAccessor) { diff --git a/hutool-json/src/test/java/cn/hutool/json/IssueI59LW4Test.java b/hutool-json/src/test/java/cn/hutool/json/IssueI59LW4Test.java new file mode 100644 index 000000000..7425821fd --- /dev/null +++ b/hutool-json/src/test/java/cn/hutool/json/IssueI59LW4Test.java @@ -0,0 +1,25 @@ +package cn.hutool.json; + +import org.junit.Assert; +import org.junit.Test; + +public class IssueI59LW4Test { + + @Test + public void bytesTest(){ + final JSONObject jsonObject = JSONUtil.createObj().set("bytes", new byte[]{1}); + Assert.assertEquals("{\"bytes\":\"AQ==\"}", jsonObject.toString()); + + final byte[] bytes = jsonObject.getBytes("bytes"); + Assert.assertArrayEquals(new byte[]{1}, bytes); + } + + @Test + public void bytesInJSONArrayTest(){ + final JSONArray jsonArray = JSONUtil.createArray().set(new byte[]{1}); + Assert.assertEquals("[\"AQ==\"]", jsonArray.toString()); + + final byte[] bytes = jsonArray.getBytes(0); + Assert.assertArrayEquals(new byte[]{1}, bytes); + } +} diff --git a/hutool-jwt/pom.xml b/hutool-jwt/pom.xml index dbf7ca3f9..91cc4cd97 100755 --- a/hutool-jwt/pom.xml +++ b/hutool-jwt/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-jwt diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index 48dbfc344..ac384e580 100755 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-log diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index 2940278bb..93378c39d 100755 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-poi diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml index d01af5420..2d43092fc 100755 --- a/hutool-script/pom.xml +++ b/hutool-script/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-script diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml index 655a3a1e8..46f89eaa9 100755 --- a/hutool-setting/pom.xml +++ b/hutool-setting/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-setting diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml index b700c75a4..575a2040b 100755 --- a/hutool-socket/pom.xml +++ b/hutool-socket/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-socket diff --git a/hutool-socket/src/main/java/cn/hutool/socket/ChannelUtil.java b/hutool-socket/src/main/java/cn/hutool/socket/ChannelUtil.java new file mode 100644 index 000000000..cf105a629 --- /dev/null +++ b/hutool-socket/src/main/java/cn/hutool/socket/ChannelUtil.java @@ -0,0 +1,62 @@ +package cn.hutool.socket; + +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.thread.ThreadFactoryBuilder; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.channels.AsynchronousChannelGroup; +import java.nio.channels.AsynchronousSocketChannel; +import java.util.concurrent.ExecutionException; + +/** + * Channel相关封装 + * + * @author looly + * @since 5.8.2 + */ +public class ChannelUtil { + + /** + * 创建{@link AsynchronousChannelGroup} + * + * @param poolSize 线程池大小 + * @return {@link AsynchronousChannelGroup} + */ + public static AsynchronousChannelGroup createFixedGroup(int poolSize) { + + try { + return AsynchronousChannelGroup.withFixedThreadPool(// + poolSize, // 默认线程池大小 + ThreadFactoryBuilder.create().setNamePrefix("Huool-socket-").build()// + ); + } catch (IOException e) { + throw new IORuntimeException(e); + } + } + + /** + * 连接到指定地址 + * + * @param group {@link AsynchronousChannelGroup} + * @param address 地址信息,包括地址和端口 + * @return {@link AsynchronousSocketChannel} + */ + public static AsynchronousSocketChannel connect(AsynchronousChannelGroup group, InetSocketAddress address) { + AsynchronousSocketChannel channel; + try { + channel = AsynchronousSocketChannel.open(group); + } catch (IOException e) { + throw new IORuntimeException(e); + } + + try { + channel.connect(address).get(); + } catch (InterruptedException | ExecutionException e) { + IoUtil.close(channel); + throw new SocketRuntimeException(e); + } + return channel; + } +} diff --git a/hutool-socket/src/main/java/cn/hutool/socket/aio/AioClient.java b/hutool-socket/src/main/java/cn/hutool/socket/aio/AioClient.java index 2fb37713d..9e15f30e5 100644 --- a/hutool-socket/src/main/java/cn/hutool/socket/aio/AioClient.java +++ b/hutool-socket/src/main/java/cn/hutool/socket/aio/AioClient.java @@ -1,19 +1,14 @@ package cn.hutool.socket.aio; -import cn.hutool.core.io.IORuntimeException; -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.thread.ThreadFactoryBuilder; +import cn.hutool.socket.ChannelUtil; import cn.hutool.socket.SocketConfig; -import cn.hutool.socket.SocketRuntimeException; import java.io.Closeable; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketOption; import java.nio.ByteBuffer; -import java.nio.channels.AsynchronousChannelGroup; import java.nio.channels.AsynchronousSocketChannel; -import java.util.concurrent.ExecutionException; /** * Aio Socket客户端 @@ -120,25 +115,7 @@ public class AioClient implements Closeable{ * @return this */ private static AsynchronousSocketChannel createChannel(InetSocketAddress address, int poolSize) { - - AsynchronousSocketChannel channel; - try { - AsynchronousChannelGroup group = AsynchronousChannelGroup.withFixedThreadPool(// - poolSize, // 默认线程池大小 - ThreadFactoryBuilder.create().setNamePrefix("Huool-socket-").build()// - ); - channel = AsynchronousSocketChannel.open(group); - } catch (IOException e) { - throw new IORuntimeException(e); - } - - try { - channel.connect(address).get(); - } catch (InterruptedException | ExecutionException e) { - IoUtil.close(channel); - throw new SocketRuntimeException(e); - } - return channel; + return ChannelUtil.connect(ChannelUtil.createFixedGroup(poolSize), address); } // ------------------------------------------------------------------------------------- Private method end } diff --git a/hutool-socket/src/test/java/cn/hutool/socket/aio/AioClientTest.java b/hutool-socket/src/test/java/cn/hutool/socket/aio/AioClientTest.java index f0694a080..1a53476d8 100755 --- a/hutool-socket/src/test/java/cn/hutool/socket/aio/AioClientTest.java +++ b/hutool-socket/src/test/java/cn/hutool/socket/aio/AioClientTest.java @@ -1,15 +1,23 @@ package cn.hutool.socket.aio; import cn.hutool.core.lang.Console; +import cn.hutool.core.thread.ThreadFactoryBuilder; import cn.hutool.core.util.StrUtil; +import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; +import java.nio.channels.AsynchronousChannelGroup; public class AioClientTest { - public static void main(String[] args) { + public static void main(String[] args) throws IOException { + final AsynchronousChannelGroup GROUP = AsynchronousChannelGroup.withFixedThreadPool(// + Runtime.getRuntime().availableProcessors(), // 默认线程池大小 + ThreadFactoryBuilder.create().setNamePrefix("Huool-socket-").build()// + ); + AioClient client = new AioClient(new InetSocketAddress("localhost", 8899), new SimpleIoAction() { - + @Override public void doAction(AioSession session, ByteBuffer data) { if(data.hasRemaining()) { @@ -19,10 +27,10 @@ public class AioClientTest { Console.log("OK"); } }); - + client.write(ByteBuffer.wrap("Hello".getBytes())); client.read(); - + client.close(); } } diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml index cea4cd544..010c18d99 100755 --- a/hutool-system/pom.xml +++ b/hutool-system/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool-system diff --git a/pom.xml b/pom.xml index ba4a3b432..e5c7eb393 100755 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.8.1 + 5.8.2 hutool Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。 https://github.com/dromara/hutool