From 612884e0f6561742547136b76f7d855302d68a52 Mon Sep 17 00:00:00 2001
From: looly
Date: Wed, 24 Nov 2021 09:35:50 +0800
Subject: [PATCH 01/29] fix code
---
hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java | 2 ++
.../src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java
index a43a053dc..d71606139 100644
--- a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java
@@ -1624,7 +1624,9 @@ public class DateUtil extends CalendarUtil {
*
* @param date 日期
* @return int
+ * @deprecated 2022年后结果溢出,此方法废弃
*/
+ @Deprecated
public static int toIntSecond(Date date) {
return Integer.parseInt(DateUtil.format(date, "yyMMddHHmm"));
}
diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java
index 8d1bf84f2..e742e8fa1 100644
--- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java
+++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java
@@ -56,7 +56,7 @@ public class Excel07SaxReader implements ExcelSaxReader {
@Override
public Excel07SaxReader read(File file, String idOrRidOrSheetName) throws POIException {
- try (OPCPackage open = OPCPackage.open(file, PackageAccess.READ);){
+ try (OPCPackage open = OPCPackage.open(file, PackageAccess.READ)){
return read(open, idOrRidOrSheetName);
} catch (InvalidFormatException | IOException e) {
throw new POIException(e);
From 1e82d7bd5f6905b1051b05a1ba6e5d505490e697 Mon Sep 17 00:00:00 2001
From: looly
Date: Wed, 24 Nov 2021 09:36:56 +0800
Subject: [PATCH 02/29] fix code
---
CHANGELOG.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index be9effe61..1273f46f2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,7 @@
-------------------------------------------------------------------------------------------------------------
-# 5.7.17 (2021-11-20)
+# 5.7.17 (2021-11-24)
### 🐣新特性
* 【core 】 增加AsyncUtil(pr#457@Gitee)
@@ -21,6 +21,7 @@
* 【core 】 ResourceClassLoader增加缓存(pr#1959@Github)
* 【crypto 】 增加CipherWrapper,增加setRandom(issue#1958@Github)
* 【core 】 Opt增加ofTry方法(pr#1956@Github)
+* 【core 】 DateUtil.toIntSecond标记为弃用(issue#I4JHPR@Gitee)
*
### 🐞Bug修复
* 【core 】 修复FileResource构造fileName参数无效问题(issue#1942@Github)
From 3a043a261e90c6f9cc281b880820cecaba918eb6 Mon Sep 17 00:00:00 2001
From: looly
Date: Wed, 24 Nov 2021 09:53:34 +0800
Subject: [PATCH 03/29] deprecated code
---
CHANGELOG.md | 1 +
.../main/java/cn/hutool/db/AbstractDb.java | 2 +
.../java/cn/hutool/db/sql/SqlExecutor.java | 44 ++++++++++---------
3 files changed, 26 insertions(+), 21 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1273f46f2..e4ab637d5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,7 @@
* 【crypto 】 增加CipherWrapper,增加setRandom(issue#1958@Github)
* 【core 】 Opt增加ofTry方法(pr#1956@Github)
* 【core 】 DateUtil.toIntSecond标记为弃用(issue#I4JHPR@Gitee)
+* 【db 】 Db.executeBatch标记一个重载为弃用(issue#I4JIPH@Gitee)
*
### 🐞Bug修复
* 【core 】 修复FileResource构造fileName参数无效问题(issue#1942@Github)
diff --git a/hutool-db/src/main/java/cn/hutool/db/AbstractDb.java b/hutool-db/src/main/java/cn/hutool/db/AbstractDb.java
index 77c20fcc4..0c40d4de2 100644
--- a/hutool-db/src/main/java/cn/hutool/db/AbstractDb.java
+++ b/hutool-db/src/main/java/cn/hutool/db/AbstractDb.java
@@ -239,7 +239,9 @@ public abstract class AbstractDb implements Serializable {
* @param paramsBatch 批量的参数
* @return 每个SQL执行影响的行数
* @throws SQLException SQL执行异常
+ * @deprecated 编译器无法区分重载
*/
+ @Deprecated
public int[] executeBatch(String sql, Object[]... paramsBatch) throws SQLException {
Connection conn = null;
try {
diff --git a/hutool-db/src/main/java/cn/hutool/db/sql/SqlExecutor.java b/hutool-db/src/main/java/cn/hutool/db/sql/SqlExecutor.java
index a64973625..e3aa4439b 100644
--- a/hutool-db/src/main/java/cn/hutool/db/sql/SqlExecutor.java
+++ b/hutool-db/src/main/java/cn/hutool/db/sql/SqlExecutor.java
@@ -16,7 +16,7 @@ import java.util.Map;
/**
* SQL执行器,全部为静态方法,执行查询或非查询的SQL语句
* 此方法为JDBC的简单封装,与数据库类型无关
- *
+ *
* @author loolly
*
*/
@@ -26,7 +26,7 @@ public class SqlExecutor {
* 执行非查询语句
* 语句包括 插入、更新、删除
* 此方法不会关闭Connection
- *
+ *
* @param conn 数据库连接对象
* @param sql SQL,使用name做为占位符,例如:name
* @param paramMap 参数Map
@@ -43,7 +43,7 @@ public class SqlExecutor {
* 执行非查询语句
* 语句包括 插入、更新、删除
* 此方法不会关闭Connection
- *
+ *
* @param conn 数据库连接对象
* @param sql SQL
* @param params 参数
@@ -63,7 +63,7 @@ public class SqlExecutor {
/**
* 执行调用存储过程
* 此方法不会关闭Connection
- *
+ *
* @param conn 数据库连接对象
* @param sql SQL
* @param params 参数
@@ -83,7 +83,7 @@ public class SqlExecutor {
/**
* 执行调用存储过程
* 此方法不会关闭Connection
- *
+ *
* @param conn 数据库连接对象
* @param sql SQL
* @param params 参数
@@ -99,7 +99,7 @@ public class SqlExecutor {
* 执行非查询语句,返回主键
* 发查询语句包括 插入、更新、删除
* 此方法不会关闭Connection
- *
+ *
* @param conn 数据库连接对象
* @param sql SQL
* @param paramMap 参数Map
@@ -116,7 +116,7 @@ public class SqlExecutor {
* 执行非查询语句,返回主键
* 发查询语句包括 插入、更新、删除
* 此方法不会关闭Connection
- *
+ *
* @param conn 数据库连接对象
* @param sql SQL
* @param params 参数
@@ -148,22 +148,24 @@ public class SqlExecutor {
* 批量执行非查询语句
* 语句包括 插入、更新、删除
* 此方法不会关闭Connection
- *
+ *
* @param conn 数据库连接对象
* @param sql SQL
* @param paramsBatch 批量的参数
* @return 每个SQL执行影响的行数
* @throws SQLException SQL执行异常
+ * @deprecated 重载导致编译器无法区分
*/
+ @Deprecated
public static int[] executeBatch(Connection conn, String sql, Object[]... paramsBatch) throws SQLException {
return executeBatch(conn, sql, new ArrayIter<>(paramsBatch));
}
-
+
/**
* 批量执行非查询语句
* 语句包括 插入、更新、删除
* 此方法不会关闭Connection
- *
+ *
* @param conn 数据库连接对象
* @param sql SQL
* @param paramsBatch 批量的参数
@@ -179,12 +181,12 @@ public class SqlExecutor {
DbUtil.close(ps);
}
}
-
+
/**
* 批量执行非查询语句
* 语句包括 插入、更新、删除
* 此方法不会关闭Connection
- *
+ *
* @param conn 数据库连接对象
* @param sqls SQL列表
* @return 每个SQL执行影响的行数
@@ -194,12 +196,12 @@ public class SqlExecutor {
public static int[] executeBatch(Connection conn, String... sqls) throws SQLException {
return executeBatch(conn, new ArrayIter<>(sqls));
}
-
+
/**
* 批量执行非查询语句
* 语句包括 插入、更新、删除
* 此方法不会关闭Connection
- *
+ *
* @param conn 数据库连接对象
* @param sqls SQL列表
* @return 每个SQL执行影响的行数
@@ -222,7 +224,7 @@ public class SqlExecutor {
/**
* 执行查询语句,例如:select * from table where field1=:name1
* 此方法不会关闭Connection
- *
+ *
* @param 处理结果类型
* @param conn 数据库连接对象
* @param sql 查询语句,使用参数名占位符,例如:name
@@ -240,7 +242,7 @@ public class SqlExecutor {
/**
* 执行查询语句
* 此方法不会关闭Connection
- *
+ *
* @param 处理结果类型
* @param conn 数据库连接对象
* @param sql 查询语句
@@ -282,7 +284,7 @@ public class SqlExecutor {
* executeUpdate 的返回值是一个整数(int),指示受影响的行数(即更新计数)。
* 对于 CREATE TABLE 或 DROP TABLE 等不操作行的语句,executeUpdate 的返回值总为零。
* 此方法不会关闭PreparedStatement
- *
+ *
* @param ps PreparedStatement对象
* @param params 参数
* @return 影响的行数
@@ -297,7 +299,7 @@ public class SqlExecutor {
* 可用于执行任何SQL语句,返回一个boolean值,表明执行该SQL语句是否返回了ResultSet。
* 如果执行后第一个结果是ResultSet,则返回true,否则返回false。
* 此方法不会关闭PreparedStatement
- *
+ *
* @param ps PreparedStatement对象
* @param params 参数
* @return 如果执行后第一个结果是ResultSet,则返回true,否则返回false。
@@ -311,7 +313,7 @@ public class SqlExecutor {
/**
* 执行查询语句
* 此方法不会关闭PreparedStatement
- *
+ *
* @param 处理结果类型
* @param ps PreparedStatement
* @param rsh 结果集处理对象
@@ -326,7 +328,7 @@ public class SqlExecutor {
/**
* 执行查询语句并关闭PreparedStatement
- *
+ *
* @param 处理结果类型
* @param ps PreparedStatement
* @param rsh 结果集处理对象
@@ -345,7 +347,7 @@ public class SqlExecutor {
// -------------------------------------------------------------------------------------------------------------------------------- Private method start
/**
* 执行查询
- *
+ *
* @param ps {@link PreparedStatement}
* @param rsh 结果集处理对象
* @return 结果对象
From b2804a15c22dabc2f10c9fb8f17859500182d468 Mon Sep 17 00:00:00 2001
From: sunhao
Date: Wed, 24 Nov 2021 11:09:44 +0800
Subject: [PATCH 04/29] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dbug=E3=80=90=E5=B9=B6?=
=?UTF-8?q?=E5=8F=91=E6=B5=8B=E8=AF=95=E5=90=8E=E6=9C=AA=E5=85=B3=E9=97=AD?=
=?UTF-8?q?=E7=BA=BF=E7=A8=8B=E6=B1=A0=E3=80=91=E3=80=81=E5=88=A0=E9=99=A4?=
=?UTF-8?q?=E9=83=A8=E5=88=86=E6=97=A0=E6=84=8F=E4=B9=89=E6=B3=A8=E9=87=8A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/cn/hutool/core/thread/ConcurrencyTester.java | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/hutool-core/src/main/java/cn/hutool/core/thread/ConcurrencyTester.java b/hutool-core/src/main/java/cn/hutool/core/thread/ConcurrencyTester.java
index 9b53d4f34..1accd2368 100644
--- a/hutool-core/src/main/java/cn/hutool/core/thread/ConcurrencyTester.java
+++ b/hutool-core/src/main/java/cn/hutool/core/thread/ConcurrencyTester.java
@@ -40,10 +40,12 @@ public class ConcurrencyTester {
this.sf.clearWorker();
timeInterval.start();
- this.sf//
- .addRepeatWorker(runnable)//
- .setBeginAtSameTime(true)// 同时开始
+ this.sf
+ .addRepeatWorker(runnable)
+ .setBeginAtSameTime(true)
.start();
+ // 停止线程池释放资源,避免空跑
+ this.sf.stop();
this.interval = timeInterval.interval();
return this;
From ff8317dd8c597fe175a9d8e310acfc3b3a2714b6 Mon Sep 17 00:00:00 2001
From: looly
Date: Wed, 24 Nov 2021 15:39:31 +0800
Subject: [PATCH 05/29] fix code
---
.../hutool/core/thread/ConcurrencyTester.java | 18 ++++++++++++++----
.../cn/hutool/core/thread/SyncFinisher.java | 9 ++++++++-
2 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/hutool-core/src/main/java/cn/hutool/core/thread/ConcurrencyTester.java b/hutool-core/src/main/java/cn/hutool/core/thread/ConcurrencyTester.java
index 1accd2368..f0cdd33b5 100644
--- a/hutool-core/src/main/java/cn/hutool/core/thread/ConcurrencyTester.java
+++ b/hutool-core/src/main/java/cn/hutool/core/thread/ConcurrencyTester.java
@@ -2,6 +2,9 @@ package cn.hutool.core.thread;
import cn.hutool.core.date.TimeInterval;
+import java.io.Closeable;
+import java.io.IOException;
+
/**
* 高并发测试工具类
*
@@ -12,11 +15,14 @@ import cn.hutool.core.date.TimeInterval;
* ct.test(() -> {
* // 需要并发测试的业务代码
* });
+ *
+ * Console.log(ct.getInterval());
+ * ct.close();
*
*
* @author kwer
*/
-public class ConcurrencyTester {
+public class ConcurrencyTester implements Closeable {
private final SyncFinisher sf;
private final TimeInterval timeInterval;
private long interval;
@@ -31,7 +37,8 @@ public class ConcurrencyTester {
}
/**
- * 执行测试
+ * 执行测试
+ * 执行测试后不会关闭线程池,可以调用{@link #close()}释放线程池
*
* @param runnable 要测试的内容
* @return this
@@ -44,8 +51,6 @@ public class ConcurrencyTester {
.addRepeatWorker(runnable)
.setBeginAtSameTime(true)
.start();
- // 停止线程池释放资源,避免空跑
- this.sf.stop();
this.interval = timeInterval.interval();
return this;
@@ -76,4 +81,9 @@ public class ConcurrencyTester {
public long getInterval() {
return this.interval;
}
+
+ @Override
+ public void close() throws IOException {
+ this.sf.close();
+ }
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/thread/SyncFinisher.java b/hutool-core/src/main/java/cn/hutool/core/thread/SyncFinisher.java
index 18ad5fad5..512c0d89b 100644
--- a/hutool-core/src/main/java/cn/hutool/core/thread/SyncFinisher.java
+++ b/hutool-core/src/main/java/cn/hutool/core/thread/SyncFinisher.java
@@ -2,6 +2,8 @@ package cn.hutool.core.thread;
import cn.hutool.core.exceptions.UtilException;
+import java.io.Closeable;
+import java.io.IOException;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
@@ -25,7 +27,7 @@ import java.util.concurrent.ExecutorService;
* @author Looly
* @since 4.1.15
*/
-public class SyncFinisher {
+public class SyncFinisher implements Closeable {
private final Set workers;
private final int threadSize;
@@ -173,6 +175,11 @@ public class SyncFinisher {
return endLatch.getCount();
}
+ @Override
+ public void close() throws IOException {
+ stop();
+ }
+
/**
* 工作者,为一个线程
*
From 30515f03518e417dfda4a83383f39e311f14e721 Mon Sep 17 00:00:00 2001
From: Looly
Date: Wed, 24 Nov 2021 23:10:59 +0800
Subject: [PATCH 06/29] add method
---
CHANGELOG.md | 1 +
.../cn/hutool/core/text/CharSequenceUtil.java | 27 +++++++++++++++----
.../core/text/CharSequenceUtilTest.java | 13 +++++++++
3 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e4ab637d5..1dbe0b555 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,7 @@
* 【core 】 Opt增加ofTry方法(pr#1956@Github)
* 【core 】 DateUtil.toIntSecond标记为弃用(issue#I4JHPR@Gitee)
* 【db 】 Db.executeBatch标记一个重载为弃用(issue#I4JIPH@Gitee)
+* 【core 】 增加CharSequenceUtil.subPreGbk重载(issue#I4JO2E@Gitee)
*
### 🐞Bug修复
* 【core 】 修复FileResource构造fileName参数无效问题(issue#1942@Github)
diff --git a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java
index 8310c72de..15a07faff 100644
--- a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java
@@ -1979,19 +1979,32 @@ public class CharSequenceUtil {
* 截取部分字符串,这里一个汉字的长度认为是2
*
* @param str 字符串
- * @param len 切割的位置
+ * @param len bytes切割到的位置(包含)
* @param suffix 切割后加上后缀
* @return 切割后的字符串
* @since 3.1.1
*/
public static String subPreGbk(CharSequence str, int len, CharSequence suffix) {
+ return subPreGbk(str, len, true) + suffix;
+ }
+
+ /**
+ * 截取部分字符串,这里一个汉字的长度认为是2
+ * 可以自定义halfUp,如len为10,如果截取后最后一个字符是半个字符,{@code true}表示保留,则长度是11,否则长度9
+ *
+ * @param str 字符串
+ * @param len bytes切割到的位置(包含)
+ * @param halfUp 遇到截取一半的GBK字符,是否保留。
+ * @return 切割后的字符串
+ * @since 5.7.17
+ */
+ public static String subPreGbk(CharSequence str, int len, boolean halfUp) {
if (isEmpty(str)) {
return str(str);
}
- byte[] b;
int counterOfDoubleByte = 0;
- b = str.toString().getBytes(CharsetUtil.CHARSET_GBK);
+ final byte[] b = bytes(str, CharsetUtil.CHARSET_GBK);
if (b.length <= len) {
return str.toString();
}
@@ -2002,9 +2015,13 @@ public class CharSequenceUtil {
}
if (counterOfDoubleByte % 2 != 0) {
- len += 1;
+ if(halfUp){
+ len += 1;
+ }else{
+ len -= 1;
+ }
}
- return new String(b, 0, len, CharsetUtil.CHARSET_GBK) + suffix;
+ return new String(b, 0, len, CharsetUtil.CHARSET_GBK);
}
/**
diff --git a/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java
index a8b1e53c1..83c9179ac 100644
--- a/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java
@@ -1,5 +1,6 @@
package cn.hutool.core.text;
+import cn.hutool.core.util.CharsetUtil;
import org.junit.Assert;
import org.junit.Test;
@@ -65,4 +66,16 @@ public class CharSequenceUtilTest {
index = CharSequenceUtil.indexOf("abc123", 'b', 0, 3);
Assert.assertEquals(1, index);
}
+
+ @Test
+ public void subPreGbkTest(){
+ // https://gitee.com/dromara/hutool/issues/I4JO2E
+ String s = "华硕K42Intel酷睿i31代2G以下独立显卡不含机械硬盘固态硬盘120GB-192GB4GB-6GB";
+
+ String v = CharSequenceUtil.subPreGbk(s, 40, false);
+ Assert.assertEquals(39, v.getBytes(CharsetUtil.CHARSET_GBK).length);
+
+ v = CharSequenceUtil.subPreGbk(s, 40, true);
+ Assert.assertEquals(41, v.getBytes(CharsetUtil.CHARSET_GBK).length);
+ }
}
From 99763a32b3d291a541fe94dc5d96bc7e782eb56f Mon Sep 17 00:00:00 2001
From: Looly
Date: Wed, 24 Nov 2021 23:44:17 +0800
Subject: [PATCH 07/29] ignore bridge
---
CHANGELOG.md | 1 +
.../cn/hutool/core/text/CharSequenceUtil.java | 7 ++++-
.../java/cn/hutool/core/util/ReflectUtil.java | 27 ++++++++++---------
3 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1dbe0b555..e8c3b0b9d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,7 @@
* 【core 】 DateUtil.toIntSecond标记为弃用(issue#I4JHPR@Gitee)
* 【db 】 Db.executeBatch标记一个重载为弃用(issue#I4JIPH@Gitee)
* 【core 】 增加CharSequenceUtil.subPreGbk重载(issue#I4JO2E@Gitee)
+* 【core 】 ReflectUtil.getMethod排除桥接方法(pr#1965@Github)
*
### 🐞Bug修复
* 【core 】 修复FileResource构造fileName参数无效问题(issue#1942@Github)
diff --git a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java
index 15a07faff..595a61d69 100644
--- a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java
@@ -2551,7 +2551,12 @@ public class CharSequenceUtil {
}
/**
- * 比较两个字符串是否相等。
+ * 比较两个字符串是否相等,规则如下
+ *
+ * - str1和str2都为{@code null}
+ * - 忽略大小写使用{@link String#equalsIgnoreCase(String)}判断相等
+ * - 不忽略大小写使用{@link String#contentEquals(CharSequence)}判断相等
+ *
*
* @param str1 要比较的字符串1
* @param str2 要比较的字符串2
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java
index affdcac6e..b0f9b1d7f 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java
@@ -84,7 +84,7 @@ public class ReflectUtil {
@SuppressWarnings("unchecked")
public static Constructor[] getConstructors(Class beanClass) throws SecurityException {
Assert.notNull(beanClass);
- return (Constructor[]) CONSTRUCTORS_CACHE.get(beanClass, ()->getConstructorsDirectly(beanClass));
+ return (Constructor[]) CONSTRUCTORS_CACHE.get(beanClass, () -> getConstructorsDirectly(beanClass));
}
/**
@@ -173,7 +173,7 @@ public class ReflectUtil {
*/
public static Field[] getFields(Class> beanClass) throws SecurityException {
Assert.notNull(beanClass);
- return FIELDS_CACHE.get(beanClass, ()->getFieldsDirectly(beanClass, true));
+ return FIELDS_CACHE.get(beanClass, () -> getFieldsDirectly(beanClass, true));
}
@@ -498,11 +498,9 @@ public class ReflectUtil {
}
/**
- * 查找指定方法 如果找不到对应的方法则返回{@code null}
- *
- *
- * 此方法为精准获取方法名,即方法名和参数数量和类型必须一致,否则返回{@code null}。
- *
+ * 查找指定方法 如果找不到对应的方法则返回{@code null}
+ * 此方法为精准获取方法名,即方法名和参数数量和类型必须一致,否则返回{@code null}。
+ * 如果查找的方法有多个同参数类型重载,查找第一个找到的方法
*
* @param clazz 类,如果为{@code null}返回{@code null}
* @param ignoreCase 是否忽略大小写
@@ -520,10 +518,11 @@ public class ReflectUtil {
final Method[] methods = getMethods(clazz);
if (ArrayUtil.isNotEmpty(methods)) {
for (Method method : methods) {
- if (StrUtil.equals(methodName, method.getName(), ignoreCase)) {
- if (ClassUtil.isAllAssignableFrom(method.getParameterTypes(), paramTypes)) {
- return method;
- }
+ if (StrUtil.equals(methodName, method.getName(), ignoreCase)
+ && ClassUtil.isAllAssignableFrom(method.getParameterTypes(), paramTypes)
+ //排除桥接方法,pr#1965@Github
+ && false == method.isBridge()) {
+ return method;
}
}
}
@@ -586,7 +585,9 @@ public class ReflectUtil {
final Method[] methods = getMethods(clazz);
if (ArrayUtil.isNotEmpty(methods)) {
for (Method method : methods) {
- if (StrUtil.equals(methodName, method.getName(), ignoreCase)) {
+ if (StrUtil.equals(methodName, method.getName(), ignoreCase)
+ // 排除桥接方法
+ && false == method.isBridge()) {
return method;
}
}
@@ -635,7 +636,7 @@ public class ReflectUtil {
*/
public static Method[] getMethods(Class> beanClass) throws SecurityException {
Assert.notNull(beanClass);
- return METHODS_CACHE.get(beanClass, ()-> getMethodsDirectly(beanClass, true));
+ return METHODS_CACHE.get(beanClass, () -> getMethodsDirectly(beanClass, true));
}
/**
From d5eabab63ea8e35c19dd707e39724828e610da79 Mon Sep 17 00:00:00 2001
From: duandazhi
Date: Thu, 25 Nov 2021 16:59:39 +0800
Subject: [PATCH 08/29] =?UTF-8?q?=E8=BA=AB=E4=BB=BD=E8=AF=81=E5=B7=A5?=
=?UTF-8?q?=E5=85=B7=E7=B1=BB=EF=BC=8C=E5=A2=9E=E5=8A=A0=E5=AF=B9=20?=
=?UTF-8?q?=E6=B8=AF=E6=BE=B3=E5=8F=B0=20=E5=9C=A8=E5=A4=A7=E9=99=86?=
=?UTF-8?q?=E8=BA=AB=E4=BB=BD=E8=AF=81=20=E7=9A=84=20=E6=96=87=E6=A1=A3?=
=?UTF-8?q?=E8=AF=B4=E6=98=8E=EF=BC=9B=20=E5=A4=A7=E9=99=86=E7=94=A8?=
=?UTF-8?q?=E6=88=B7=20=E5=AF=B9=20810000=E3=80=81820000=E3=80=81830000=20?=
=?UTF-8?q?=E5=BC=80=E9=80=9A=E7=9A=8418=E4=BD=8D=E8=BA=AB=E4=BB=BD?=
=?UTF-8?q?=E8=AF=81=20=E5=BE=80=E5=BE=80=E6=AF=94=E8=BE=83=E9=99=8C?=
=?UTF-8?q?=E7=94=9F=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/cn/hutool/core/util/IdcardUtil.java | 18 ++++++++++++++++++
.../cn/hutool/core/util/IdcardUtilTest.java | 12 ++++++++++++
2 files changed, 30 insertions(+)
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/IdcardUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/IdcardUtil.java
index e7adc4a38..970de3ffc 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/IdcardUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/IdcardUtil.java
@@ -202,6 +202,24 @@ public class IdcardUtil {
* 通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2
*
*
+
+ *
+ * - 香港人在大陆的身份证,【810000】开头;同样可以直接获取到 性别、出生日期
+ * - 81000019980902013X: 文绎循 男 1998-09-02
+ * - 810000201011210153: 辛烨 男 2010-11-21
+ *
+ *
+ * - 澳门人在大陆的身份证,【820000】开头;同样可以直接获取到 性别、出生日期
+ * - 820000200009100032: 黄敬杰 男 2000-09-10
+ *
+ *
+ * - 台湾人在大陆的身份证,【830000】开头;同样可以直接获取到 性别、出生日期
+ * - 830000200209060065: 王宜妃 女 2002-09-06
+ * - 830000194609150010: 苏建文 男 1946-09-14
+ * - 83000019810715006X: 刁婉琇 女 1981-07-15
+ *
+ *
+ *
* @param idcard 待验证的身份证
* @return 是否有效的18位身份证,忽略x的大小写
*/
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/IdcardUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/IdcardUtilTest.java
index 24f423fc0..b9cd747a2 100644
--- a/hutool-core/src/test/java/cn/hutool/core/util/IdcardUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/util/IdcardUtilTest.java
@@ -103,6 +103,18 @@ public class IdcardUtilTest {
Assert.assertTrue(isValidCard18);
isValidCard18 = IdcardUtil.isValidCard18("33010219200403064X");
Assert.assertTrue(isValidCard18);
+
+ // 香港人在大陆身份证
+ isValidCard18 = IdcardUtil.isValidCard18("81000019980902013X");
+ Assert.assertTrue(isValidCard18);
+
+ // 澳门人在大陆身份证
+ isValidCard18 = IdcardUtil.isValidCard18("820000200009100032");
+ Assert.assertTrue(isValidCard18);
+
+ // 台湾人在大陆身份证
+ isValidCard18 = IdcardUtil.isValidCard18("830000200209060065");
+ Assert.assertTrue(isValidCard18);
}
@Test
From e57a927c9b63e5d3bae68955e405e09877b5ac6d Mon Sep 17 00:00:00 2001
From: looly
Date: Thu, 25 Nov 2021 17:45:18 +0800
Subject: [PATCH 09/29] fix code
---
.../src/main/java/cn/hutool/core/lang/func/LambdaUtil.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java
index 02db6a2e1..f604ebb00 100644
--- a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java
@@ -73,7 +73,7 @@ public class LambdaUtil {
* @param func 需要解析的 lambda 对象
* @return 返回解析后的结果
*/
- private static SerializedLambda _resolve(Serializable func) {
+ private static SerializedLambda _resolve(Serializable func) {
return cache.get(func.getClass().getName(), () -> ReflectUtil.invoke(func, "writeReplace"));
}
}
From d3f2f85d1a2f234ed92179d816735dcb98005ddb Mon Sep 17 00:00:00 2001
From: scruel
Date: Fri, 26 Nov 2021 14:45:23 +0800
Subject: [PATCH 10/29] fix doc typo
---
.../src/main/java/cn/hutool/core/collection/CollectionUtil.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/CollectionUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/CollectionUtil.java
index dde70af56..66d89dc9b 100644
--- a/hutool-core/src/main/java/cn/hutool/core/collection/CollectionUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/collection/CollectionUtil.java
@@ -1,7 +1,7 @@
package cn.hutool.core.collection;
/**
- * 集合相关工具类,包括数组,是{@link CollUtil} 的别名工具类类
+ * 集合相关工具类,包括数组,是 {@link CollUtil} 的别名工具类
*
* @author xiaoleilu
* @see CollUtil
From c85f204da9445b58c2a42b06944812dc22ccf9c1 Mon Sep 17 00:00:00 2001
From: Looly
Date: Fri, 26 Nov 2021 20:38:13 +0800
Subject: [PATCH 11/29] change code
---
CHANGELOG.md | 3 ++-
hutool-http/src/main/java/cn/hutool/http/HttpResponse.java | 6 ++++--
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e8c3b0b9d..4a9ad47d9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,7 @@
-------------------------------------------------------------------------------------------------------------
-# 5.7.17 (2021-11-24)
+# 5.7.17 (2021-11-26)
### 🐣新特性
* 【core 】 增加AsyncUtil(pr#457@Gitee)
@@ -25,6 +25,7 @@
* 【db 】 Db.executeBatch标记一个重载为弃用(issue#I4JIPH@Gitee)
* 【core 】 增加CharSequenceUtil.subPreGbk重载(issue#I4JO2E@Gitee)
* 【core 】 ReflectUtil.getMethod排除桥接方法(pr#1965@Github)
+* 【http 】 completeFileNameFromHeader在使用path为路径时,自动解码(issue#I4K0FS@Gitee)
*
### 🐞Bug修复
* 【core 】 修复FileResource构造fileName参数无效问题(issue#1942@Github)
diff --git a/hutool-http/src/main/java/cn/hutool/http/HttpResponse.java b/hutool-http/src/main/java/cn/hutool/http/HttpResponse.java
index f64f1ecd7..03ae911da 100644
--- a/hutool-http/src/main/java/cn/hutool/http/HttpResponse.java
+++ b/hutool-http/src/main/java/cn/hutool/http/HttpResponse.java
@@ -7,7 +7,6 @@ import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.StreamProgress;
import cn.hutool.core.lang.Assert;
-import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
@@ -434,7 +433,10 @@ public class HttpResponse extends HttpBase implements Closeable {
fileName = StrUtil.subSuf(path, path.lastIndexOf('/') + 1);
if (StrUtil.isBlank(fileName)) {
// 编码后的路径做为文件名
- fileName = URLUtil.encodeQuery(path, CharsetUtil.CHARSET_UTF_8);
+ fileName = URLUtil.encodeQuery(path, charset);
+ } else {
+ // issue#I4K0FS@Gitee
+ fileName = URLUtil.decode(fileName, charset);
}
}
return FileUtil.file(targetFileOrDir, fileName);
From 95854cddb126efc2a80ea7c2c709f05c3493d230 Mon Sep 17 00:00:00 2001
From: Looly
Date: Fri, 26 Nov 2021 21:31:55 +0800
Subject: [PATCH 12/29] add options
---
CHANGELOG.md | 1 +
.../java/cn/hutool/core/bean/PropDesc.java | 39 ++++++++++---
.../hutool/core/bean/copier/BeanCopier.java | 55 ++++++++++++++++---
.../hutool/core/bean/copier/CopyOptions.java | 20 ++++++-
.../core/bean/copier/BeanCopierTest.java | 50 +++++++++++++++++
5 files changed, 147 insertions(+), 18 deletions(-)
create mode 100644 hutool-core/src/test/java/cn/hutool/core/bean/copier/BeanCopierTest.java
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4a9ad47d9..4887c7fdf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,6 +26,7 @@
* 【core 】 增加CharSequenceUtil.subPreGbk重载(issue#I4JO2E@Gitee)
* 【core 】 ReflectUtil.getMethod排除桥接方法(pr#1965@Github)
* 【http 】 completeFileNameFromHeader在使用path为路径时,自动解码(issue#I4K0FS@Gitee)
+* 【core 】 CopyOptions增加override配置(issue#I4JQ1N@Gitee)
*
### 🐞Bug修复
* 【core 】 修复FileResource构造fileName参数无效问题(issue#1942@Github)
diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java b/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java
index 8fc238457..c9ea67472 100644
--- a/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java
+++ b/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java
@@ -121,18 +121,19 @@ public class PropDesc {
/**
* 检查属性是否可读(即是否可以通过{@link #getValue(Object)}获取到值)
+ *
* @param checkTransient 是否检查Transient关键字或注解
* @return 是否可读
* @since 5.4.2
*/
- public boolean isReadable(boolean checkTransient){
+ public boolean isReadable(boolean checkTransient) {
// 检查是否有getter方法或是否为public修饰
- if(null == this.getter && false == ModifierUtil.isPublic(this.field)){
+ if (null == this.getter && false == ModifierUtil.isPublic(this.field)) {
return false;
}
// 检查transient关键字和@Transient注解
- if(checkTransient && isTransientForGet()){
+ if (checkTransient && isTransientForGet()) {
return false;
}
@@ -164,7 +165,7 @@ public class PropDesc {
* 首先调用字段对应的Getter方法获取值,如果Getter方法不存在,则判断字段如果为public,则直接获取字段值
*
* @param bean Bean对象
- * @param targetType 返回属性值需要转换的类型,null表示不转换
+ * @param targetType 返回属性值需要转换的类型,null表示不转换
* @param ignoreError 是否忽略错误,包括转换错误和注入错误
* @return this
* @since 5.4.2
@@ -190,18 +191,19 @@ public class PropDesc {
/**
* 检查属性是否可读(即是否可以通过{@link #getValue(Object)}获取到值)
+ *
* @param checkTransient 是否检查Transient关键字或注解
* @return 是否可读
* @since 5.4.2
*/
- public boolean isWritable(boolean checkTransient){
+ public boolean isWritable(boolean checkTransient) {
// 检查是否有getter方法或是否为public修饰
- if(null == this.setter && false == ModifierUtil.isPublic(this.field)){
+ if (null == this.setter && false == ModifierUtil.isPublic(this.field)) {
return false;
}
// 检查transient关键字和@Transient注解
- if(checkTransient && isTransientForSet()){
+ if (checkTransient && isTransientForSet()) {
return false;
}
@@ -239,7 +241,28 @@ public class PropDesc {
* @since 5.4.2
*/
public PropDesc setValue(Object bean, Object value, boolean ignoreNull, boolean ignoreError) {
- if (ignoreNull && null == value) {
+ return setValue(bean, value, ignoreNull, ignoreError, true);
+ }
+
+ /**
+ * 设置属性值,可以自动转换字段类型为目标类型
+ *
+ * @param bean Bean对象
+ * @param value 属性值,可以为任意类型
+ * @param ignoreNull 是否忽略{@code null}值,true表示忽略
+ * @param ignoreError 是否忽略错误,包括转换错误和注入错误
+ * @param override 是否覆盖目标值,如果不覆盖,会先读取bean的值,非{@code null}则写,否则忽略。如果覆盖,则不判断直接写
+ * @return this
+ * @since 5.7.17
+ */
+ public PropDesc setValue(Object bean, Object value, boolean ignoreNull, boolean ignoreError, boolean override) {
+ if (null == value && ignoreNull) {
+ return this;
+ }
+
+ // issue#I4JQ1N@Gitee
+ // 非覆盖模式下,如果目标值存在,则跳过
+ if (false == override && null != getValue(bean)) {
return this;
}
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 bcfae58a1..ec0a01d22 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
@@ -140,13 +140,44 @@ public class BeanCopier implements Copier, Serializable {
* Map转Map
*
* @param source 源Map
- * @param dest 目标Map
+ * @param targetMap 目标Map
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
- private void mapToMap(Map source, Map dest) {
- if (null != dest && null != source) {
- dest.putAll(source);
- }
+ private void mapToMap(Map source, Map targetMap) {
+ source.forEach((key, value)->{
+ final CopyOptions copyOptions = this.copyOptions;
+ final HashSet ignoreSet = (null != copyOptions.ignoreProperties) ? CollUtil.newHashSet(copyOptions.ignoreProperties) : null;
+
+ // issue#I4JQ1N@Gitee
+ // 非覆盖模式下,如果目标值存在,则跳过
+ if(false == copyOptions.override && null != targetMap.get(key)){
+ return;
+ }
+
+ if(key instanceof CharSequence){
+ if (CollUtil.contains(ignoreSet, key)) {
+ // 目标属性值被忽略或值提供者无此key时跳过
+ return;
+ }
+
+ // 对key做映射,映射后为null的忽略之
+ key = copyOptions.editFieldName(copyOptions.getMappedFieldName(key.toString(), false));
+ if(null == key){
+ return;
+ }
+
+ value = copyOptions.editFieldValue(key.toString(), value);
+ }
+
+
+ if ((null == value && copyOptions.ignoreNullValue) || source == value) {
+ // 当允许跳过空时,跳过
+ //值不能为bean本身,防止循环引用,此类也跳过
+ return;
+ }
+
+ targetMap.put(key, value);
+ });
}
/**
@@ -158,11 +189,11 @@ public class BeanCopier implements Copier, Serializable {
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
private void beanToMap(Object bean, Map targetMap) {
- final HashSet ignoreSet = (null != copyOptions.ignoreProperties) ? CollUtil.newHashSet(copyOptions.ignoreProperties) : null;
final CopyOptions copyOptions = this.copyOptions;
+ final HashSet ignoreSet = (null != copyOptions.ignoreProperties) ? CollUtil.newHashSet(copyOptions.ignoreProperties) : null;
BeanUtil.descForEach(bean.getClass(), (prop)->{
- if(false == prop.isReadable(copyOptions.isTransientSupport())){
+ if(false == prop.isReadable(copyOptions.transientSupport)){
// 忽略的属性跳过之
return;
}
@@ -178,6 +209,12 @@ public class BeanCopier implements Copier, Serializable {
return;
}
+ // issue#I4JQ1N@Gitee
+ // 非覆盖模式下,如果目标值存在,则跳过
+ if(false == copyOptions.override && null != targetMap.get(key)){
+ return;
+ }
+
Object value;
try {
value = prop.getValue(bean);
@@ -230,7 +267,7 @@ public class BeanCopier implements Copier, Serializable {
// 遍历目标bean的所有属性
BeanUtil.descForEach(actualEditable, (prop)->{
- if(false == prop.isWritable(this.copyOptions.isTransientSupport())){
+ if(false == prop.isWritable(this.copyOptions.transientSupport)){
// 字段不可写,跳过之
return;
}
@@ -270,7 +307,7 @@ public class BeanCopier implements Copier, Serializable {
return;
}
- prop.setValue(bean, value, copyOptions.ignoreNullValue, copyOptions.ignoreError);
+ prop.setValue(bean, value, copyOptions.ignoreNullValue, copyOptions.ignoreError, copyOptions.override);
});
}
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/CopyOptions.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/CopyOptions.java
index b0e35315f..92ab2937a 100644
--- a/hutool-core/src/main/java/cn/hutool/core/bean/copier/CopyOptions.java
+++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/CopyOptions.java
@@ -65,7 +65,11 @@ public class CopyOptions implements Serializable {
/**
* 是否支持transient关键字修饰和@Transient注解,如果支持,被修饰的字段或方法对应的字段将被忽略。
*/
- private boolean transientSupport = true;
+ protected boolean transientSupport = true;
+ /**
+ * 是否覆盖目标值,如果不覆盖,会先读取目标对象的值,非{@code null}则写,否则忽略。如果覆盖,则不判断直接写
+ */
+ protected boolean override = true;
/**
* 创建拷贝选项
@@ -259,7 +263,9 @@ public class CopyOptions implements Serializable {
*
* @return 是否支持
* @since 5.4.2
+ * @deprecated 无需此方法,内部使用直接调用属性
*/
+ @Deprecated
public boolean isTransientSupport() {
return this.transientSupport;
}
@@ -276,6 +282,18 @@ public class CopyOptions implements Serializable {
return this;
}
+ /**
+ * 设置是否覆盖目标值,如果不覆盖,会先读取目标对象的值,非{@code null}则写,否则忽略。如果覆盖,则不判断直接写
+ *
+ * @param override 是否覆盖目标值
+ * @return this
+ * @since 5.7.17
+ */
+ public CopyOptions setOverride(boolean override) {
+ this.override = override;
+ return this;
+ }
+
/**
* 获得映射后的字段名
* 当非反向,则根据源字段名获取目标字段名,反之根据目标字段名获取源字段名。
diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/copier/BeanCopierTest.java b/hutool-core/src/test/java/cn/hutool/core/bean/copier/BeanCopierTest.java
new file mode 100644
index 000000000..0c314d18b
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/bean/copier/BeanCopierTest.java
@@ -0,0 +1,50 @@
+package cn.hutool.core.bean.copier;
+
+import lombok.Data;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class BeanCopierTest {
+
+ /**
+ * 测试在非覆盖模式下,目标对象有值则不覆盖
+ */
+ @Test
+ public void beanToBeanNotOverrideTest() {
+ final A a = new A();
+ a.setValue("123");
+ final B b = new B();
+ b.setValue("abc");
+
+ final BeanCopier copier = BeanCopier.create(a, b, CopyOptions.create().setOverride(false));
+ copier.copy();
+
+ Assert.assertEquals("abc", b.getValue());
+ }
+
+ /**
+ * 测试在覆盖模式下,目标对象值被覆盖
+ */
+ @Test
+ public void beanToBeanOverrideTest() {
+ final A a = new A();
+ a.setValue("123");
+ final B b = new B();
+ b.setValue("abc");
+
+ final BeanCopier copier = BeanCopier.create(a, b, CopyOptions.create());
+ copier.copy();
+
+ Assert.assertEquals("123", b.getValue());
+ }
+
+ @Data
+ private static class A {
+ private String value;
+ }
+
+ @Data
+ private static class B {
+ private String value;
+ }
+}
From 06cc38734ca9fe65a102f7f35b22b6e8795dcc28 Mon Sep 17 00:00:00 2001
From: Looly
Date: Fri, 26 Nov 2021 21:49:01 +0800
Subject: [PATCH 13/29] add method
---
CHANGELOG.md | 1 +
.../poi/excel/sax/Excel07SaxReader.java | 2 +-
.../hutool/poi/excel/sax/SheetRidReader.java | 23 +++++++++++++++++++
3 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4887c7fdf..f7f929b2b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,6 +27,7 @@
* 【core 】 ReflectUtil.getMethod排除桥接方法(pr#1965@Github)
* 【http 】 completeFileNameFromHeader在使用path为路径时,自动解码(issue#I4K0FS@Gitee)
* 【core 】 CopyOptions增加override配置(issue#I4JQ1N@Gitee)
+* 【poi 】 SheetRidReader可以获取所有sheet名(issue#I4JA3M@Gitee)
*
### 🐞Bug修复
* 【core 】 修复FileResource构造fileName参数无效问题(issue#1942@Github)
diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java
index e742e8fa1..ee5c5710a 100644
--- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java
+++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java
@@ -202,7 +202,7 @@ public class Excel07SaxReader implements ExcelSaxReader {
}
// sheetIndex需转换为rid
- final SheetRidReader ridReader = new SheetRidReader().read(xssfReader);
+ final SheetRidReader ridReader = SheetRidReader.parse(xssfReader);
if (StrUtil.startWithIgnoreCase(idOrRidOrSheetName, SHEET_NAME_PREFIX)) {
// name:开头的被认为是sheet名称直接处理
diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java
index 76e295f8b..9cfc772b4 100644
--- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java
+++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java
@@ -1,6 +1,7 @@
package cn.hutool.poi.excel.sax;
import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
@@ -13,6 +14,7 @@ import org.xml.sax.helpers.DefaultHandler;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
/**
@@ -32,6 +34,17 @@ import java.util.Map;
*/
public class SheetRidReader extends DefaultHandler {
+ /**
+ * 从{@link XSSFReader}中解析sheet名、sheet id等相关信息
+ *
+ * @param reader {@link XSSFReader}
+ * @return SheetRidReader
+ * @since 5.7.17
+ */
+ public static SheetRidReader parse(XSSFReader reader) {
+ return new SheetRidReader().read(reader);
+ }
+
private final static String TAG_NAME = "sheet";
private final static String RID_ATTR = "r:id";
private final static String SHEET_ID_ATTR = "sheetId";
@@ -137,6 +150,16 @@ public class SheetRidReader extends DefaultHandler {
return null;
}
+ /**
+ * 获取所有sheet名称
+ *
+ * @return sheet名称
+ * @since 5.7.17
+ */
+ public List getSheetNames() {
+ return ListUtil.toList(this.NAME_RID_MAP.keySet());
+ }
+
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
if (TAG_NAME.equalsIgnoreCase(localName)) {
From 496d07c8d79f2b376e9165bc21752b160b4e40b4 Mon Sep 17 00:00:00 2001
From: Looly
Date: Fri, 26 Nov 2021 22:21:41 +0800
Subject: [PATCH 14/29] add test
---
CHANGELOG.md | 1 +
.../src/test/java/cn/hutool/core/util/ArrayUtilTest.java | 6 ++++++
hutool-http/src/main/java/cn/hutool/http/HttpUtil.java | 3 +++
hutool-http/src/test/java/cn/hutool/http/HttpUtilTest.java | 6 ++++++
4 files changed, 16 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f7f929b2b..a9008a4f6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -33,6 +33,7 @@
* 【core 】 修复FileResource构造fileName参数无效问题(issue#1942@Github)
* 【cache 】 修复WeakCache键值强关联导致的无法回收问题(issue#1953@Github)
* 【core 】 修复ZipUtil相对路径父路径获取null问题(issue#1961@Github)
+* 【http 】 修复HttpUtil.normalizeParams未判空导致的问题(issue#1975@Github)
-------------------------------------------------------------------------------------------------------------
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java
index a7755e00e..5a0d71ca8 100644
--- a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java
@@ -182,6 +182,12 @@ public class ArrayUtilTest {
Assert.assertEquals(9, range[9]);
}
+ @Test(expected = NegativeArraySizeException.class)
+ public void rangeMinTest() {
+ //noinspection ResultOfMethodCallIgnored
+ ArrayUtil.range(0, Integer.MIN_VALUE);
+ }
+
@Test
public void maxTest() {
int max = ArrayUtil.max(1, 2, 13, 4, 5);
diff --git a/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java b/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java
index 0257cd464..ffe7ed669 100644
--- a/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java
+++ b/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java
@@ -539,6 +539,9 @@ public class HttpUtil {
* @since 4.5.2
*/
public static String normalizeParams(String paramPart, Charset charset) {
+ if(StrUtil.isEmpty(paramPart)){
+ return paramPart;
+ }
final StrBuilder builder = StrBuilder.create(paramPart.length() + 16);
final int len = paramPart.length();
String name = null;
diff --git a/hutool-http/src/test/java/cn/hutool/http/HttpUtilTest.java b/hutool-http/src/test/java/cn/hutool/http/HttpUtilTest.java
index e829d7752..00ad46b87 100644
--- a/hutool-http/src/test/java/cn/hutool/http/HttpUtilTest.java
+++ b/hutool-http/src/test/java/cn/hutool/http/HttpUtilTest.java
@@ -302,6 +302,12 @@ public class HttpUtilTest {
Assert.assertEquals("%E5%8F%82%E6%95%B0", encodeResult);
}
+ @Test
+ public void normalizeBlankParamsTest() {
+ String encodeResult = HttpUtil.normalizeParams("", CharsetUtil.CHARSET_UTF_8);
+ Assert.assertEquals("", encodeResult);
+ }
+
@Test
public void getMimeTypeTest() {
String mimeType = HttpUtil.getMimeType("aaa.aaa");
From 7ece10a15d16c3ba0c17006f9df3ed5818edd830 Mon Sep 17 00:00:00 2001
From: Looly
Date: Fri, 26 Nov 2021 22:50:26 +0800
Subject: [PATCH 15/29] fix comment
---
.../src/main/java/cn/hutool/core/lang/Opt.java | 2 ++
.../main/java/cn/hutool/core/util/IdcardUtil.java | 14 ++++++--------
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java b/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java
index f3b23892c..e03ad64cd 100644
--- a/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java
+++ b/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java
@@ -253,8 +253,10 @@ public class Opt {
* String hutool = Opt.ofBlankAble("hutool").mapOrElse(String::toUpperCase, () -> Console.log("yes")).mapOrElse(String::intern, () -> Console.log("Value is not present~")).get();
* }
*
+ * @param map后新的类型
* @param mapper 包裹里的值存在时的操作
* @param emptyAction 包裹里的值不存在时的操作
+ * @return 新的类型的Opt
* @throws NullPointerException 如果包裹里的值存在时,执行的操作为 {@code null}, 或者包裹里的值不存在时的操作为 {@code null},则抛出{@code NPE}
*/
public Opt mapOrElse(Function super T, ? extends U> mapper, VoidFunc0 emptyAction) {
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/IdcardUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/IdcardUtil.java
index 970de3ffc..4fa1201f3 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/IdcardUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/IdcardUtil.java
@@ -154,7 +154,7 @@ public class IdcardUtil {
* @return 是否有效
*/
public static boolean isValidCard(String idCard) {
- if(StrUtil.isBlank(idCard)){
+ if (StrUtil.isBlank(idCard)) {
return false;
}
@@ -201,9 +201,7 @@ public class IdcardUtil {
* 余数只可能有0 1 2 3 4 5 6 7 8 9 10这11个数字。其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2
* 通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2
*
- *
-
- *
+ *
* - 香港人在大陆的身份证,【810000】开头;同样可以直接获取到 性别、出生日期
* - 81000019980902013X: 文绎循 男 1998-09-02
* - 810000201011210153: 辛烨 男 2010-11-21
@@ -218,7 +216,6 @@ public class IdcardUtil {
* - 830000194609150010: 苏建文 男 1946-09-14
* - 83000019810715006X: 刁婉琇 女 1981-07-15
*
- *
*
* @param idcard 待验证的身份证
* @return 是否有效的18位身份证,忽略x的大小写
@@ -255,7 +252,7 @@ public class IdcardUtil {
* - 通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2
*
*
- * @param idcard 待验证的身份证
+ * @param idcard 待验证的身份证
* @param ignoreCase 是否忽略大小写。{@code true}则忽略X大小写,否则严格匹配大写。
* @return 是否有效的18位身份证
* @since 5.5.7
@@ -576,7 +573,7 @@ public class IdcardUtil {
*/
public static String getProvinceByIdCard(String idcard) {
final String code = getProvinceCodeByIdCard(idcard);
- if(StrUtil.isNotBlank(code)){
+ if (StrUtil.isNotBlank(code)) {
return CITY_CODES.get(code);
}
return null;
@@ -617,7 +614,7 @@ public class IdcardUtil {
* @return {@link Idcard}
* @since 5.4.3
*/
- public static Idcard getIdcardInfo(String idcard){
+ public static Idcard getIdcardInfo(String idcard) {
return new Idcard(idcard);
}
@@ -761,6 +758,7 @@ public class IdcardUtil {
/**
* 获取年龄
+ *
* @return 年龄
*/
public int getAge() {
From 9e5d075b0d6b5d4d1c8b7a7a0e0c1415171e6bd1 Mon Sep 17 00:00:00 2001
From: SPPan
Date: Sat, 27 Nov 2021 22:32:15 +0800
Subject: [PATCH 16/29] =?UTF-8?q?POI=E8=AF=BB=E5=8F=96EXCEL=E6=97=A5?=
=?UTF-8?q?=E6=9C=9F=E4=B8=BA1899=E5=B9=B4=E9=97=AE=E9=A2=98=E5=A4=84?=
=?UTF-8?q?=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../hutool/poi/excel/cell/values/NumericCellValue.java | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/values/NumericCellValue.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/values/NumericCellValue.java
index 951af97c2..bf160730e 100755
--- a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/values/NumericCellValue.java
+++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/values/NumericCellValue.java
@@ -4,6 +4,7 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelDateUtil;
import cn.hutool.poi.excel.cell.CellValue;
+import java.util.Date;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.util.NumberToTextConverter;
@@ -24,7 +25,7 @@ public class NumericCellValue implements CellValue