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