From 538874562d68b3316d7d376ecec20714ced32223 Mon Sep 17 00:00:00 2001 From: naooohu Date: Thu, 20 Jan 2022 01:28:58 +0800 Subject: [PATCH 001/156] =?UTF-8?q?add=20=E6=B7=BB=E5=8A=A0=E5=88=A4?= =?UTF-8?q?=E6=96=AD=E4=B8=A4=E4=B8=AA=E6=97=A5=E6=9C=9F=E6=98=AF=E5=90=A6?= =?UTF-8?q?=E4=B8=BA=E4=B8=80=E5=91=A8=EF=BC=88=E5=9B=BD=E5=86=85=E4=B8=80?= =?UTF-8?q?=E5=91=A8=E7=9A=84=E5=BC=80=E5=A7=8B=E4=B8=BA=E5=91=A8=E4=B8=80?= =?UTF-8?q?=EF=BC=8C=E5=9B=BD=E5=A4=96=E4=B8=80=E5=91=A8=E7=9A=84=E5=BC=80?= =?UTF-8?q?=E5=A7=8B=E4=B8=BA=E5=91=A8=E6=97=A5=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/hutool/core/date/CalendarUtil.java | 16 +++++++++++ .../java/cn/hutool/core/date/DateUtil.java | 28 +++++++++++++++++++ .../cn/hutool/core/date/DateUtilTest.java | 11 ++++++++ 3 files changed, 55 insertions(+) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java index a1e2f176b..774aabec5 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java @@ -348,6 +348,22 @@ public class CalendarUtil { cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA); } + /** + * 比较两个日期是否为同一周 + * + * @param cal1 日期1 + * @param cal2 日期2 + * @return 是否为同一周 + */ + public static boolean isSameWeek(Calendar cal1, Calendar cal2) { + if (cal1 == null || cal2 == null) { + throw new IllegalArgumentException("The date must not be null"); + } + return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && + cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH) && + cal1.get(Calendar.DAY_OF_WEEK) == cal2.get(Calendar.DAY_OF_WEEK); + } + /** * 比较两个日期是否为同一月 * 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 813fba971..066777c78 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 @@ -1586,6 +1586,34 @@ public class DateUtil extends CalendarUtil { return CalendarUtil.isSameDay(calendar(date1), calendar(date2)); } + /** + * 比较两个日期是否为同一周 + * + * @param date1 日期1 + * @param date2 日期2 + * @param isMon 是否为周一。国内第一天为星期一,国外第一天为星期日 + * @return 是否为同一周 + */ + public static boolean isSameWeek(final Date date1, final Date date2, boolean isMon) { + if (date1 == null || date2 == null) { + throw new IllegalArgumentException("The date must not be null"); + } + Calendar calendar1 = calendar(date1); + Calendar calendar2 = calendar(date2); + if (isMon) { + calendar1.setFirstDayOfWeek(Calendar.MONDAY); + calendar1.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); + calendar2.setFirstDayOfWeek(Calendar.MONDAY); + calendar2.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); + } else { + calendar1.setFirstDayOfWeek(Calendar.SUNDAY); + calendar1.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); + calendar2.setFirstDayOfWeek(Calendar.SUNDAY); + calendar2.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); + } + return CalendarUtil.isSameWeek(calendar1, calendar2); + } + /** * 比较两个日期是否为同一月 * diff --git a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java index 24e7321a8..ceab8fe7e 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java @@ -1004,4 +1004,15 @@ public class DateUtilTest { final DateTime parse = DateUtil.parse("2021-12-01", DatePattern.NORM_DATE_FORMATTER); Assert.assertEquals("2021-12-01 00:00:00", parse.toString()); } + + @Test + public void test() { + // 周六与周日比较 + final boolean isSameWeek = DateUtil.isSameWeek(DateTime.of("2022-01-01", "yyyy-MM-dd"), DateTime.of("2022-01-02", "yyyy-MM-dd"), true); + Assert.assertTrue(isSameWeek); + // 周日与周一比较 + final boolean isSameWeek1 = DateUtil.isSameWeek(DateTime.of("2022-01-02", "yyyy-MM-dd"), DateTime.of("2022-01-03", "yyyy-MM-dd"), false); + Assert.assertTrue(isSameWeek1); + + } } From e596a9c8e4b7b849eb07877335ead71d685b4ab9 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 20 Jan 2022 12:27:37 +0800 Subject: [PATCH 002/156] prepare 5.7.21 --- CHANGELOG.md | 5 +++++ README-EN.md | 6 +++--- README.md | 6 +++--- bin/version.txt | 2 +- docs/js/version.js | 2 +- hutool-all/pom.xml | 2 +- hutool-aop/pom.xml | 2 +- hutool-bloomFilter/pom.xml | 2 +- hutool-bom/pom.xml | 2 +- hutool-cache/pom.xml | 2 +- hutool-captcha/pom.xml | 2 +- hutool-core/pom.xml | 2 +- hutool-cron/pom.xml | 2 +- hutool-crypto/pom.xml | 2 +- hutool-db/pom.xml | 2 +- hutool-dfa/pom.xml | 2 +- hutool-extra/pom.xml | 2 +- hutool-http/pom.xml | 2 +- hutool-json/pom.xml | 2 +- hutool-jwt/pom.xml | 2 +- hutool-log/pom.xml | 2 +- hutool-poi/pom.xml | 2 +- hutool-script/pom.xml | 2 +- hutool-setting/pom.xml | 2 +- hutool-socket/pom.xml | 2 +- hutool-system/pom.xml | 2 +- pom.xml | 2 +- 27 files changed, 35 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df97fc9c3..f528a27a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,12 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- +# 5.7.21 (2022-01-20) +### 🐣新特性 +### 🐞Bug修复 + +------------------------------------------------------------------------------------------------------------- # 5.7.20 (2022-01-20) ### 🐣新特性 diff --git a/README-EN.md b/README-EN.md index b55c1128d..f7a5da2d2 100644 --- a/README-EN.md +++ b/README-EN.md @@ -142,18 +142,18 @@ We provide the T-Shirt and Sweater with Hutool Logo, please visit the shop: cn.hutool hutool-all - 5.7.20 + 5.7.21 ``` ### 🍐Gradle ``` -implementation 'cn.hutool:hutool-all:5.7.20' +implementation 'cn.hutool:hutool-all:5.7.21' ``` ## 📥Download -- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.7.20/) +- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.7.21/) > 🔔️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 8aeb70262..a4ef14c1f 100644 --- a/README.md +++ b/README.md @@ -142,20 +142,20 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不 cn.hutool hutool-all - 5.7.20 + 5.7.21 ``` ### 🍐Gradle ``` -implementation 'cn.hutool:hutool-all:5.7.20' +implementation 'cn.hutool:hutool-all:5.7.21' ``` ### 📥下载jar 点击以下链接,下载`hutool-all-X.X.X.jar`即可: -- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.7.20/) +- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.7.21/) > 🔔️注意 > Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。 diff --git a/bin/version.txt b/bin/version.txt index b0917fb0e..fcad0d34c 100755 --- a/bin/version.txt +++ b/bin/version.txt @@ -1 +1 @@ -5.7.20 +5.7.21 diff --git a/docs/js/version.js b/docs/js/version.js index 978cfac6d..6bdf634cd 100644 --- a/docs/js/version.js +++ b/docs/js/version.js @@ -1 +1 @@ -var version = '5.7.20' \ No newline at end of file +var version = '5.7.21' \ No newline at end of file diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index 511746da4..27f161685 100644 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-all diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml index 7ea45314f..94786ad48 100644 --- a/hutool-aop/pom.xml +++ b/hutool-aop/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-aop diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml index c8cdcd926..e6d5a8a92 100644 --- a/hutool-bloomFilter/pom.xml +++ b/hutool-bloomFilter/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-bloomFilter diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml index c3cee33b3..eb557d8b9 100644 --- a/hutool-bom/pom.xml +++ b/hutool-bom/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-bom diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml index 062080971..16b19f58b 100644 --- a/hutool-cache/pom.xml +++ b/hutool-cache/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-cache diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml index 45754904a..61d5e5eb0 100644 --- a/hutool-captcha/pom.xml +++ b/hutool-captcha/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-captcha diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index 995d36026..3331f8bde 100644 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-core diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml index f0929496c..7f6b31ad6 100644 --- a/hutool-cron/pom.xml +++ b/hutool-cron/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-cron diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml index 7105bd7f5..2249e5391 100644 --- a/hutool-crypto/pom.xml +++ b/hutool-crypto/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-crypto diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index 4d6d83222..f314f3191 100644 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-db diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml index 244b9c3fe..6416c6f74 100644 --- a/hutool-dfa/pom.xml +++ b/hutool-dfa/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-dfa diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index 0a6a57284..15945e1ce 100644 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-extra diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index b4a57da4c..0cff463c3 100644 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-http diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index a41748fd4..03cbd5837 100644 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-json diff --git a/hutool-jwt/pom.xml b/hutool-jwt/pom.xml index 549b5b819..328bca47f 100644 --- a/hutool-jwt/pom.xml +++ b/hutool-jwt/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-jwt diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index ea661e721..db88952d7 100644 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-log diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index 80d7ce519..4be7f3f50 100644 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-poi diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml index 7fa28a4f5..f1d4bcc68 100644 --- a/hutool-script/pom.xml +++ b/hutool-script/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-script diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml index 7bd5fdce5..b9cd5073f 100644 --- a/hutool-setting/pom.xml +++ b/hutool-setting/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-setting diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml index d8d684dfe..11da40893 100644 --- a/hutool-socket/pom.xml +++ b/hutool-socket/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-socket diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml index 4105c3a27..ec3f296fc 100644 --- a/hutool-system/pom.xml +++ b/hutool-system/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool-system diff --git a/pom.xml b/pom.xml index ec82d9de5..906bd8b87 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.7.20 + 5.7.21-SNAPSHOT hutool Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。 https://github.com/dromara/hutool From 6014a47f7c3e1570dc0c2e53ddee96dbfd187106 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 20 Jan 2022 12:30:53 +0800 Subject: [PATCH 003/156] fix path --- README-EN.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README-EN.md b/README-EN.md index f7a5da2d2..3f9f3cf01 100644 --- a/README-EN.md +++ b/README-EN.md @@ -12,7 +12,7 @@ - + diff --git a/README.md b/README.md index a4ef14c1f..1d8f3f7c9 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ - + From 4447bb18d420c9e5b36e50485a2502b99b7865ec Mon Sep 17 00:00:00 2001 From: tjh Date: Thu, 20 Jan 2022 16:28:08 +0800 Subject: [PATCH 004/156] =?UTF-8?q?=E6=96=B0=EF=BC=9A=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E7=BB=84=EF=BC=8C=E7=94=A8=E4=BA=8E=E5=A4=84?= =?UTF-8?q?=E7=90=86=E5=A4=8D=E6=9D=82=E7=9A=84where=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/hutool/db/sql/ConditionGroup.java | 51 +++++++++++++++++++ .../cn/hutool/db/sql/ConditionGroupTest.java | 26 ++++++++++ 2 files changed, 77 insertions(+) create mode 100644 hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java create mode 100644 hutool-db/src/test/java/cn/hutool/db/sql/ConditionGroupTest.java diff --git a/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java b/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java new file mode 100644 index 000000000..33467287a --- /dev/null +++ b/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java @@ -0,0 +1,51 @@ +package cn.hutool.db.sql; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; + +import java.util.List; + +/** + * 条件组
+ * 用于构建复杂where条件 + * + * @author tjh + */ +public class ConditionGroup extends Condition{ + /** + * 条件列表 + */ + private Condition[] conditions; + + /** + * 追加条件 + * + * @param conditions 条件列表 + */ + public void addConditions(Condition... conditions) { + if(null == this.conditions) { + this.conditions = conditions; + } else { + this.conditions = ArrayUtil.addAll(this.conditions, conditions); + } + } + + /** + * 将条件组转换为条件字符串,使用括号包裹,并回填占位符对应的参数值 + * + * @param paramValues 参数列表,用于回填占位符对应参数值 + * @return 条件字符串 + */ + @Override + public String toString(List paramValues) { + if (ArrayUtil.isEmpty(conditions)) return StrUtil.EMPTY; + + final StringBuilder conditionStrBuilder = StrUtil.builder(); + conditionStrBuilder.append("("); + // 将组内的条件构造为SQL,因为toString,会进行递归,处理所有的条件组 + conditionStrBuilder.append(ConditionBuilder.of(this.conditions).build(paramValues)); + conditionStrBuilder.append(")"); + + return conditionStrBuilder.toString(); + } +} diff --git a/hutool-db/src/test/java/cn/hutool/db/sql/ConditionGroupTest.java b/hutool-db/src/test/java/cn/hutool/db/sql/ConditionGroupTest.java new file mode 100644 index 000000000..3c48c2218 --- /dev/null +++ b/hutool-db/src/test/java/cn/hutool/db/sql/ConditionGroupTest.java @@ -0,0 +1,26 @@ +package cn.hutool.db.sql; + +import org.junit.Test; + +public class ConditionGroupTest { + @Test + public void ConditionGroupToStringTest() { + Condition condition1 = new Condition("a", "A"); + Condition condition2 = new Condition("b", "B"); + condition2.setLinkOperator(LogicalOperator.OR); + Condition condition3 = new Condition("c", "C"); + Condition condition4 = new Condition("d", "D"); + + ConditionGroup cg = new ConditionGroup(); + cg.addConditions(condition1, condition2); + + // 条件组嵌套情况 + ConditionGroup cg2 = new ConditionGroup(); + cg2.addConditions(cg, condition3); + + final ConditionBuilder conditionBuilder = ConditionBuilder.of(cg2, condition4); + + System.out.println(conditionBuilder.build()); + System.out.println(conditionBuilder.getParamValues()); + } +} From 673df9e76a016fd1aa7f8ee0b97b9864c3288ced Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 20 Jan 2022 18:23:43 +0800 Subject: [PATCH 005/156] add templates --- CHANGELOG.md | 1 + hutool-extra/pom.xml | 6 + .../engine/jetbrick/JetbrickEngine.java | 109 ++++++++++++++++++ .../engine/jetbrick/JetbrickTemplate.java | 56 +++++++++ .../jetbrick/loader/StringResourceLoader.java | 82 +++++++++++++ .../engine/jetbrick/package-info.java | 6 + .../cn.hutool.extra.template.TemplateEngine | 1 + .../hutool/extra/template/JetbrickTest.java | 32 +++++ .../extra/template/TemplateUtilTest.java | 2 +- .../resources/templates/jetbrick_test.jetx | 1 + 10 files changed, 295 insertions(+), 1 deletion(-) create mode 100755 hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/JetbrickEngine.java create mode 100755 hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/JetbrickTemplate.java create mode 100755 hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/loader/StringResourceLoader.java create mode 100755 hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/package-info.java create mode 100755 hutool-extra/src/test/java/cn/hutool/extra/template/JetbrickTest.java create mode 100755 hutool-extra/src/test/resources/templates/jetbrick_test.jetx diff --git a/CHANGELOG.md b/CHANGELOG.md index f528a27a2..602317ed0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ # 5.7.21 (2022-01-20) ### 🐣新特性 +* 【extra 】 增加jetbrick模板支持 ### 🐞Bug修复 ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index 15945e1ce..4d289fbd1 100644 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -119,6 +119,12 @@ 2.6.0 true + + com.github.subchen + jetbrick-template + 2.1.10 + true + diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/JetbrickEngine.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/JetbrickEngine.java new file mode 100755 index 000000000..f6b3f24ed --- /dev/null +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/JetbrickEngine.java @@ -0,0 +1,109 @@ +package cn.hutool.extra.template.engine.jetbrick; + +import cn.hutool.extra.template.Template; +import cn.hutool.extra.template.TemplateConfig; +import cn.hutool.extra.template.TemplateEngine; +import jetbrick.template.JetEngine; + +import java.util.Properties; + +/** + * Jetbrick模板引擎封装
+ * 见:https://github.com/subchen/jetbrick-template-2x + * + * @author looly + * @since 5.7.21 + */ +public class JetbrickEngine implements TemplateEngine { + + private JetEngine engine; + + // --------------------------------------------------------------------------------- Constructor start + /** + * 默认构造 + */ + public JetbrickEngine() {} + + /** + * 构造 + * + * @param config 模板配置 + */ + public JetbrickEngine(TemplateConfig config) { + init(config); + } + + /** + * 构造 + * + * @param engine {@link JetEngine} + */ + public JetbrickEngine(JetEngine engine) { + init(engine); + } + // --------------------------------------------------------------------------------- Constructor end + + + @Override + public TemplateEngine init(TemplateConfig config) { + init(createEngine(config)); + return this; + } + + /** + * 初始化引擎 + * @param engine 引擎 + */ + private void init(JetEngine engine){ + this.engine = engine; + } + + @Override + public Template getTemplate(String resource) { + if(null == this.engine){ + init(TemplateConfig.DEFAULT); + } + return JetbrickTemplate.wrap(engine.getTemplate(resource)); + } + + /** + * 创建引擎 + * + * @param config 模板配置 + * @return {@link JetEngine} + */ + private static JetEngine createEngine(TemplateConfig config) { + if (null == config) { + config = TemplateConfig.DEFAULT; + } + + Properties props = new Properties(); + props.setProperty("jetx.input.encoding", config.getCharsetStr()); + props.setProperty("jetx.output.encoding", config.getCharsetStr()); + props.setProperty("jetx.template.loaders", "$loader"); + + switch (config.getResourceMode()){ + case CLASSPATH: + props.setProperty("$loader", "jetbrick.template.loader.ClasspathResourceLoader"); + props.setProperty("$loader.root", config.getPath()); + break; + case FILE: + props.setProperty("$loader", "jetbrick.template.loader.FileSystemResourceLoader"); + props.setProperty("$loader.root", config.getPath()); + break; + case WEB_ROOT: + props.setProperty("$loader", "jetbrick.template.loader.ServletResourceLoader"); + props.setProperty("$loader.root", config.getPath()); + break; + case STRING: + props.setProperty("$loader", "cn.hutool.extra.template.engine.jetbrick.loader.StringResourceLoader"); + props.setProperty("$loader.charset", config.getCharsetStr()); + break; + default: + // 默认 + return JetEngine.create(); + } + + return JetEngine.create(props); + } +} diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/JetbrickTemplate.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/JetbrickTemplate.java new file mode 100755 index 000000000..78470a41f --- /dev/null +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/JetbrickTemplate.java @@ -0,0 +1,56 @@ +package cn.hutool.extra.template.engine.jetbrick; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.TypeReference; +import cn.hutool.extra.template.AbstractTemplate; +import jetbrick.template.JetTemplate; + +import java.io.OutputStream; +import java.io.Serializable; +import java.io.Writer; +import java.util.Map; + +/** + * Jetbrick模板实现
+ * 见:https://github.com/subchen/jetbrick-template-2x + * + * @author looly + * @since 5.7.21 + */ +public class JetbrickTemplate extends AbstractTemplate implements Serializable{ + private static final long serialVersionUID = 1L; + + private final JetTemplate rawTemplate; + + /** + * 包装Jetbrick模板 + * + * @param jetTemplate Jetbrick的模板对象 {@link JetTemplate } + * @return JetbrickTemplate + */ + public static JetbrickTemplate wrap(JetTemplate jetTemplate) { + return (null == jetTemplate) ? null : new JetbrickTemplate(jetTemplate); + } + + /** + * 构造 + * + * @param jetTemplate Jetbrick的模板对象 {@link JetTemplate } + */ + public JetbrickTemplate(JetTemplate jetTemplate) { + this.rawTemplate = jetTemplate; + } + + @Override + public void render(Map bindingMap, Writer writer) { + final Map map = Convert.convert(new TypeReference>() {}, bindingMap); + rawTemplate.render(map, writer); + } + + @Override + public void render(Map bindingMap, OutputStream out) { + final Map map = Convert.convert(new TypeReference>() {}, bindingMap); + rawTemplate.render(map, out); + } + +} diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/loader/StringResourceLoader.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/loader/StringResourceLoader.java new file mode 100755 index 000000000..768970963 --- /dev/null +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/loader/StringResourceLoader.java @@ -0,0 +1,82 @@ +package cn.hutool.extra.template.engine.jetbrick.loader; + +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.StrUtil; +import jetbrick.io.resource.AbstractResource; +import jetbrick.io.resource.Resource; +import jetbrick.io.resource.ResourceNotFoundException; +import jetbrick.template.loader.AbstractResourceLoader; + +import java.io.InputStream; +import java.net.URL; +import java.nio.charset.Charset; + +/** + * 字符串模板加载器 + * + * @author looly + * @since 5.7.21 + */ +public class StringResourceLoader extends AbstractResourceLoader { + + private Charset charset; + + @Override + public Resource load(String name) { + return new StringTemplateResource(name, charset); + } + + /** + * 设置编码 + * @param charset 编码 + */ + public void setCharset(Charset charset){ + this.charset = charset; + } + + /** + * 字符串模板 + * + * @author looly + */ + static class StringTemplateResource extends AbstractResource { + + private final String content; + private final Charset charset; + + /** + * 构造 + * @param content 模板内容 + * @param charset 编码 + */ + public StringTemplateResource(String content, Charset charset){ + this.content = content; + this.charset = charset; + } + + @Override + public InputStream openStream() throws ResourceNotFoundException { + return IoUtil.toStream(content, charset); + } + + @Override + public URL getURL() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean exist() { + return StrUtil.isEmpty(content); + } + + @Override + public String toString() { + return this.content; + } + + @Override + public long lastModified() { + return 1; + } + } +} diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/package-info.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/package-info.java new file mode 100755 index 000000000..0f33263e5 --- /dev/null +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/package-info.java @@ -0,0 +1,6 @@ +/** + * jetbrick-template实现,模板引擎介绍见:https://github.com/subchen/jetbrick-template-2x + * + * @author looly + */ +package cn.hutool.extra.template.engine.jetbrick; diff --git a/hutool-extra/src/main/resources/META-INF/services/cn.hutool.extra.template.TemplateEngine b/hutool-extra/src/main/resources/META-INF/services/cn.hutool.extra.template.TemplateEngine index 798b778cc..04d98dc93 100644 --- a/hutool-extra/src/main/resources/META-INF/services/cn.hutool.extra.template.TemplateEngine +++ b/hutool-extra/src/main/resources/META-INF/services/cn.hutool.extra.template.TemplateEngine @@ -5,3 +5,4 @@ cn.hutool.extra.template.engine.rythm.RythmEngine cn.hutool.extra.template.engine.enjoy.EnjoyEngine cn.hutool.extra.template.engine.thymeleaf.ThymeleafEngine cn.hutool.extra.template.engine.wit.WitEngine +cn.hutool.extra.template.engine.jetbrick.JetbrickEngine diff --git a/hutool-extra/src/test/java/cn/hutool/extra/template/JetbrickTest.java b/hutool-extra/src/test/java/cn/hutool/extra/template/JetbrickTest.java new file mode 100755 index 000000000..1ee03b473 --- /dev/null +++ b/hutool-extra/src/test/java/cn/hutool/extra/template/JetbrickTest.java @@ -0,0 +1,32 @@ +package cn.hutool.extra.template; + +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.template.engine.jetbrick.JetbrickEngine; +import org.junit.Assert; +import org.junit.Test; + +public class JetbrickTest { + + @Test + public void jetbrickEngineTest() { + //classpath模板 + TemplateConfig config = new TemplateConfig("templates", TemplateConfig.ResourceMode.CLASSPATH) + .setCustomEngine(JetbrickEngine.class); + TemplateEngine engine = TemplateUtil.createEngine(config); + Template template = engine.getTemplate("jetbrick_test.jetx"); + String result = template.render(Dict.create().set("name", "hutool")); + Assert.assertEquals("你好,hutool", StrUtil.trim(result)); + } + + @Test + public void jetbrickEngineWithStringTest() { + // 字符串模板 + TemplateConfig config = new TemplateConfig("templates", TemplateConfig.ResourceMode.STRING) + .setCustomEngine(JetbrickEngine.class); + TemplateEngine engine = TemplateUtil.createEngine(config); + Template template = engine.getTemplate("hello,${name}"); + String result = template.render(Dict.create().set("name", "hutool")); + Assert.assertEquals("hello,hutool", StrUtil.trim(result)); + } +} diff --git a/hutool-extra/src/test/java/cn/hutool/extra/template/TemplateUtilTest.java b/hutool-extra/src/test/java/cn/hutool/extra/template/TemplateUtilTest.java index c7db4fa11..2889ddf50 100644 --- a/hutool-extra/src/test/java/cn/hutool/extra/template/TemplateUtilTest.java +++ b/hutool-extra/src/test/java/cn/hutool/extra/template/TemplateUtilTest.java @@ -156,7 +156,7 @@ public class TemplateUtilTest { } @Test - public void WitEngineTest() { + public void witEngineTest() { //classpath模板 TemplateConfig config = new TemplateConfig("templates", ResourceMode.CLASSPATH) .setCustomEngine(WitEngine.class); diff --git a/hutool-extra/src/test/resources/templates/jetbrick_test.jetx b/hutool-extra/src/test/resources/templates/jetbrick_test.jetx new file mode 100755 index 000000000..a471f9f6f --- /dev/null +++ b/hutool-extra/src/test/resources/templates/jetbrick_test.jetx @@ -0,0 +1 @@ +你好,${name} From 7d4d87be829341c493d33e795bbbe1abda86e775 Mon Sep 17 00:00:00 2001 From: naooohu Date: Thu, 20 Jan 2022 21:12:29 +0800 Subject: [PATCH 006/156] =?UTF-8?q?add=20=E6=B7=BB=E5=8A=A0=E8=B7=A8?= =?UTF-8?q?=E6=9C=88=E6=AF=94=E8=BE=83=E6=98=AF=E5=90=A6=E5=9C=A8=E5=90=8C?= =?UTF-8?q?=E4=B8=80=E5=91=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/cn/hutool/core/date/CalendarUtil.java | 4 +--- .../src/test/java/cn/hutool/core/date/DateUtilTest.java | 6 ++++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java index 774aabec5..4c6d3093c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java @@ -359,9 +359,7 @@ public class CalendarUtil { if (cal1 == null || cal2 == null) { throw new IllegalArgumentException("The date must not be null"); } - return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && - cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH) && - cal1.get(Calendar.DAY_OF_WEEK) == cal2.get(Calendar.DAY_OF_WEEK); + return isSameDay(cal1, cal2); } /** diff --git a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java index ceab8fe7e..0aea526a6 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java @@ -1006,13 +1006,15 @@ public class DateUtilTest { } @Test - public void test() { + public void isSameWeektest() { // 周六与周日比较 final boolean isSameWeek = DateUtil.isSameWeek(DateTime.of("2022-01-01", "yyyy-MM-dd"), DateTime.of("2022-01-02", "yyyy-MM-dd"), true); Assert.assertTrue(isSameWeek); // 周日与周一比较 final boolean isSameWeek1 = DateUtil.isSameWeek(DateTime.of("2022-01-02", "yyyy-MM-dd"), DateTime.of("2022-01-03", "yyyy-MM-dd"), false); Assert.assertTrue(isSameWeek1); - + // 跨月比较 + final boolean isSameWeek2 = DateUtil.isSameWeek(DateTime.of("2021-12-29", "yyyy-MM-dd"), DateTime.of("2022-01-01", "yyyy-MM-dd"), true); + Assert.assertTrue(isSameWeek2); } } From 3b6cca7435a4256e57406dc70ed7e31d63948223 Mon Sep 17 00:00:00 2001 From: naooohu Date: Fri, 21 Jan 2022 00:55:34 +0800 Subject: [PATCH 007/156] =?UTF-8?q?fix=20=E6=8A=8A=E6=97=A5=E6=9C=9F?= =?UTF-8?q?=E4=B8=BA=E8=AE=BE=E7=BD=AE=E4=B8=BA=E5=BD=93=E5=89=8D=E5=91=A8?= =?UTF-8?q?=E7=9A=84=E7=AC=AC=E4=B8=80=E5=A4=A9=E4=BB=A3=E7=A0=81=E5=9D=97?= =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E5=88=B0=20CalendarUtil=20=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/hutool/core/date/CalendarUtil.java | 16 +++++++++++++++- .../main/java/cn/hutool/core/date/DateUtil.java | 15 +-------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java index 4c6d3093c..be7e6a41d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java @@ -353,12 +353,26 @@ public class CalendarUtil { * * @param cal1 日期1 * @param cal2 日期2 + * @param isMon 是否为周一。国内第一天为星期一,国外第一天为星期日 * @return 是否为同一周 */ - public static boolean isSameWeek(Calendar cal1, Calendar cal2) { + public static boolean isSameWeek(Calendar cal1, Calendar cal2, boolean isMon) { if (cal1 == null || cal2 == null) { throw new IllegalArgumentException("The date must not be null"); } + // 把所传日期设置为其当前周的第一天 + // 比较设置后的两个日期是否是同一天:true 代表同一周 + if (isMon) { + cal1.setFirstDayOfWeek(Calendar.MONDAY); + cal1.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); + cal2.setFirstDayOfWeek(Calendar.MONDAY); + cal2.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); + } else { + cal1.setFirstDayOfWeek(Calendar.SUNDAY); + cal1.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); + cal2.setFirstDayOfWeek(Calendar.SUNDAY); + cal2.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); + } return isSameDay(cal1, cal2); } 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 066777c78..c887ef349 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 @@ -1598,20 +1598,7 @@ public class DateUtil extends CalendarUtil { if (date1 == null || date2 == null) { throw new IllegalArgumentException("The date must not be null"); } - Calendar calendar1 = calendar(date1); - Calendar calendar2 = calendar(date2); - if (isMon) { - calendar1.setFirstDayOfWeek(Calendar.MONDAY); - calendar1.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); - calendar2.setFirstDayOfWeek(Calendar.MONDAY); - calendar2.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); - } else { - calendar1.setFirstDayOfWeek(Calendar.SUNDAY); - calendar1.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); - calendar2.setFirstDayOfWeek(Calendar.SUNDAY); - calendar2.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); - } - return CalendarUtil.isSameWeek(calendar1, calendar2); + return CalendarUtil.isSameWeek(calendar(date1), calendar(date2), isMon); } /** From f2462892d8b8e3b02315e1e57a99c83ba05e0256 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 21 Jan 2022 11:35:13 +0800 Subject: [PATCH 008/156] add test --- .../java/cn/hutool/core/net/UrlBuilderTest.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/hutool-core/src/test/java/cn/hutool/core/net/UrlBuilderTest.java b/hutool-core/src/test/java/cn/hutool/core/net/UrlBuilderTest.java index 764167662..d6a1e290d 100644 --- a/hutool-core/src/test/java/cn/hutool/core/net/UrlBuilderTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/net/UrlBuilderTest.java @@ -348,4 +348,19 @@ public class UrlBuilderTest { builder.setFragment(builder.getFragment() + "?timestamp=1640391380204"); Assert.assertEquals("https://www.hutool.cn/#/a/b?timestamp=1640391380204", builder.toString()); } + + @Test + public void paramWithPlusTest(){ + String url = "http://127.0.0.1/?" + + "Expires=1642734164&" + + "security-token=CAIS+AF1q6Ft5B2yfSjIr5fYEeju1b1ggpPee2KGpjlgQtdfl43urjz2IHtKdXRvBu8Xs" + + "/4wnmxX7f4YlqB6T55OSAmcNZEoPwKpT4zmMeT7oMWQweEurv" + + "/MQBqyaXPS2MvVfJ+OLrf0ceusbFbpjzJ6xaCAGxypQ12iN+/m6" + + "/Ngdc9FHHPPD1x8CcxROxFppeIDKHLVLozNCBPxhXfKB0ca0WgVy0EHsPnvm5DNs0uH1AKjkbRM9r6ceMb0M5NeW75kSMqw0eBMca7M7TVd8RAi9t0t1" + + "/IVpGiY4YDAWQYLv0rda7DOltFiMkpla7MmXqlft+hzcgeQY0pc" + + "/RqAAYRYVCBiyuzAexSiDiJX1VqWljg4jYp1sdyv3HpV3sXVcf6VH6AN9ot5YNTw4JNO0aNpLpLm93rRMrOKIOsve+OmNyZ4HS7qHQKt1qp7HY1A" + + "/wGhJstkAoGQt+CHSMwVdIx3bVT1+ZYnJdM/oIQ/90afw4EEEQaRE51Z0rQC7z8d"; + final String build = UrlBuilder.of(url).build(); + Assert.assertEquals(url, build); + } } From efeddc146999b73e0a56f7b3e736d523ab95f90b Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 21 Jan 2022 11:47:11 +0800 Subject: [PATCH 009/156] fix bug --- CHANGELOG.md | 3 ++- .../src/main/java/cn/hutool/core/date/ChineseDate.java | 2 +- .../test/java/cn/hutool/core/date/ChineseDateTest.java | 8 ++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 602317ed0..680a1ace4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,12 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.7.21 (2022-01-20) +# 5.7.21 (2022-01-21) ### 🐣新特性 * 【extra 】 增加jetbrick模板支持 ### 🐞Bug修复 +* 【core 】 修复ChineseDate农历获取正月出现数组越界BUG(issue#2112@Github) ------------------------------------------------------------------------------------------------------------- # 5.7.20 (2022-01-20) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java b/hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java index 061489bf3..1dc0d2136 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java @@ -92,7 +92,7 @@ public class ChineseDate { offset -= daysOfMonth; } - this.isLeapMonth = month == (leapMonth + 1); + this.isLeapMonth = leapMonth > 0 && (month == (leapMonth + 1)); if (hasLeapMonth && false == this.isLeapMonth) { // 当前月份前有闰月,则月份显示要-1,除非当前月份就是润月 month--; diff --git a/hutool-core/src/test/java/cn/hutool/core/date/ChineseDateTest.java b/hutool-core/src/test/java/cn/hutool/core/date/ChineseDateTest.java index da29455fb..e2d86d1e9 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/ChineseDateTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/ChineseDateTest.java @@ -105,4 +105,12 @@ public class ChineseDateTest { Assert.assertEquals("戊申猴年 五月初五", c1.toString()); Assert.assertEquals("戊申猴年 闰五月初五", c2.toString()); } + + @Test + public void getChineseMonthTest2(){ + //https://github.com/dromara/hutool/issues/2112 + ChineseDate springFestival = new ChineseDate(DateUtil.parseDate("2022-02-01")); + final String chineseMonth = springFestival.getChineseMonth(); + Assert.assertEquals("一月", chineseMonth); + } } From 158290c38808044cc65c41a176db9ae9e55d9715 Mon Sep 17 00:00:00 2001 From: VampireAchao Date: Sat, 22 Jan 2022 12:08:36 +0800 Subject: [PATCH 010/156] =?UTF-8?q?AsyncUtil=E4=B8=8B=E5=A2=9E=E5=8A=A0get?= =?UTF-8?q?Opt=E6=96=B9=E6=B3=95=EF=BC=8C=E7=94=A8=E4=BA=8E=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E5=A4=B1=E8=B4=A5=E6=97=B6=E6=8F=90=E4=BE=9B=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=80=BC=EF=BC=8C=E4=B9=9F=E8=83=BD=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=BC=82=E5=B8=B8;=E6=8B=93=E5=B1=95?= =?UTF-8?q?=E4=BA=86Opt.ofEmptyAble=E6=96=B9=E6=B3=95=EF=BC=8C=E4=BD=BF?= =?UTF-8?q?=E5=85=B6=E5=8F=AF=E4=BB=A5=E5=88=A4=E6=96=ADCollection?= =?UTF-8?q?=E4=B8=8B=E7=9A=84=E5=85=B6=E4=BB=96=E9=9B=86=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/cn/hutool/core/lang/Opt.java | 11 ++++++----- .../main/java/cn/hutool/core/thread/AsyncUtil.java | 13 +++++++++++++ .../java/cn/hutool/core/thread/AsyncUtilTest.java | 9 +++++++++ 3 files changed, 28 insertions(+), 5 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 dad1b5cd0..363d3a625 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 @@ -24,12 +24,12 @@ */ package cn.hutool.core.lang; -import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.func.Func0; import cn.hutool.core.lang.func.VoidFunc0; import cn.hutool.core.util.StrUtil; -import java.util.List; +import java.util.Collection; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; @@ -101,18 +101,19 @@ public class Opt { } /** - * 返回一个包裹里{@code List}集合可能为空的{@code Opt},额外判断了集合内元素为空的情况 + * 返回一个包裹里{@code Collection}集合可能为空的{@code Opt},额外判断了集合内元素为空的情况 * * @param value 传入需要包裹的元素 * @param 包裹里元素的类型 * @return 一个包裹里元素可能为空的 {@code Opt} * @since 5.7.17 */ - public static Opt> ofEmptyAble(List value) { - return CollectionUtil.isEmpty(value) ? empty() : new Opt<>(value); + public static > Opt ofEmptyAble(R value) { + return CollUtil.isEmpty(value) ? empty() : new Opt<>(value); } /** + * 传入一段操作,包裹异常 * * @param supplier 操作 * @param 类型 diff --git a/hutool-core/src/main/java/cn/hutool/core/thread/AsyncUtil.java b/hutool-core/src/main/java/cn/hutool/core/thread/AsyncUtil.java index ab9947744..4dc8efcee 100644 --- a/hutool-core/src/main/java/cn/hutool/core/thread/AsyncUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/thread/AsyncUtil.java @@ -1,5 +1,7 @@ package cn.hutool.core.thread; +import cn.hutool.core.lang.Opt; + import java.lang.reflect.UndeclaredThrowableException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -60,4 +62,15 @@ public class AsyncUtil { } } + /** + * 获取异步任务结果,包裹了异常,并返回 {@link Opt} + * + * @param 任务返回值类型 + * @param task 异步任务 + * @return 任务返回值 + */ + public static Opt getOpt(CompletableFuture task) { + return Opt.ofTry(task::get); + } + } diff --git a/hutool-core/src/test/java/cn/hutool/core/thread/AsyncUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/thread/AsyncUtilTest.java index 89d6640d2..e7bdc110d 100644 --- a/hutool-core/src/test/java/cn/hutool/core/thread/AsyncUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/thread/AsyncUtilTest.java @@ -1,5 +1,7 @@ package cn.hutool.core.thread; +import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.core.lang.Opt; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -34,5 +36,12 @@ public class AsyncUtilTest { AsyncUtil.waitAll(hutool, sweater, warm); // 获取结果 Assert.assertEquals("hutool卫衣真暖和", AsyncUtil.get(hutool) + AsyncUtil.get(sweater) + AsyncUtil.get(warm)); + + Opt opt = AsyncUtil.getOpt(CompletableFuture.supplyAsync(() -> { + ExceptionUtil.wrapRuntimeAndThrow("Ops!"); + return "whatever"; + })); + Assert.assertTrue(opt.isFail()); + Assert.assertEquals("java.lang.RuntimeException: Ops!", opt.getException().getMessage()); } } From 74c1aa12a3f4b6003aa8525e769e5c9d9f48ad7e Mon Sep 17 00:00:00 2001 From: lsx0310 Date: Mon, 24 Jan 2022 23:53:26 +0800 Subject: [PATCH 011/156] =?UTF-8?q?=E5=A2=9E=E5=8A=A0MetroHash=E7=AE=97?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/hutool/core/lang/hash/MetroHash.java | 233 ++++++++++++++++++ .../java/cn/hutool/core/util/HashUtil.java | 86 +++++++ .../cn/hutool/core/lang/MetroHashTest.java | 81 ++++++ hutool-cuckooFilter/pom.xml | 26 ++ pom.xml | 3 +- 5 files changed, 428 insertions(+), 1 deletion(-) create mode 100644 hutool-core/src/main/java/cn/hutool/core/lang/hash/MetroHash.java create mode 100644 hutool-core/src/test/java/cn/hutool/core/lang/MetroHashTest.java create mode 100644 hutool-cuckooFilter/pom.xml diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/hash/MetroHash.java b/hutool-core/src/main/java/cn/hutool/core/lang/hash/MetroHash.java new file mode 100644 index 000000000..e86dc3d97 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/hash/MetroHash.java @@ -0,0 +1,233 @@ +package cn.hutool.core.lang.hash; + +import java.util.Arrays; + +/** + * Apache 发布的MetroHash算法,是一组用于非加密用例的最先进的哈希函数。 + * 除了卓越的性能外,他们还以算法生成而著称。 + * + *

+ * 官方实现:https://github.com/jandrewrogers/MetroHash + * 官方文档:http://www.jandrewrogers.com/2015/05/27/metrohash/ + * Go语言实现:https://github.com/linvon/cuckoo-filter/blob/main/vendor/github.com/dgryski/go-metro/ + * @author li + */ + +public class MetroHash { + + /** + * hash64 种子加盐 + */ + private final static long k0_64 = 0xD6D018F5; + private final static long k1_64 = 0xA2AA033B; + private final static long k2_64 = 0x62992FC1; + private final static long k3_64 = 0x30BC5B29; + + /** + * hash128 种子加盐 + */ + private final static long k0_128 = 0xC83A91E1; + private final static long k1_128 = 0x8648DBDB; + private final static long k2_128 = 0x7BDEC03B; + private final static long k3_128 = 0x2F5870A5; + + public static long hash64(String str) { + return hash64(str, 1337); + } + + public static long hash64(byte[] data) { + return hash64(data, 1337); + } + + public static long hash64(String str, long seed) { + return hash64(str.getBytes(), seed); + } + + public static Number128 hash128(String str) { + return hash128(str, 1337); + } + + public static Number128 hash128(byte[] data) { + return hash128(data, 1337); + } + + public static Number128 hash128(String str, long seed) { + return hash128(str.getBytes(), seed); + } + + public static long hash64(byte[] data, long seed) { + byte[] buffer = data; + long hash = (seed + k2_64) * k0_64; + + long v0, v1, v2, v3; + v0 = hash; + v1 = hash; + v2 = hash; + v3 = hash; + + if (buffer.length >= 32) { + + while (buffer.length >= 32) { + v0 += littleEndian64(Arrays.copyOfRange(buffer, 0, 8)) * k0_64; + v0 = rotateLeft64(v0, -29) + v2; + v1 += littleEndian64(Arrays.copyOfRange(buffer, 8, 16)) * k1_64; + v1 = rotateLeft64(v1, -29) + v3; + v2 += littleEndian64(Arrays.copyOfRange(buffer, 16, 24)) * k2_64; + v2 = rotateLeft64(v2, -29) + v0; + v3 += littleEndian64(Arrays.copyOfRange(buffer, 24, 32)) * k3_64; + v3 = rotateLeft64(v3, -29) + v1; + buffer = Arrays.copyOfRange(buffer, 32, buffer.length); + } + + v2 ^= rotateLeft64(((v0 + v3) * k0_64) + v1, -37) * k1_64; + v3 ^= rotateLeft64(((v1 + v2) * k1_64) + v0, -37) * k0_64; + v0 ^= rotateLeft64(((v0 + v2) * k0_64) + v3, -37) * k1_64; + v1 ^= rotateLeft64(((v1 + v3) * k1_64) + v2, -37) * k0_64; + hash += v0 ^ v1; + } + + if (buffer.length >= 16) { + v0 = hash + littleEndian64(Arrays.copyOfRange(buffer, 0, 8)) * k2_64; + v0 = rotateLeft64(v0, -29) * k3_64; + v1 = hash + littleEndian64(Arrays.copyOfRange(buffer, 8, 16)) * k2_64; + v1 = rotateLeft64(v1, -29) * k3_64; + v0 ^= rotateLeft64(v0 * k0_64, -21) + v1; + v1 ^= rotateLeft64(v1 * k3_64, -21) + v0; + hash += v1; + buffer = Arrays.copyOfRange(buffer, 16, buffer.length); + } + + if (buffer.length >= 8) { + hash += littleEndian64(Arrays.copyOfRange(buffer, 0, 8)) * k3_64; + buffer = Arrays.copyOfRange(buffer, 8, buffer.length); + hash ^= rotateLeft64(hash, -55) * k1_64; + } + + if (buffer.length >= 4) { + hash += (long) littleEndian32(Arrays.copyOfRange(buffer, 0, 4)) * k3_64; + hash ^= rotateLeft64(hash, -26) * k1_64; + buffer = Arrays.copyOfRange(buffer, 4, buffer.length); + } + + if (buffer.length >= 2) { + hash += (long) littleEndian16(Arrays.copyOfRange(buffer, 0, 2)) * k3_64; + buffer = Arrays.copyOfRange(buffer, 2, buffer.length); + hash ^= rotateLeft64(hash, -48) * k1_64; + } + + if (buffer.length >= 1) { + hash += (long) buffer[0] * k3_64; + hash ^= rotateLeft64(hash, -38) * k1_64; + } + + hash ^= rotateLeft64(hash, -28); + hash *= k0_64; + hash ^= rotateLeft64(hash, -29); + + return hash; + } + + + public static Number128 hash128(byte[] data, long seed) { + byte[] buffer = data; + + long v0, v1, v2, v3; + + v0 = (seed - k0_128) * k3_128; + v1 = (seed + k1_128) * k2_128; + + if (buffer.length >= 32) { + v2 = (seed + k0_128) * k2_128; + v3 = (seed - k1_128) * k3_128; + + while (buffer.length >= 32) { + v0 += littleEndian64(buffer) * k0_128; + buffer = Arrays.copyOfRange(buffer, 8, buffer.length); + v0 = rotateRight(v0, 29) + v2; + v1 += littleEndian64(buffer) * k1_128; + buffer = Arrays.copyOfRange(buffer, 8, buffer.length); + v1 = rotateRight(v1, 29) + v3; + v2 += littleEndian64(buffer) * k2_128; + buffer = Arrays.copyOfRange(buffer, 8, buffer.length); + v2 = rotateRight(v2, 29) + v0; + v3 = littleEndian64(buffer) * k3_128; + buffer = Arrays.copyOfRange(buffer, 8, buffer.length); + v3 = rotateRight(v3, 29) + v1; + } + + v2 ^= rotateRight(((v0 + v3) * k0_128) + v1, 21) * k1_128; + v3 ^= rotateRight(((v1 + v2) * k1_128) + v0, 21) * k0_128; + v0 ^= rotateRight(((v0 + v2) * k0_128) + v3, 21) * k1_128; + v1 ^= rotateRight(((v1 + v3) * k1_128) + v2, 21) * k0_128; + } + + if (buffer.length >= 16) { + v0 += littleEndian64(buffer) * k2_128; + buffer = Arrays.copyOfRange(buffer, 8, buffer.length); + v0 = rotateRight(v0, 33) * k3_128; + v1 += littleEndian64(buffer) * k2_128; + buffer = Arrays.copyOfRange(buffer, 8, buffer.length); + v1 = rotateRight(v1, 33) * k3_128; + v0 ^= rotateRight((v0 * k2_128) + v1, 45) + k1_128; + v1 ^= rotateRight((v1 * k3_128) + v0, 45) + k0_128; + } + + if (buffer.length >= 8) { + v0 += littleEndian64(buffer) * k2_128; + buffer = Arrays.copyOfRange(buffer, 8, buffer.length); + v0 = rotateRight(v0, 33) * k3_128; + v0 ^= rotateRight((v0 * k2_128) + v1, 27) * k1_128; + } + + if (buffer.length >= 4) { + v1 += (long) littleEndian32(buffer) * k2_128; + buffer = Arrays.copyOfRange(buffer, 4, buffer.length); + v1 = rotateRight(v1, 33) * k3_128; + v1 ^= rotateRight((v1 * k3_128) + v0, 46) * k0_128; + } + + if (buffer.length >= 2) { + v0 += (long) littleEndian16(buffer) * k2_128; + buffer = Arrays.copyOfRange(buffer, 2, buffer.length); + v0 = rotateRight(v0, 33) * k3_128; + v0 ^= rotateRight((v0 * k2_128) * v1, 22) * k1_128; + } + + if (buffer.length >= 1) { + v1 += (long) buffer[0] * k2_128; + v1 = rotateRight(v1, 33) * k3_128; + v1 ^= rotateRight((v1 * k3_128) + v0, 58) * k0_128; + } + + v0 += rotateRight((v0 * k0_128) + v1, 13); + v1 += rotateRight((v1 * k1_128) + v0, 37); + v0 += rotateRight((v0 * k2_128) + v1, 13); + v1 += rotateRight((v1 * k3_128) + v0, 37); + + return new Number128(v0, v1); + } + + + private static long littleEndian64(byte[] b) { + return (long) b[0] | (long) (b[1]) << 8 | (long) b[2] << 16 | (long) b[3] << 24 | + (long) b[4] << 32 | (long) b[5] << 40 | (long) b[6] << 48 | (long) b[7] << 56; + } + + private static int littleEndian32(byte[] b) { + return (int) b[0] | (int) b[1] << 8 | (int) b[2] << 16 | (int) b[3] << 24; + } + + private static int littleEndian16(byte[] b) { + return (short) b[0] | (short) b[1] << 8; + } + + private static long rotateLeft64(long x, int k) { + int n = 64; + int s = k & (n - 1); + return x << s | x >> (n - s); + } + + private static long rotateRight(long val, int shift) { + return (val >> shift) | (val << (64 - shift)); + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/util/HashUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/HashUtil.java index 97ee1537b..5bd64d5aa 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/HashUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/HashUtil.java @@ -1,6 +1,7 @@ package cn.hutool.core.util; import cn.hutool.core.lang.hash.CityHash; +import cn.hutool.core.lang.hash.MetroHash; import cn.hutool.core.lang.hash.MurmurHash; import cn.hutool.core.lang.hash.Number128; @@ -545,4 +546,89 @@ public class HashUtil { public static long[] cityHash128(byte[] data, Number128 seed) { return CityHash.hash128(data, seed).getLongArray(); } + + /** + * MetroHash 算法64-bit实现 + * + * @param data 数据 + * @param seed 种子 + * @return + */ + public static long metroHash64(byte[] data, long seed) { + return MetroHash.hash64(data, seed); + } + + /** + * MetroHash 算法64-bit实现 + * + * @param data 数据 + * @return + */ + public static long metroHash64(byte[] data) { + return MetroHash.hash64(data); + } + + /** + * MetroHash 算法64-bit实现 + * + * @param str 数据 + * @param seed 种子 + * @return + */ + public static long metroHash64(String str,long seed) { + return MetroHash.hash64(str,seed); + } + + /** + * MetroHash 算法64-bit实现 + * + * @param str 数据 + * @return + */ + public static long metroHash64(String str) { + return MetroHash.hash64(str); + } + + /** + * MetroHash 算法128-bit实现 + * + * @param data 数据 + * @param seed 种子 + * @return hash值,long[0]:低位,long[1]:高位 + */ + public static long[] metroHash128(byte[] data, long seed) { + return MetroHash.hash128(data,seed).getLongArray(); + } + + /** + * MetroHash 算法128-bit实现 + * + * @param data 数据 + * @return hash值,long[0]:低位,long[1]:高位 + */ + public static long[] metroHash128(byte[] data) { + return MetroHash.hash128(data).getLongArray(); + } + + /** + * MetroHash 算法128-bit实现 + * + * @param str 数据 + * @return hash值,long[0]:低位,long[1]:高位 + */ + public static long[] metroHash128(String str) { + return MetroHash.hash128(str).getLongArray(); + } + + /** + * MetroHash 算法128-bit实现 + * + * @param str 数据 + * @param seed 种子 + * @return hash值,long[0]:低位,long[1]:高位 + */ + public static long[] metroHash128(String str, long seed) { + return MetroHash.hash128(str,seed).getLongArray(); + } + } diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/MetroHashTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/MetroHashTest.java new file mode 100644 index 000000000..b30b5f9f7 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/lang/MetroHashTest.java @@ -0,0 +1,81 @@ +package cn.hutool.core.lang; + + +import cn.hutool.core.lang.hash.CityHash; +import cn.hutool.core.lang.hash.MetroHash; +import org.junit.Test; + +import java.util.Random; + +public class MetroHashTest { + + + /** + * 数据量越大 MetroHash 优势越明显, + */ + @Test + public void bulkHashing64Test() { + String[] strArray = getRandomStringArray(10000000); + long startCity = System.currentTimeMillis(); + for (String s : strArray) { + CityHash.hash64(s.getBytes()); + } + long endCity = System.currentTimeMillis(); + + long startMetro = System.currentTimeMillis(); + for (String s : strArray) { + MetroHash.hash64(s); + } + long endMetro = System.currentTimeMillis(); + + System.out.println("metroHash =============" + (endMetro - startMetro)); + System.out.println("cityHash =============" + (endCity - startCity)); + } + + + /** + * 数据量越大 MetroHash 优势越明显, + */ + @Test + public void bulkHashing128Test() { + String[] strArray = getRandomStringArray(10000000); + long startCity = System.currentTimeMillis(); + for (String s : strArray) { + CityHash.hash128(s.getBytes()); + } + long endCity = System.currentTimeMillis(); + + long startMetro = System.currentTimeMillis(); + for (String s : strArray) { + MetroHash.hash128(s); + } + long endMetro = System.currentTimeMillis(); + + System.out.println("metroHash =============" + (endMetro - startMetro)); + System.out.println("cityHash =============" + (endCity - startCity)); + } + + + private static String[] getRandomStringArray(int length) { + String[] result = new String[length]; + Random random = new Random(); + int index = 0; + while (index < length) { + result[index++] = getRandomString(random.nextInt(64)); + } + return result; + } + + private static String getRandomString(int length) { + String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + Random random = new Random(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < length; i++) { + int number = random.nextInt(62); + sb.append(str.charAt(number)); + } + return sb.toString(); + } + + +} diff --git a/hutool-cuckooFilter/pom.xml b/hutool-cuckooFilter/pom.xml new file mode 100644 index 000000000..793315b04 --- /dev/null +++ b/hutool-cuckooFilter/pom.xml @@ -0,0 +1,26 @@ + + + + hutool-parent + cn.hutool + 5.7.19 + + 4.0.0 + jar + + hutool-cuckooFilter + ${project.artifactId} + Hutool 布谷鸟过滤器 + + + + + cn.hutool + hutool-core + ${project.parent.version} + + + + diff --git a/pom.xml b/pom.xml index 673cdadb7..6d2609f28 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,8 @@ hutool-captcha hutool-socket hutool-jwt - + hutool-cuckooFilter + utf-8 From bdeae6f02ebfc368c0f228fb302d27fb2b703ebd Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 7 Jan 2022 21:14:54 +0800 Subject: [PATCH 012/156] prepare 5.7.20 --- CHANGELOG.md | 6 ++++++ README-EN.md | 6 +++--- README.md | 6 +++--- bin/version.txt | 2 +- docs/js/version.js | 2 +- hutool-all/pom.xml | 2 +- hutool-aop/pom.xml | 2 +- hutool-bloomFilter/pom.xml | 2 +- hutool-bom/pom.xml | 2 +- hutool-cache/pom.xml | 2 +- hutool-captcha/pom.xml | 2 +- hutool-core/pom.xml | 2 +- hutool-cron/pom.xml | 2 +- hutool-crypto/pom.xml | 2 +- hutool-db/pom.xml | 2 +- hutool-dfa/pom.xml | 2 +- hutool-extra/pom.xml | 2 +- hutool-http/pom.xml | 2 +- hutool-json/pom.xml | 2 +- hutool-jwt/pom.xml | 2 +- hutool-log/pom.xml | 2 +- hutool-poi/pom.xml | 2 +- hutool-script/pom.xml | 2 +- hutool-setting/pom.xml | 2 +- hutool-socket/pom.xml | 2 +- hutool-system/pom.xml | 2 +- pom.xml | 2 +- 27 files changed, 36 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 208ee2fe9..95e774205 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ ------------------------------------------------------------------------------------------------------------- +# 5.7.20 (2022-01-07) + +### 🐣新特性 +### 🐞Bug修复 + +------------------------------------------------------------------------------------------------------------- # 5.7.19 (2022-01-07) ### 🐣新特性 diff --git a/README-EN.md b/README-EN.md index 07ec93b86..b55c1128d 100644 --- a/README-EN.md +++ b/README-EN.md @@ -142,18 +142,18 @@ We provide the T-Shirt and Sweater with Hutool Logo, please visit the shop: cn.hutool hutool-all - 5.7.19 + 5.7.20 ``` ### 🍐Gradle ``` -implementation 'cn.hutool:hutool-all:5.7.19' +implementation 'cn.hutool:hutool-all:5.7.20' ``` ## 📥Download -- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.7.19/) +- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.7.20/) > 🔔️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 aa2154e23..8aeb70262 100644 --- a/README.md +++ b/README.md @@ -142,20 +142,20 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不 cn.hutool hutool-all - 5.7.19 + 5.7.20 ``` ### 🍐Gradle ``` -implementation 'cn.hutool:hutool-all:5.7.19' +implementation 'cn.hutool:hutool-all:5.7.20' ``` ### 📥下载jar 点击以下链接,下载`hutool-all-X.X.X.jar`即可: -- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.7.19/) +- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.7.20/) > 🔔️注意 > Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。 diff --git a/bin/version.txt b/bin/version.txt index 1ccc37576..b0917fb0e 100755 --- a/bin/version.txt +++ b/bin/version.txt @@ -1 +1 @@ -5.7.19 +5.7.20 diff --git a/docs/js/version.js b/docs/js/version.js index 90d3c3b3a..978cfac6d 100644 --- a/docs/js/version.js +++ b/docs/js/version.js @@ -1 +1 @@ -var version = '5.7.19' \ No newline at end of file +var version = '5.7.20' \ No newline at end of file diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index 9dbbfdc1f..10a7032a4 100644 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-all diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml index 35e36768f..edc46b7a7 100644 --- a/hutool-aop/pom.xml +++ b/hutool-aop/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-aop diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml index 82e8163aa..abeaec1c1 100644 --- a/hutool-bloomFilter/pom.xml +++ b/hutool-bloomFilter/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-bloomFilter diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml index 2db026910..3b8ad4fd4 100644 --- a/hutool-bom/pom.xml +++ b/hutool-bom/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-bom diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml index 91a94dc0d..d544b5527 100644 --- a/hutool-cache/pom.xml +++ b/hutool-cache/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-cache diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml index 4bd96f6e5..5dd8f9f15 100644 --- a/hutool-captcha/pom.xml +++ b/hutool-captcha/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-captcha diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index 2548d3862..0129bcab8 100644 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-core diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml index ba2fdbfd2..d95c455b4 100644 --- a/hutool-cron/pom.xml +++ b/hutool-cron/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-cron diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml index 46da18d6b..50f7356ac 100644 --- a/hutool-crypto/pom.xml +++ b/hutool-crypto/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-crypto diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index 7b35e41ad..92fe54fa8 100644 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-db diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml index 37bd3ae42..183c0eff9 100644 --- a/hutool-dfa/pom.xml +++ b/hutool-dfa/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-dfa diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index 2fd49d272..7fca763ac 100644 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-extra diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index de2525d33..a27a4ac72 100644 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-http diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index ef9c36c8a..5103dc136 100644 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-json diff --git a/hutool-jwt/pom.xml b/hutool-jwt/pom.xml index f818fc158..7520a39c4 100644 --- a/hutool-jwt/pom.xml +++ b/hutool-jwt/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-jwt diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index 0d97e4362..075926147 100644 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-log diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index 826579e9c..f80d0c8e9 100644 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-poi diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml index 7a6c33e2c..21854b669 100644 --- a/hutool-script/pom.xml +++ b/hutool-script/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-script diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml index cbbc6a4c9..107bd6367 100644 --- a/hutool-setting/pom.xml +++ b/hutool-setting/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-setting diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml index 1839e22bf..26529bfd2 100644 --- a/hutool-socket/pom.xml +++ b/hutool-socket/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-socket diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml index 0e2f0ec12..ca87e5d2d 100644 --- a/hutool-system/pom.xml +++ b/hutool-system/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool-system diff --git a/pom.xml b/pom.xml index 6d2609f28..b6cee2017 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.7.19 + 5.7.20-SNAPSHOT hutool Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。 https://github.com/dromara/hutool From 6ed92bfacf869a09d5d7616512030c46c98c7a7c Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 8 Jan 2022 13:36:57 +0800 Subject: [PATCH 013/156] fix bug --- CHANGELOG.md | 3 +- .../java/cn/hutool/core/bean/BeanDesc.java | 44 ++++------- .../java/cn/hutool/core/bean/BeanUtil.java | 7 +- .../core/lang/reflect/MethodHandleUtil.java | 5 +- .../java/cn/hutool/core/util/ReflectUtil.java | 78 ++++++++++++++++++- .../cn/hutool/core/bean/Issue2082Test.java | 33 ++++++++ 6 files changed, 129 insertions(+), 41 deletions(-) create mode 100755 hutool-core/src/test/java/cn/hutool/core/bean/Issue2082Test.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 95e774205..aba46ae03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,11 @@ ------------------------------------------------------------------------------------------------------------- -# 5.7.20 (2022-01-07) +# 5.7.20 (2022-01-08) ### 🐣新特性 ### 🐞Bug修复 +* 【core 】 修复setter重载导致匹配错误(issue#2082@Github) ------------------------------------------------------------------------------------------------------------- # 5.7.19 (2022-01-07) diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/BeanDesc.java b/hutool-core/src/main/java/cn/hutool/core/bean/BeanDesc.java index 65411b497..976f40d29 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanDesc.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanDesc.java @@ -140,14 +140,12 @@ public class BeanDesc implements Serializable { * @return this */ private BeanDesc init() { - final Method[] methods = ReflectUtil.getMethods(this.beanClass); + final Method[] gettersAndSetters = ReflectUtil.getMethods(this.beanClass, ReflectUtil::isGetterOrSetterIgnoreCase); PropDesc prop; for (Field field : ReflectUtil.getFields(this.beanClass)) { - if (false == ModifierUtil.isStatic(field) && - // 排除对象子类 - false == "this$0".equals(field.getName())) { - //只针对非static属性 - prop = createProp(field, methods); + // 排除静态属性和对象子类 + if (false == ModifierUtil.isStatic(field) && false == ReflectUtil.isOuterClassField(field)) { + prop = createProp(field, gettersAndSetters); // 只有不存在时才放入,防止父类属性覆盖子类属性 this.propMap.putIfAbsent(prop.getFieldName(), prop); } @@ -190,12 +188,12 @@ public class BeanDesc implements Serializable { /** * 查找字段对应的Getter和Setter方法 * - * @param field 字段 - * @param methods 类中所有的方法 - * @param ignoreCase 是否忽略大小写匹配 + * @param field 字段 + * @param gettersOrSetters 类中所有的Getter或Setter方法 + * @param ignoreCase 是否忽略大小写匹配 * @return PropDesc */ - private PropDesc findProp(Field field, Method[] methods, boolean ignoreCase) { + private PropDesc findProp(Field field, Method[] gettersOrSetters, boolean ignoreCase) { final String fieldName = field.getName(); final Class fieldType = field.getType(); final boolean isBooleanField = BooleanUtil.isBoolean(fieldType); @@ -203,24 +201,19 @@ public class BeanDesc implements Serializable { Method getter = null; Method setter = null; String methodName; - Class[] parameterTypes; - for (Method method : methods) { - parameterTypes = method.getParameterTypes(); - if (parameterTypes.length > 1) { - // 多于1个参数说明非Getter或Setter - continue; - } - + for (Method method : gettersOrSetters) { methodName = method.getName(); - if (parameterTypes.length == 0) { + if (method.getParameterCount() == 0) { // 无参数,可能为Getter方法 if (isMatchGetter(methodName, fieldName, isBooleanField, ignoreCase)) { // 方法名与字段名匹配,则为Getter方法 getter = method; } } else if (isMatchSetter(methodName, fieldName, isBooleanField, ignoreCase)) { - // 只有一个参数的情况下方法名与字段名对应匹配,则为Setter方法 - setter = method; + // setter方法的参数类型和字段类型必须一致,或参数类型是字段类型的子类 + if(fieldType.isAssignableFrom(method.getParameterTypes()[0])){ + setter = method; + } } if (null != getter && null != setter) { // 如果Getter和Setter方法都找到了,不再继续寻找 @@ -261,15 +254,6 @@ public class BeanDesc implements Serializable { handledFieldName = StrUtil.upperFirst(fieldName); } - if (false == methodName.startsWith("get") && false == methodName.startsWith("is")) { - // 非标准Getter方法 - return false; - } - if ("getclass".equals(methodName)) { - //跳过getClass方法 - return false; - } - // 针对Boolean类型特殊检查 if (isBooleanField) { if (fieldName.startsWith("is")) { 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 796124648..d9452cd14 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java @@ -88,9 +88,8 @@ public class BeanUtil { */ public static boolean hasSetter(Class clazz) { if (ClassUtil.isNormalClass(clazz)) { - final Method[] methods = clazz.getMethods(); - for (Method method : methods) { - if (method.getParameterTypes().length == 1 && method.getName().startsWith("set")) { + for (Method method : clazz.getMethods()) { + if (method.getParameterCount() == 1 && method.getName().startsWith("set")) { // 检测包含标准的setXXX方法即视为标准的JavaBean return true; } @@ -110,7 +109,7 @@ public class BeanUtil { public static boolean hasGetter(Class clazz) { if (ClassUtil.isNormalClass(clazz)) { for (Method method : clazz.getMethods()) { - if (method.getParameterTypes().length == 0) { + if (method.getParameterCount() == 0) { if (method.getName().startsWith("get") || method.getName().startsWith("is")) { return true; } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/reflect/MethodHandleUtil.java b/hutool-core/src/main/java/cn/hutool/core/lang/reflect/MethodHandleUtil.java index 781208744..fbfa2ded3 100755 --- a/hutool-core/src/main/java/cn/hutool/core/lang/reflect/MethodHandleUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/reflect/MethodHandleUtil.java @@ -12,6 +12,7 @@ import java.lang.reflect.Method; /** * 方法句柄{@link MethodHandle}封装工具类
+ * 方法句柄是一个有类型的,可以直接执行的指向底层方法、构造器、field等的引用,可以简单理解为函数指针,它是一种更加底层的查找、调整和调用方法的机制。 * 参考: *