From a0ae51eebba6ffe27b3b49619e72166dabacf330 Mon Sep 17 00:00:00 2001 From: unufolio Date: Mon, 14 Dec 2020 10:34:51 +0800 Subject: [PATCH 01/54] fix typo in NumberUtil --- .../java/cn/hutool/core/util/NumberUtil.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java index 96f17de45..347059239 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java @@ -41,7 +41,7 @@ public class NumberUtil { /** * 默认除法运算精度 */ - private static final int DEFAUT_DIV_SCALE = 10; + private static final int DEFAULT_DIV_SCALE = 10; /** * 0-20对应的阶乘,超过20的阶乘会超过Long.MAX_VALUE @@ -484,7 +484,7 @@ public class NumberUtil { * @return 两个参数的商 */ public static double div(float v1, float v2) { - return div(v1, v2, DEFAUT_DIV_SCALE); + return div(v1, v2, DEFAULT_DIV_SCALE); } /** @@ -495,7 +495,7 @@ public class NumberUtil { * @return 两个参数的商 */ public static double div(float v1, double v2) { - return div(v1, v2, DEFAUT_DIV_SCALE); + return div(v1, v2, DEFAULT_DIV_SCALE); } /** @@ -506,7 +506,7 @@ public class NumberUtil { * @return 两个参数的商 */ public static double div(double v1, float v2) { - return div(v1, v2, DEFAUT_DIV_SCALE); + return div(v1, v2, DEFAULT_DIV_SCALE); } /** @@ -517,7 +517,7 @@ public class NumberUtil { * @return 两个参数的商 */ public static double div(double v1, double v2) { - return div(v1, v2, DEFAUT_DIV_SCALE); + return div(v1, v2, DEFAULT_DIV_SCALE); } /** @@ -528,7 +528,7 @@ public class NumberUtil { * @return 两个参数的商 */ public static double div(Double v1, Double v2) { - return div(v1, v2, DEFAUT_DIV_SCALE); + return div(v1, v2, DEFAULT_DIV_SCALE); } /** @@ -540,7 +540,7 @@ public class NumberUtil { * @since 3.1.0 */ public static BigDecimal div(Number v1, Number v2) { - return div(v1, v2, DEFAUT_DIV_SCALE); + return div(v1, v2, DEFAULT_DIV_SCALE); } /** @@ -551,7 +551,7 @@ public class NumberUtil { * @return 两个参数的商 */ public static BigDecimal div(String v1, String v2) { - return div(v1, v2, DEFAUT_DIV_SCALE); + return div(v1, v2, DEFAULT_DIV_SCALE); } /** From 0a4e2615016a066b5b0096750a69666550987bd8 Mon Sep 17 00:00:00 2001 From: Golden Looly Date: Mon, 14 Dec 2020 22:35:02 +0800 Subject: [PATCH 02/54] Revert "fix typo in NumberUtil" --- .../java/cn/hutool/core/util/NumberUtil.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java index 347059239..96f17de45 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java @@ -41,7 +41,7 @@ public class NumberUtil { /** * 默认除法运算精度 */ - private static final int DEFAULT_DIV_SCALE = 10; + private static final int DEFAUT_DIV_SCALE = 10; /** * 0-20对应的阶乘,超过20的阶乘会超过Long.MAX_VALUE @@ -484,7 +484,7 @@ public class NumberUtil { * @return 两个参数的商 */ public static double div(float v1, float v2) { - return div(v1, v2, DEFAULT_DIV_SCALE); + return div(v1, v2, DEFAUT_DIV_SCALE); } /** @@ -495,7 +495,7 @@ public class NumberUtil { * @return 两个参数的商 */ public static double div(float v1, double v2) { - return div(v1, v2, DEFAULT_DIV_SCALE); + return div(v1, v2, DEFAUT_DIV_SCALE); } /** @@ -506,7 +506,7 @@ public class NumberUtil { * @return 两个参数的商 */ public static double div(double v1, float v2) { - return div(v1, v2, DEFAULT_DIV_SCALE); + return div(v1, v2, DEFAUT_DIV_SCALE); } /** @@ -517,7 +517,7 @@ public class NumberUtil { * @return 两个参数的商 */ public static double div(double v1, double v2) { - return div(v1, v2, DEFAULT_DIV_SCALE); + return div(v1, v2, DEFAUT_DIV_SCALE); } /** @@ -528,7 +528,7 @@ public class NumberUtil { * @return 两个参数的商 */ public static double div(Double v1, Double v2) { - return div(v1, v2, DEFAULT_DIV_SCALE); + return div(v1, v2, DEFAUT_DIV_SCALE); } /** @@ -540,7 +540,7 @@ public class NumberUtil { * @since 3.1.0 */ public static BigDecimal div(Number v1, Number v2) { - return div(v1, v2, DEFAULT_DIV_SCALE); + return div(v1, v2, DEFAUT_DIV_SCALE); } /** @@ -551,7 +551,7 @@ public class NumberUtil { * @return 两个参数的商 */ public static BigDecimal div(String v1, String v2) { - return div(v1, v2, DEFAULT_DIV_SCALE); + return div(v1, v2, DEFAUT_DIV_SCALE); } /** From 4a8160c822b05ced717f9fcea6504286097ea266 Mon Sep 17 00:00:00 2001 From: Kwok Date: Fri, 25 Dec 2020 14:26:18 +0800 Subject: [PATCH 03/54] Update PropsUtil.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修正注释错误 --- .../src/main/java/cn/hutool/setting/dialect/PropsUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hutool-setting/src/main/java/cn/hutool/setting/dialect/PropsUtil.java b/hutool-setting/src/main/java/cn/hutool/setting/dialect/PropsUtil.java index a8a121c63..3c274c0f3 100644 --- a/hutool-setting/src/main/java/cn/hutool/setting/dialect/PropsUtil.java +++ b/hutool-setting/src/main/java/cn/hutool/setting/dialect/PropsUtil.java @@ -40,9 +40,9 @@ public class PropsUtil { /** * 获取给定路径找到的第一个配置文件
- * * name可以为不包括扩展名的文件名(默认.setting为结尾),也可以是文件名全称 + * * name可以为不包括扩展名的文件名(默认.properties为结尾),也可以是文件名全称 * - * @param names 文件名,如果没有扩展名,默认为.setting + * @param names 文件名,如果没有扩展名,默认为.properties * * @return 当前环境下配置文件 */ From e02abaf128f038e6cbe768ad1c0016ca6a6405d2 Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 27 Dec 2020 02:50:02 +0800 Subject: [PATCH 04/54] fix #I2AQ2M --- CHANGELOG.md | 3 ++- .../src/main/java/cn/hutool/core/util/RuntimeUtil.java | 2 +- .../test/java/cn/hutool/core/util/RuntimeUtilTest.java | 10 +++++++--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67d9a174b..cedb735bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------------------------------------- -# 5.5.5 (2020-12-24) +# 5.5.5 (2020-12-27) ### 新特性 * 【core 】 URLUtil.normalize新增重载(pr#233@Gitee) @@ -19,6 +19,7 @@ * 【core 】 TreeUtil增加空判定(issue#I2ACCW@Gitee) * 【db 】 解决Hive获取表名失败问题(issue#I2AGLU@Gitee) * 【core 】 修复DateUtil.parse未使用严格模式导致结果不正常的问题(issue#1332@Github) +* 【core 】 修复RuntimeUtil.getUsableMemory非static问题(issue#I2AQ2M@Gitee) ------------------------------------------------------------------------------------------------------------- # 5.5.4 (2020-12-16) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/RuntimeUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/RuntimeUtil.java index f4d4f4c16..405825ba1 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/RuntimeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/RuntimeUtil.java @@ -298,7 +298,7 @@ public class RuntimeUtil { * * @return 最大可用内存 */ - public final long getUsableMemory() { + public static long getUsableMemory() { return getMaxMemory() - getTotalMemory() + getFreeMemory(); } } diff --git a/hutool-core/src/test/java/cn/hutool/core/util/RuntimeUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/RuntimeUtilTest.java index 4e45a6384..21accb091 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/RuntimeUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/RuntimeUtilTest.java @@ -1,11 +1,10 @@ package cn.hutool.core.util; +import cn.hutool.core.lang.Console; +import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; -import cn.hutool.core.lang.Console; -import cn.hutool.core.util.RuntimeUtil; - /** * 命令行单元测试 * @author looly @@ -26,4 +25,9 @@ public class RuntimeUtilTest { String str = RuntimeUtil.execForStr("cmd /c dir"); Console.log(str); } + + @Test + public void getUsableMemoryTest(){ + Assert.assertTrue(RuntimeUtil.getUsableMemory() > 0); + } } From a50aba4a7b470678e726f9e627f789cfa5ec179b Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 27 Dec 2020 02:53:54 +0800 Subject: [PATCH 05/54] fix #I2AO8B --- CHANGELOG.md | 1 + .../src/main/java/cn/hutool/core/util/ArrayUtil.java | 7 +------ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cedb735bc..5e7658391 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ * 【db 】 解决Hive获取表名失败问题(issue#I2AGLU@Gitee) * 【core 】 修复DateUtil.parse未使用严格模式导致结果不正常的问题(issue#1332@Github) * 【core 】 修复RuntimeUtil.getUsableMemory非static问题(issue#I2AQ2M@Gitee) +* 【core 】 修复ArrayUtil.equals方法严格判断问题(issue#I2AO8B@Gitee) ------------------------------------------------------------------------------------------------------------- # 5.5.4 (2020-12-16) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java index ccf42f12b..db6d7345d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java @@ -523,7 +523,7 @@ public class ArrayUtil extends PrimitiveArrayUtil { } /** - * 克隆数组,如果非数组返回null + * 克隆数组,如果非数组返回{@code null} * * @param 数组元素类型 * @param obj 数组对象 @@ -1667,11 +1667,6 @@ public class ArrayUtil extends PrimitiveArrayUtil { Assert.isTrue(isArray(array1), "First is not a Array !"); Assert.isTrue(isArray(array2), "Second is not a Array !"); - // 数组类型一致性判断 - if (array1.getClass() != array2.getClass()) { - return false; - } - if (array1 instanceof long[]) { return Arrays.equals((long[]) array1, (long[]) array2); } else if (array1 instanceof int[]) { From b85430ee80a9df15dfd6cb06fa3f34d991a390fd Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 27 Dec 2020 03:20:14 +0800 Subject: [PATCH 06/54] fix #I2AOQW --- hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java | 3 +-- .../src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java index 79d89eb4a..4d599d1c0 100644 --- a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java @@ -170,5 +170,4 @@ public class JSONUtilTest { " \"test\": \"\\\\地库地库\",\n" + "}"); } -} - +} \ No newline at end of file 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 abe9b7176..918a1e937 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 @@ -88,7 +88,8 @@ public class SheetRidReader extends DefaultHandler { String rid = null; String name = null; for (int i = 0; i < length; i++) { - switch (attributes.getLocalName(i)) { + final String attrName = attributes.getQName(i); + switch (attrName) { case SHEET_ID_ATTR: sheetId = attributes.getValue(i); break; From 8e1b7d1fa89fabaf128d4a4855afb0f420581676 Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 27 Dec 2020 03:21:08 +0800 Subject: [PATCH 07/54] fix #I2AOQW --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e7658391..d7a902235 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ * 【core 】 修复DateUtil.parse未使用严格模式导致结果不正常的问题(issue#1332@Github) * 【core 】 修复RuntimeUtil.getUsableMemory非static问题(issue#I2AQ2M@Gitee) * 【core 】 修复ArrayUtil.equals方法严格判断问题(issue#I2AO8B@Gitee) +* 【core 】 修复SheetRidReader在获取rid时读取错误问题(issue#I2AOQW@Gitee) ------------------------------------------------------------------------------------------------------------- # 5.5.4 (2020-12-16) From ee5331f53ecaddb510147ee3c0840bfb59ad288c Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 27 Dec 2020 04:31:46 +0800 Subject: [PATCH 08/54] fix #I2AOQW --- CHANGELOG.md | 2 +- .../poi/excel/sax/Excel03SaxReader.java | 2 +- .../poi/excel/sax/Excel07SaxReader.java | 45 +++++++--- .../poi/excel/sax/SheetDataSaxHandler.java | 2 +- .../hutool/poi/excel/sax/SheetRidReader.java | 89 ++++++++++++------- .../cn/hutool/poi/excel/ExcelSaxReadTest.java | 5 ++ 6 files changed, 97 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7a902235..532ada354 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ * 【core 】 修复DateUtil.parse未使用严格模式导致结果不正常的问题(issue#1332@Github) * 【core 】 修复RuntimeUtil.getUsableMemory非static问题(issue#I2AQ2M@Gitee) * 【core 】 修复ArrayUtil.equals方法严格判断问题(issue#I2AO8B@Gitee) -* 【core 】 修复SheetRidReader在获取rid时读取错误问题(issue#I2AOQW@Gitee) +* 【poi 】 修复SheetRidReader在获取rid时读取错误问题(issue#I2AOQW@Gitee) ------------------------------------------------------------------------------------------------------------- # 5.5.4 (2020-12-16) diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java index dbd97dd04..e64b43d3f 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java @@ -116,7 +116,7 @@ public class Excel03SaxReader implements HSSFListener, ExcelSaxReader { // sheet r:Id前缀 - private static final String RID_PREFIX = "rId"; + public static final String RID_PREFIX = "rId"; private final SheetDataSaxHandler handler; /** @@ -146,21 +145,13 @@ public class Excel07SaxReader implements ExcelSaxReader { * 开始读取Excel,Sheet编号从0开始计数 * * @param xssfReader {@link XSSFReader},Excel读取器 - * @param idOrRid Excel中的sheet id或者rid编号,rid必须加rId前缀,例如rId0,如果为-1处理所有编号的sheet + * @param idOrRid Excel中的sheet id或者rid编号,从0开始,rid必须加rId前缀,例如rId0,如果为-1处理所有编号的sheet * @return this * @throws POIException POI异常 * @since 5.4.4 */ private Excel07SaxReader readSheets(XSSFReader xssfReader, String idOrRid) throws POIException { - // 将sheetId转换为rid - if (NumberUtil.isInteger(idOrRid)) { - final SheetRidReader ridReader = new SheetRidReader(); - final String rid = ridReader.read(xssfReader).getRidBySheetId(idOrRid); - if (StrUtil.isNotEmpty(rid)) { - idOrRid = rid; - } - } - this.handler.sheetIndex = Integer.parseInt(StrUtil.removePrefixIgnoreCase(idOrRid, RID_PREFIX)); + this.handler.sheetIndex = getSheetIndex(xssfReader, idOrRid); InputStream sheetInputStream = null; try { if (this.handler.sheetIndex > -1) { @@ -190,5 +181,35 @@ public class Excel07SaxReader implements ExcelSaxReader { } return this; } + + /** + * 获取sheet索引,从0开始 + *
    + *
  • 传入'rId'开头,直接去除rId前缀
  • + *
  • 传入纯数字,表示sheetIndex,通过{@link SheetRidReader}转换为rId
  • + *
+ * + * @param xssfReader {@link XSSFReader},Excel读取器 + * @param idOrRid Excel中的sheet id或者rid编号,从0开始,rid必须加rId前缀,例如rId0,如果为-1处理所有编号的sheet + * @return sheet索引,从0开始 + * @since 5.5.5 + */ + private int getSheetIndex(XSSFReader xssfReader, String idOrRid){ + // rid直接处理 + if(StrUtil.startWithIgnoreCase(idOrRid, RID_PREFIX)){ + return Integer.parseInt(StrUtil.removePrefixIgnoreCase(idOrRid, RID_PREFIX)); + } + + // sheetIndex需转换为rid + final int sheetIndex = Integer.parseInt(idOrRid); + final SheetRidReader ridReader = new SheetRidReader(); + final Integer rid = ridReader.read(xssfReader).getRidBySheetIdBase0(sheetIndex); + + if(null != rid){ + return rid; + } + + return sheetIndex; + } // --------------------------------------------------------------------------------------- Private method end } \ No newline at end of file diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetDataSaxHandler.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetDataSaxHandler.java index c703691e9..811e1f6cc 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetDataSaxHandler.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetDataSaxHandler.java @@ -29,7 +29,7 @@ public class SheetDataSaxHandler extends DefaultHandler { protected StylesTable stylesTable; // excel 2007 的共享字符串表,对应sharedString.xml protected SharedStringsTable sharedStringsTable; - // sheet的索引 + // sheet的索引,从0开始 protected int sheetIndex; // 当前非空行 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 918a1e937..56c744ec9 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 @@ -17,7 +17,7 @@ import java.util.Map; /** * 在Sax方式读取Excel时,读取sheet标签中sheetId和rid的对应关系,类似于: *
- * <sheet name="Sheet6" sheetId="4" r:id="6"/>
+ * <sheet name="Sheet6" sheetId="4" r:id="rId6"/>
  * 
*

* 读取结果为: @@ -36,8 +36,8 @@ public class SheetRidReader extends DefaultHandler { private final static String SHEET_ID_ATTR = "sheetId"; private final static String NAME_ATTR = "name"; - private final Map ID_RID_MAP = new HashMap<>(); - private final Map NAME_RID_MAP = new HashMap<>(); + private final Map ID_RID_MAP = new HashMap<>(); + private final Map NAME_RID_MAP = new HashMap<>(); /** * 读取Wordkbook的XML中sheet标签中sheetId和rid的对应关系 @@ -61,51 +61,74 @@ public class SheetRidReader extends DefaultHandler { } /** - * 根据sheetId获取rid + * 根据sheetId获取rid,从1开始 * - * @param sheetId Sheet的ID - * @return rid + * @param sheetId Sheet的ID,从1开始 + * @return rid,从1开始 */ - public String getRidBySheetId(String sheetId) { + public Integer getRidBySheetId(int sheetId) { return ID_RID_MAP.get(sheetId); } /** - * 根据sheet name获取rid + * 根据sheetId获取rid,从0开始 + * + * @param sheetId Sheet的ID,从0开始 + * @return rid,从0开始 + * @since 5.5.5 + */ + public Integer getRidBySheetIdBase0(int sheetId) { + final Integer rid = getRidBySheetId(sheetId + 1); + if(null != rid){ + return rid - 1; + } + return null; + } + + /** + * 根据sheet name获取rid,从1开始 * * @param sheetName Sheet的name - * @return rid + * @return rid,从1开始 */ - public String getRidByName(String sheetName) { + public Integer getRidByName(String sheetName) { return NAME_RID_MAP.get(sheetName); } + /** + * 根据sheet name获取rid,从0开始 + * + * @param sheetName Sheet的name + * @return rid,从0开始 + * @since 5.5.5 + */ + public Integer getRidByNameBase0(String sheetName) { + final Integer rid = getRidByName(sheetName); + if(null != rid){ + return rid - 1; + } + return null; + } + @Override public void startElement(String uri, String localName, String qName, Attributes attributes) { if (TAG_NAME.equalsIgnoreCase(localName)) { - final int length = attributes.getLength(); - String sheetId = null; - String rid = null; - String name = null; - for (int i = 0; i < length; i++) { - final String attrName = attributes.getQName(i); - switch (attrName) { - case SHEET_ID_ATTR: - sheetId = attributes.getValue(i); - break; - case RID_ATTR: - rid = attributes.getValue(i); - break; - case NAME_ATTR: - name = attributes.getValue(i); - break; - } - if (StrUtil.isNotEmpty(sheetId)) { - ID_RID_MAP.put(sheetId, rid); - } - if (StrUtil.isNotEmpty(name)) { - NAME_RID_MAP.put(name, rid); - } + final String ridStr = attributes.getValue(SHEET_ID_ATTR); + if(StrUtil.isEmpty(ridStr)){ + return; + } + final int rid = Integer.parseInt(StrUtil.removePrefixIgnoreCase(ridStr, Excel07SaxReader.RID_PREFIX)); + + // sheet名和rid映射 + final String name = attributes.getValue(NAME_ATTR); + if (StrUtil.isNotEmpty(name)) { + NAME_RID_MAP.put(name, rid); + } + + // sheetId和rid映射 + final String sheetIdStr = attributes.getValue(SHEET_ID_ATTR); + if(StrUtil.isNotEmpty(sheetIdStr)){ + ID_RID_MAP.put(Integer.parseInt(sheetIdStr), rid); } } } diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java index 785eb2899..337b7a9c7 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java @@ -58,6 +58,11 @@ public class ExcelSaxReadTest { @Test public void readBySaxTest() { + ExcelUtil.readBySax("blankAndDateTest.xlsx", "0", createRowHandler()); + } + + @Test + public void readBySaxByRidTest() { ExcelUtil.readBySax("blankAndDateTest.xlsx", 0, createRowHandler()); } From dc440b2cc756a65380e4dd10889fbaa5dab03321 Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 27 Dec 2020 05:15:07 +0800 Subject: [PATCH 09/54] add read by name support --- CHANGELOG.md | 1 + .../poi/excel/sax/Excel03SaxReader.java | 30 ++++++++- .../poi/excel/sax/Excel07SaxReader.java | 61 +++++++++++-------- .../hutool/poi/excel/sax/ExcelSaxReader.java | 3 + .../cn/hutool/poi/excel/ExcelSaxReadTest.java | 5 ++ 5 files changed, 72 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 532ada354..4703ea1d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * 【poi 】 增加ExcelDateUtil更多日期格式支持(issue#1316@Github) * 【core 】 NumberUtil.toBigDecimal支持各类数字格式,如1,234.56等(issue#1334@Github) * 【core 】 NumberUtil增加parseXXX方法(issue#1334@Github) +* 【poi 】 Excel07SaxReader支持通过sheetName读取(issue#I2AOSE@Gitee) ### Bug修复 * 【core 】 FileUtil.isSub相对路径判断问题(pr#1315@Github) diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java index e64b43d3f..38e4600eb 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java @@ -1,6 +1,7 @@ package cn.hutool.poi.excel.sax; import cn.hutool.core.io.IoUtil; +import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.poi.excel.sax.handler.RowHandler; @@ -121,7 +122,7 @@ public class Excel03SaxReader implements HSSFListener, ExcelSaxReader + *

  • 传入'rId'开头,直接去除rId前缀
  • + *
  • 传入纯数字,表示sheetIndex,直接转换为rid
  • + * + * + * @param idOrRidOrSheetName Excel中的sheet id或者rid编号或sheet名称,从0开始,rid必须加rId前缀,例如rId0,如果为-1处理所有编号的sheet + * @return sheet索引,从0开始 + * @since 5.5.5 + */ + private int getSheetIndex(String idOrRidOrSheetName) { + Assert.notBlank(idOrRidOrSheetName, "id or rid or sheetName must be not blank!"); + + // rid直接处理 + if (StrUtil.startWithIgnoreCase(idOrRidOrSheetName, RID_PREFIX)) { + return Integer.parseInt(StrUtil.removePrefixIgnoreCase(idOrRidOrSheetName, RID_PREFIX)); + } + + final int sheetIndex; + try { + return Integer.parseInt(idOrRidOrSheetName); + } catch (NumberFormatException ignore) { + throw new IllegalArgumentException("Invalid sheet id: " + idOrRidOrSheetName); + } + } // ---------------------------------------------------------------------------------------------- Private method end } 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 e764074de..1c8c60093 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 @@ -24,8 +24,6 @@ import java.util.Iterator; */ public class Excel07SaxReader implements ExcelSaxReader { - // sheet r:Id前缀 - public static final String RID_PREFIX = "rId"; private final SheetDataSaxHandler handler; /** @@ -55,9 +53,9 @@ public class Excel07SaxReader implements ExcelSaxReader { } @Override - public Excel07SaxReader read(File file, String idOrRid) throws POIException { + public Excel07SaxReader read(File file, String idOrRidOrSheetName) throws POIException { try { - return read(OPCPackage.open(file), idOrRid); + return read(OPCPackage.open(file), idOrRidOrSheetName); } catch (InvalidFormatException e) { throw new POIException(e); } @@ -69,9 +67,9 @@ public class Excel07SaxReader implements ExcelSaxReader { } @Override - public Excel07SaxReader read(InputStream in, String idOrRid) throws POIException { + public Excel07SaxReader read(InputStream in, String idOrRidOrSheetName) throws POIException { try (final OPCPackage opcPackage = OPCPackage.open(in)) { - return read(opcPackage, idOrRid); + return read(opcPackage, idOrRidOrSheetName); } catch (IOException e) { throw new IORuntimeException(e); } catch (InvalidFormatException e) { @@ -95,13 +93,13 @@ public class Excel07SaxReader implements ExcelSaxReader { * 开始读取Excel,Sheet编号从0开始计数 * * @param opcPackage {@link OPCPackage},Excel包,读取后不关闭 - * @param idOrRid Excel中的sheet id或者rid编号,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet + * @param idOrRidOrSheetName Excel中的sheet id或者rid编号或sheet名,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet * @return this * @throws POIException POI异常 */ - public Excel07SaxReader read(OPCPackage opcPackage, String idOrRid) throws POIException { + public Excel07SaxReader read(OPCPackage opcPackage, String idOrRidOrSheetName) throws POIException { try { - return read(new XSSFReader(opcPackage), idOrRid); + return read(new XSSFReader(opcPackage), idOrRidOrSheetName); } catch (OpenXML4JException e) { throw new POIException(e); } catch (IOException e) { @@ -113,12 +111,12 @@ public class Excel07SaxReader implements ExcelSaxReader { * 开始读取Excel,Sheet编号从0开始计数 * * @param xssfReader {@link XSSFReader},Excel读取器 - * @param idOrRid Excel中的sheet id或者rid编号,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet + * @param idOrRidOrSheetName Excel中的sheet id或者rid编号或sheet名,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet * @return this * @throws POIException POI异常 * @since 5.4.4 */ - public Excel07SaxReader read(XSSFReader xssfReader, String idOrRid) throws POIException { + public Excel07SaxReader read(XSSFReader xssfReader, String idOrRidOrSheetName) throws POIException { // 获取共享样式表,样式非必须 try { this.handler.stylesTable = xssfReader.getStylesTable(); @@ -135,7 +133,7 @@ public class Excel07SaxReader implements ExcelSaxReader { throw new POIException(e); } - return readSheets(xssfReader, idOrRid); + return readSheets(xssfReader, idOrRidOrSheetName); } // ------------------------------------------------------------------------------ Read end @@ -144,14 +142,14 @@ public class Excel07SaxReader implements ExcelSaxReader { /** * 开始读取Excel,Sheet编号从0开始计数 * - * @param xssfReader {@link XSSFReader},Excel读取器 - * @param idOrRid Excel中的sheet id或者rid编号,从0开始,rid必须加rId前缀,例如rId0,如果为-1处理所有编号的sheet + * @param xssfReader {@link XSSFReader},Excel读取器 + * @param idOrRidOrSheetName Excel中的sheet id或者rid编号或sheet名,从0开始,rid必须加rId前缀,例如rId0,如果为-1处理所有编号的sheet * @return this * @throws POIException POI异常 * @since 5.4.4 */ - private Excel07SaxReader readSheets(XSSFReader xssfReader, String idOrRid) throws POIException { - this.handler.sheetIndex = getSheetIndex(xssfReader, idOrRid); + private Excel07SaxReader readSheets(XSSFReader xssfReader, String idOrRidOrSheetName) throws POIException { + this.handler.sheetIndex = getSheetIndex(xssfReader, idOrRidOrSheetName); InputStream sheetInputStream = null; try { if (this.handler.sheetIndex > -1) { @@ -187,29 +185,38 @@ public class Excel07SaxReader implements ExcelSaxReader { *
      *
    • 传入'rId'开头,直接去除rId前缀
    • *
    • 传入纯数字,表示sheetIndex,通过{@link SheetRidReader}转换为rId
    • + *
    • 传入其它字符串,表示sheetName,通过{@link SheetRidReader}转换为rId
    • *
    * - * @param xssfReader {@link XSSFReader},Excel读取器 - * @param idOrRid Excel中的sheet id或者rid编号,从0开始,rid必须加rId前缀,例如rId0,如果为-1处理所有编号的sheet + * @param xssfReader {@link XSSFReader},Excel读取器 + * @param idOrRidOrSheetName Excel中的sheet id或者rid编号或sheet名称,从0开始,rid必须加rId前缀,例如rId0,如果为-1处理所有编号的sheet * @return sheet索引,从0开始 * @since 5.5.5 */ - private int getSheetIndex(XSSFReader xssfReader, String idOrRid){ + private int getSheetIndex(XSSFReader xssfReader, String idOrRidOrSheetName) { // rid直接处理 - if(StrUtil.startWithIgnoreCase(idOrRid, RID_PREFIX)){ - return Integer.parseInt(StrUtil.removePrefixIgnoreCase(idOrRid, RID_PREFIX)); + if (StrUtil.startWithIgnoreCase(idOrRidOrSheetName, RID_PREFIX)) { + return Integer.parseInt(StrUtil.removePrefixIgnoreCase(idOrRidOrSheetName, RID_PREFIX)); } // sheetIndex需转换为rid - final int sheetIndex = Integer.parseInt(idOrRid); - final SheetRidReader ridReader = new SheetRidReader(); - final Integer rid = ridReader.read(xssfReader).getRidBySheetIdBase0(sheetIndex); + final SheetRidReader ridReader = new SheetRidReader().read(xssfReader); - if(null != rid){ - return rid; + final int sheetIndex; + Integer rid; + try { + sheetIndex = Integer.parseInt(idOrRidOrSheetName); + rid = ridReader.getRidBySheetIdBase0(sheetIndex); + return (null != rid) ? rid : sheetIndex; + } catch (NumberFormatException ignore) { + // 非数字,可能为sheet名称 + rid = ridReader.getRidByNameBase0(idOrRidOrSheetName); + if (null != rid) { + return rid; + } } - return sheetIndex; + throw new IllegalArgumentException("Invalid rId or id or sheetName: " + idOrRidOrSheetName); } // --------------------------------------------------------------------------------------- Private method end } \ No newline at end of file diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxReader.java index c6369fa24..da97140e9 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxReader.java @@ -15,6 +15,9 @@ import java.io.InputStream; */ public interface ExcelSaxReader { + // sheet r:Id前缀 + String RID_PREFIX = "rId"; + /** * 开始读取Excel * diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java index 337b7a9c7..8ac66a995 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java @@ -66,6 +66,11 @@ public class ExcelSaxReadTest { ExcelUtil.readBySax("blankAndDateTest.xlsx", 0, createRowHandler()); } + @Test + public void readBySaxByNameTest() { + ExcelUtil.readBySax("blankAndDateTest.xlsx", "Sheet1", createRowHandler()); + } + @Test @Ignore public void readBySaxTest2() { From 22c16f0ddd914e2945da7e33d4f6821d76023f4c Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 27 Dec 2020 05:27:36 +0800 Subject: [PATCH 10/54] fix #1336 --- CHANGELOG.md | 1 + hutool-core/pom.xml | 8 -------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4703ea1d0..306661a7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ * 【core 】 修复RuntimeUtil.getUsableMemory非static问题(issue#I2AQ2M@Gitee) * 【core 】 修复ArrayUtil.equals方法严格判断问题(issue#I2AO8B@Gitee) * 【poi 】 修复SheetRidReader在获取rid时读取错误问题(issue#I2AOQW@Gitee) +* 【core 】 修复强依赖了POI的问题(issue#1336@Github) ------------------------------------------------------------------------------------------------------------- # 5.5.4 (2020-12-16) diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index 52cc2738e..d12458b15 100644 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -5,14 +5,6 @@ 4.0.0 jar - - - org.apache.poi - poi - 4.1.2 - compile - - cn.hutool From 389d0464bc3709d784e9257b43196595492983cb Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 27 Dec 2020 05:33:12 +0800 Subject: [PATCH 11/54] fix comment --- hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java b/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java index 51a875f35..124fc2068 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java @@ -81,7 +81,7 @@ public class Mail { * 创建邮件客户端 * * @param mailAccount 邮件帐号 - * @return {@link Mail} + * @return Mail */ public static Mail create(MailAccount mailAccount) { return new Mail(mailAccount); @@ -90,7 +90,7 @@ public class Mail { /** * 创建邮件客户端,使用全局邮件帐户 * - * @return {@link Mail} + * @return Mail */ public static Mail create() { return new Mail(); From c219ee54b92077eaf4e9835f2456c0af1a624ac0 Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 28 Dec 2020 09:30:56 +0800 Subject: [PATCH 12/54] update dependency --- hutool-db/pom.xml | 6 +++--- hutool-extra/pom.xml | 8 ++++---- hutool-log/pom.xml | 2 +- hutool-script/pom.xml | 2 +- hutool-system/pom.xml | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index 2ebca13ec..08e216abe 100644 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -21,12 +21,12 @@ 0.9.5.5 2.8.0 9.0.30 - 1.2.3 + 1.2.4 2.4.13 3.12.7 - 3.32.3.2 + 3.34.0 2.5.1 - 3.3.0 + 3.4.1 diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index e1f6d2b76..ca36b48b2 100644 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -23,14 +23,14 @@ 1.3.0 2.3.30 4.9.03 - 3.0.11.RELEASE + 3.0.12.RELEASE 1.6.2 0.1.55 3.4.1 3.7.2 5.1.1 4.0.1 - 2.4.0 + 2.4.1 3.3.0 @@ -406,7 +406,7 @@ org.mvel mvel2 - 2.4.10.Final + 2.4.11.Final compile true @@ -420,7 +420,7 @@ org.springframework spring-expression - 5.3.1 + 5.3.2 compile true diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index d5153741a..ab674bc73 100644 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -92,7 +92,7 @@ org.tinylog tinylog-impl - 2.1.2 + 2.2.0 test diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml index 5359097d7..0a1920f94 100644 --- a/hutool-script/pom.xml +++ b/hutool-script/pom.xml @@ -18,7 +18,7 @@ 2.7.2 3.0.1 - 3.0.6 + 3.0.7 diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml index 05d842820..556b61899 100644 --- a/hutool-system/pom.xml +++ b/hutool-system/pom.xml @@ -26,7 +26,7 @@ com.github.oshi oshi-core - 5.3.6 + 5.3.7 provided From 3b4289a36b0e44b7abce19e61145cb6c332f8239 Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 28 Dec 2020 09:33:56 +0800 Subject: [PATCH 13/54] release 5.5.5 --- 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-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 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index 0020eaf2b..9d55c5313 100644 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-all diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml index baf95f5c1..660b76fb8 100644 --- a/hutool-aop/pom.xml +++ b/hutool-aop/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-aop diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml index dd38d715e..4781d5462 100644 --- a/hutool-bloomFilter/pom.xml +++ b/hutool-bloomFilter/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-bloomFilter diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml index c71df6274..48f6ab0c5 100644 --- a/hutool-bom/pom.xml +++ b/hutool-bom/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-bom diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml index e6c93cea1..999d811c8 100644 --- a/hutool-cache/pom.xml +++ b/hutool-cache/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-cache diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml index f9e94afae..7eb0a03f2 100644 --- a/hutool-captcha/pom.xml +++ b/hutool-captcha/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-captcha diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index d12458b15..38c9adefc 100644 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-core diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml index 539789bbc..8cc3acdb4 100644 --- a/hutool-cron/pom.xml +++ b/hutool-cron/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-cron diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml index f33710ee2..4b94e5c61 100644 --- a/hutool-crypto/pom.xml +++ b/hutool-crypto/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-crypto diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index 08e216abe..7c6db64f1 100644 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-db diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml index dd937c6c0..8355567b9 100644 --- a/hutool-dfa/pom.xml +++ b/hutool-dfa/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-dfa diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index ca36b48b2..600ad2bd6 100644 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-extra diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index aa24333da..86ad23761 100644 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-http diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index 58b7cc493..03f1f8a2b 100644 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-json diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index ab674bc73..c72232813 100644 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-log diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index 603b19a6b..86e4d5225 100644 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-poi diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml index 0a1920f94..3e08508e3 100644 --- a/hutool-script/pom.xml +++ b/hutool-script/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-script diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml index d7f4bd618..525d898ef 100644 --- a/hutool-setting/pom.xml +++ b/hutool-setting/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-setting diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml index 1c62791de..4d116860d 100644 --- a/hutool-socket/pom.xml +++ b/hutool-socket/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-socket diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml index 556b61899..d9fb303d3 100644 --- a/hutool-system/pom.xml +++ b/hutool-system/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool-system diff --git a/pom.xml b/pom.xml index fae0ac9b2..3adc36402 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.5-SNAPSHOT + 5.5.5 hutool Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。 https://github.com/looly/hutool From cda1467adf59c999a3831f6a5eb6dce8aa6da50b Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 28 Dec 2020 09:51:30 +0800 Subject: [PATCH 14/54] prepare 5.5.6 --- CHANGELOG.md | 8 ++++++++ README-EN.md | 8 ++++---- README.md | 8 ++++---- 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-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 +- 26 files changed, 39 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 306661a7b..f01403a48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,13 @@ ------------------------------------------------------------------------------------------------------------- +# 5.5.6 (2020-12-28) + +### 新特性 +### Bug修复 + +------------------------------------------------------------------------------------------------------------- + # 5.5.5 (2020-12-27) ### 新特性 @@ -26,6 +33,7 @@ * 【core 】 修复强依赖了POI的问题(issue#1336@Github) ------------------------------------------------------------------------------------------------------------- + # 5.5.4 (2020-12-16) ### 新特性 diff --git a/README-EN.md b/README-EN.md index d71319098..b1cf15e76 100644 --- a/README-EN.md +++ b/README-EN.md @@ -125,19 +125,19 @@ Each module can be introduced individually, or all modules can be introduced by cn.hutool hutool-all - 5.5.5 + 5.5.6 ``` ### Gradle ``` -compile 'cn.hutool:hutool-all:5.5.5' +compile 'cn.hutool:hutool-all:5.5.6' ``` ## Download -- [Maven1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.5/) -- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.5/) +- [Maven1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.6/) +- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.6/) > 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 6bbf71396..04edec2e5 100644 --- a/README.md +++ b/README.md @@ -123,21 +123,21 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不 cn.hutool hutool-all - 5.5.5 + 5.5.6 ``` ### Gradle ``` -compile 'cn.hutool:hutool-all:5.5.5' +compile 'cn.hutool:hutool-all:5.5.6' ``` ### 非Maven项目 点击以下任一链接,下载`hutool-all-X.X.X.jar`即可: -- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.5/) -- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.5/) +- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.6/) +- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.6/) > 注意 > Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。 diff --git a/bin/version.txt b/bin/version.txt index e69889c7f..8c448afe6 100755 --- a/bin/version.txt +++ b/bin/version.txt @@ -1 +1 @@ -5.5.5 +5.5.6 diff --git a/docs/js/version.js b/docs/js/version.js index bb06014fa..458ea3ed9 100644 --- a/docs/js/version.js +++ b/docs/js/version.js @@ -1 +1 @@ -var version = '5.5.5' \ No newline at end of file +var version = '5.5.6' \ No newline at end of file diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index 9d55c5313..c16dcd747 100644 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-all diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml index 660b76fb8..060fea685 100644 --- a/hutool-aop/pom.xml +++ b/hutool-aop/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-aop diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml index 4781d5462..aba3006e2 100644 --- a/hutool-bloomFilter/pom.xml +++ b/hutool-bloomFilter/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-bloomFilter diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml index 48f6ab0c5..50fcc725d 100644 --- a/hutool-bom/pom.xml +++ b/hutool-bom/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-bom diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml index 999d811c8..8dc292198 100644 --- a/hutool-cache/pom.xml +++ b/hutool-cache/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-cache diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml index 7eb0a03f2..c7f1f0dd7 100644 --- a/hutool-captcha/pom.xml +++ b/hutool-captcha/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-captcha diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index 38c9adefc..2d4ab74e7 100644 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-core diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml index 8cc3acdb4..470afc39f 100644 --- a/hutool-cron/pom.xml +++ b/hutool-cron/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-cron diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml index 4b94e5c61..2ac7b16c4 100644 --- a/hutool-crypto/pom.xml +++ b/hutool-crypto/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-crypto diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index 7c6db64f1..ae70efe4f 100644 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-db diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml index 8355567b9..0283149ea 100644 --- a/hutool-dfa/pom.xml +++ b/hutool-dfa/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-dfa diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index 600ad2bd6..124f14340 100644 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-extra diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index 86ad23761..e9dfaaaa8 100644 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-http diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index 03f1f8a2b..ffda773bc 100644 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-json diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index c72232813..e0045f1cb 100644 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-log diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index 86e4d5225..e67a3c9ed 100644 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-poi diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml index 3e08508e3..9dbc5b786 100644 --- a/hutool-script/pom.xml +++ b/hutool-script/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-script diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml index 525d898ef..4af4e12bd 100644 --- a/hutool-setting/pom.xml +++ b/hutool-setting/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-setting diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml index 4d116860d..3b0de273e 100644 --- a/hutool-socket/pom.xml +++ b/hutool-socket/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-socket diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml index d9fb303d3..d996cb109 100644 --- a/hutool-system/pom.xml +++ b/hutool-system/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool-system diff --git a/pom.xml b/pom.xml index 3adc36402..260532fe9 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.5 + 5.5.6-SNAPSHOT hutool Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。 https://github.com/looly/hutool From b9cd8a34d424a1148d9a9c19b41207ae3548fd39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=AD=E9=93=AE=E5=B7=A9?= Date: Mon, 28 Dec 2020 10:27:32 +0800 Subject: [PATCH 15/54] =?UTF-8?q?=E6=89=8B=E6=9C=BA=E5=8F=B7=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E7=B1=BB=20=E5=BA=A7=E6=9C=BA=20=E6=AD=A3=E5=88=99?= =?UTF-8?q?=E8=A1=A8=E8=BE=BE=E5=BC=8F=E7=BB=9F=E4=B8=80=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/cn/hutool/core/lang/PatternPool.java | 5 ++++- .../src/main/java/cn/hutool/core/util/PhoneUtil.java | 7 +------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/PatternPool.java b/hutool-core/src/main/java/cn/hutool/core/lang/PatternPool.java index f2261059f..044f54420 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/PatternPool.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/PatternPool.java @@ -56,7 +56,10 @@ public class PatternPool { * 移动电话 */ public final static Pattern MOBILE = Pattern.compile("(?:0|86|\\+86)?1[3-9]\\d{9}"); - + /** + * 座机号码 + */ + public final static Pattern TEL = Pattern.compile("0\\d{2,3}-[1-9]\\d{6,7}"); /** * 18位身份证号码 */ diff --git a/hutool-core/src/main/java/cn/hutool/core/util/PhoneUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/PhoneUtil.java index 402255992..5762eb452 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/PhoneUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/PhoneUtil.java @@ -14,11 +14,6 @@ import java.util.regex.Pattern; */ public class PhoneUtil { - /** - * 座机号码 - */ - private static final Pattern TEL = Pattern.compile("0\\d{2,3}-[1-9]\\d{6,7}"); - /** * 验证是否为手机号码(中国) * @@ -38,7 +33,7 @@ public class PhoneUtil { * @since 5.3.11 */ public static boolean isTel(CharSequence value) { - return Validator.isMatchRegex(TEL, value); + return Validator.isMatchRegex(PatternPool.TEL, value); } /** From 82662f03a5fc3555555852436e169575e3e17963 Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 28 Dec 2020 10:31:14 +0800 Subject: [PATCH 16/54] enhance pr#243 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f01403a48..130481550 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ # 5.5.6 (2020-12-28) ### 新特性 +* 【core 】 手机号工具类 座机正则表达式统一管理(pr#243@Gitee) + ### Bug修复 ------------------------------------------------------------------------------------------------------------- From 7d25da459f9cb0aaa03621a342d5e87b5c935d52 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 29 Dec 2020 16:54:53 +0800 Subject: [PATCH 17/54] fix #I2B0S1 --- CHANGELOG.md | 3 ++- .../src/main/java/cn/hutool/core/io/FileUtil.java | 15 ++++++++++++++- .../main/java/cn/hutool/core/util/ZipUtil.java | 2 +- .../extra/compress/extractor/StreamExtractor.java | 2 +- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 130481550..304447f57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,13 @@ ------------------------------------------------------------------------------------------------------------- -# 5.5.6 (2020-12-28) +# 5.5.6 (2020-12-29) ### 新特性 * 【core 】 手机号工具类 座机正则表达式统一管理(pr#243@Gitee) ### Bug修复 +* 【core 】 修复ZipUtil.unzip从流解压关闭问题(issue#I2B0S1@Gitee) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java index d0b59ab37..b613959a0 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java @@ -2914,7 +2914,20 @@ public class FileUtil extends PathUtil { * @throws IORuntimeException IO异常 */ public static File writeFromStream(InputStream in, File dest) throws IORuntimeException { - return FileWriter.create(dest).writeFromStream(in); + return writeFromStream(in, dest, true); + } + + /** + * 将流的内容写入文件 + * + * @param dest 目标文件 + * @param in 输入流 + * @return dest + * @throws IORuntimeException IO异常 + * @since 5.5.6 + */ + public static File writeFromStream(InputStream in, File dest, boolean isCloseIn) throws IORuntimeException { + return FileWriter.create(dest).writeFromStream(in, isCloseIn); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ZipUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ZipUtil.java index ea01d0763..88d02b4ed 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/ZipUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ZipUtil.java @@ -644,7 +644,7 @@ public class ZipUtil { outItemFile.mkdirs(); } else { // 文件 - FileUtil.writeFromStream(zipStream, outItemFile); + FileUtil.writeFromStream(zipStream, outItemFile, false); } }); return outFile; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/compress/extractor/StreamExtractor.java b/hutool-extra/src/main/java/cn/hutool/extra/compress/extractor/StreamExtractor.java index 69e198c5b..040dcd5a5 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/compress/extractor/StreamExtractor.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/compress/extractor/StreamExtractor.java @@ -119,7 +119,7 @@ public class StreamExtractor implements Extractor{ //noinspection ResultOfMethodCallIgnored outItemFile.mkdirs(); } else { - FileUtil.writeFromStream(in, outItemFile); + FileUtil.writeFromStream(in, outItemFile, false); } } } From 0c0f06f83239d70a142445df19d6d678540515c8 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 29 Dec 2020 18:59:12 +0800 Subject: [PATCH 18/54] fix #I2B57B --- .../java/cn/hutool/poi/word/TableUtil.java | 33 ++++++++++++----- .../cn/hutool/poi/word/WordWriterTest.java | 35 ++++++++++++++++++- 2 files changed, 59 insertions(+), 9 deletions(-) diff --git a/hutool-poi/src/main/java/cn/hutool/poi/word/TableUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/word/TableUtil.java index 4a700a086..9b580a711 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/word/TableUtil.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/word/TableUtil.java @@ -5,6 +5,7 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.IterUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.Console; import cn.hutool.core.map.MapUtil; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFTable; @@ -33,7 +34,7 @@ public class TableUtil { } /** - * 创建表格并填充数据 + * 创建表格并填充数据,默认表格 * * @param doc {@link XWPFDocument} * @param data 数据 @@ -41,19 +42,35 @@ public class TableUtil { */ public static XWPFTable createTable(XWPFDocument doc, Iterable data) { Assert.notNull(doc, "XWPFDocument must be not null !"); - XWPFTable table = doc.createTable(); + final XWPFTable table = doc.createTable(); + // 新建table的时候默认会新建一行,此处移除之 + table.removeRow(0); + return writeTable(table, data); + } + /** + * 为table填充数据 + * + * @param table {@link XWPFTable} + * @param data 数据 + * @return {@link XWPFTable} + * @since 5.5.6 + */ + public static XWPFTable writeTable(XWPFTable table, Iterable data){ + Assert.notNull(table, "XWPFTable must be not null !"); if (IterUtil.isEmpty(data)) { // 数据为空,返回空表 return table; } - - int index = 0; + + boolean isFirst = true; for (Object rowData : data) { - writeRow(getOrCreateRow(table, index), rowData, true); - index ++; + writeRow(table.createRow(), rowData, isFirst); + if(isFirst){ + isFirst = false; + } } - + return table; } @@ -81,7 +98,7 @@ public class TableUtil { writeRow(row, CollUtil.newArrayList(rowBean), isWriteKeyAsHead); return; } - + writeRow(row, rowMap, isWriteKeyAsHead); } diff --git a/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java b/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java index 22effb9a8..093682484 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java @@ -1,14 +1,15 @@ package cn.hutool.poi.word; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.lang.Console; -import cn.hutool.poi.word.Word07Writer; import org.junit.Ignore; import org.junit.Test; import java.awt.Font; import java.io.File; +import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.Map; @@ -49,4 +50,36 @@ public class WordWriterTest { writer.addTable(CollUtil.newArrayList(map)); writer.flush(FileUtil.file("d:/test/test.docx")); } + + @Test + @Ignore + public void writeMapAsTableTest() { + Word07Writer writer = new Word07Writer(); + + Map data = new LinkedHashMap<>(); + data.put("姓名", "张三"); + data.put("年龄", 23); + data.put("成绩", 80.5); + data.put("是否合格", true); + data.put("考试日期", DateUtil.date()); + + Map data2 = new LinkedHashMap<>(); + data2.put("姓名", "李四"); + data2.put("年龄", 4); + data2.put("成绩", 59); + data2.put("是否合格", false); + data2.put("考试日期", DateUtil.date()); + + ArrayList> mapArrayList = CollUtil.newArrayList(data, data2); + + // 添加段落(标题) + writer.addText(new Font("方正小标宋简体", Font.PLAIN, 22), "我是第一部分"); + // 添加段落(正文) + writer.addText(new Font("宋体", Font.PLAIN, 13), "我是正文第一部分"); + writer.addTable(mapArrayList); + // 写出到文件 + writer.flush(FileUtil.file("d:/test/a.docx")); + // 关闭 + writer.close(); + } } From 33fbc9288ed38e0c4fa02e2180a3b62035568569 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 29 Dec 2020 19:00:06 +0800 Subject: [PATCH 19/54] fix #I2B57B --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 304447f57..081f126fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ ### Bug修复 * 【core 】 修复ZipUtil.unzip从流解压关闭问题(issue#I2B0S1@Gitee) +* 【core 】 修复Excel07Writer写出表格错乱问题(issue#I2B57B@Gitee) ------------------------------------------------------------------------------------------------------------- From 99934e2b9f7661b953a3d7f84a0553a26ea875c1 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 29 Dec 2020 19:08:52 +0800 Subject: [PATCH 20/54] fix bug #1342 --- CHANGELOG.md | 3 ++- .../src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 081f126fc..56beb0da4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,8 @@ ### Bug修复 * 【core 】 修复ZipUtil.unzip从流解压关闭问题(issue#I2B0S1@Gitee) -* 【core 】 修复Excel07Writer写出表格错乱问题(issue#I2B57B@Gitee) +* 【poi 】 修复Excel07Writer写出表格错乱问题(issue#I2B57B@Gitee) +* 【poi 】 修复SheetRidReader读取字段错误问题(issue#1342@Github) ------------------------------------------------------------------------------------------------------------- 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 56c744ec9..65d697be5 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 @@ -113,7 +113,7 @@ public class SheetRidReader extends DefaultHandler { @Override public void startElement(String uri, String localName, String qName, Attributes attributes) { if (TAG_NAME.equalsIgnoreCase(localName)) { - final String ridStr = attributes.getValue(SHEET_ID_ATTR); + final String ridStr = attributes.getValue(RID_ATTR); if(StrUtil.isEmpty(ridStr)){ return; } From b8e5cc006ebe37ee74fc279ef32b5a77cc1fb7ae Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 29 Dec 2020 19:21:08 +0800 Subject: [PATCH 21/54] fix bug #1341 --- CHANGELOG.md | 1 + .../src/main/java/cn/hutool/core/io/FileUtil.java | 11 ++++++++++- .../src/test/java/cn/hutool/core/io/FileUtilTest.java | 6 ++++++ .../java/cn/hutool/http/server/action/RootAction.java | 2 -- .../cn/hutool/http/server/action/package-info.java | 6 ++++++ 5 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 hutool-http/src/main/java/cn/hutool/http/server/action/package-info.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 56beb0da4..c1af8055b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * 【core 】 修复ZipUtil.unzip从流解压关闭问题(issue#I2B0S1@Gitee) * 【poi 】 修复Excel07Writer写出表格错乱问题(issue#I2B57B@Gitee) * 【poi 】 修复SheetRidReader读取字段错误问题(issue#1342@Github) +* 【core 】 修复FileUtil.getMimeType不支持css和js(issue#1341@Github) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java index b613959a0..7a1b423cd 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java @@ -3182,7 +3182,16 @@ public class FileUtil extends PathUtil { * @since 4.1.15 */ public static String getMimeType(String filePath) { - return URLConnection.getFileNameMap().getContentTypeFor(filePath); + String contentType = URLConnection.getFileNameMap().getContentTypeFor(filePath); + if(null == contentType){ + // 补充一些常用的mimeType + if(filePath.endsWith(".css")){ + contentType = "text/css"; + } else if(filePath.endsWith(".js")){ + contentType = "application/x-javascript"; + } + } + return contentType; } /** diff --git a/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java index 2980d0890..68c0a955c 100644 --- a/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java @@ -376,6 +376,12 @@ public class FileUtilTest { public void getMimeTypeTest() { String mimeType = FileUtil.getMimeType("test2Write.jpg"); Assert.assertEquals("image/jpeg", mimeType); + + mimeType = FileUtil.getMimeType("main.css"); + Assert.assertEquals("text/css", mimeType); + + mimeType = FileUtil.getMimeType("test.js"); + Assert.assertEquals("application/x-javascript", mimeType); } @Test diff --git a/hutool-http/src/main/java/cn/hutool/http/server/action/RootAction.java b/hutool-http/src/main/java/cn/hutool/http/server/action/RootAction.java index 6b0ea3c64..e0047617b 100644 --- a/hutool-http/src/main/java/cn/hutool/http/server/action/RootAction.java +++ b/hutool-http/src/main/java/cn/hutool/http/server/action/RootAction.java @@ -2,7 +2,6 @@ package cn.hutool.http.server.action; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.FileUtil; -import cn.hutool.core.lang.Console; import cn.hutool.http.server.HttpServerRequest; import cn.hutool.http.server.HttpServerResponse; @@ -80,7 +79,6 @@ public class RootAction implements Action { } } - Console.log(file.getAbsolutePath()); response.send404("404 Not Found !"); } } diff --git a/hutool-http/src/main/java/cn/hutool/http/server/action/package-info.java b/hutool-http/src/main/java/cn/hutool/http/server/action/package-info.java new file mode 100644 index 000000000..122487572 --- /dev/null +++ b/hutool-http/src/main/java/cn/hutool/http/server/action/package-info.java @@ -0,0 +1,6 @@ +/** + * {@link com.sun.net.httpserver.HttpServer} 封装 + * + * @author looly + */ +package cn.hutool.http.server.action; \ No newline at end of file From 648ba17107a793601766a1f062d080fd1a419a1b Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 29 Dec 2020 19:33:15 +0800 Subject: [PATCH 22/54] add method for #1335 --- CHANGELOG.md | 1 + .../main/java/cn/hutool/extra/mail/Mail.java | 26 ++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1af8055b..c9280d944 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### 新特性 * 【core 】 手机号工具类 座机正则表达式统一管理(pr#243@Gitee) +* 【extra 】 Mail增加setDebugOutput方法(issue#1335@Gitee) ### Bug修复 * 【core 】 修复ZipUtil.unzip从流解压关闭问题(issue#I2B0S1@Gitee) diff --git a/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java b/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java index 124fc2068..95137a7a9 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java @@ -25,6 +25,7 @@ import javax.mail.util.ByteArrayDataSource; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.io.PrintStream; import java.nio.charset.Charset; import java.util.Date; @@ -77,6 +78,11 @@ public class Mail { */ private boolean useGlobalSession = false; + /** + * debug输出位置,可以自定义debug日志 + */ + private PrintStream debugOutput; + /** * 创建邮件客户端 * @@ -345,6 +351,18 @@ public class Mail { this.useGlobalSession = isUseGlobalSession; return this; } + + /** + * 设置debug输出位置,可以自定义debug日志 + * + * @param debugOutput debug输出位置 + * @return this + * @since 5.5.6 + */ + public Mail setDebugOutput(PrintStream debugOutput) { + this.debugOutput = debugOutput; + return this; + } // --------------------------------------------------------------- Getters and Setters end /** @@ -453,8 +471,14 @@ public class Mail { authenticator = new UserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass()); } - return isSingleton ? Session.getDefaultInstance(mailAccount.getSmtpProps(), authenticator) // + final Session session = isSingleton ? Session.getDefaultInstance(mailAccount.getSmtpProps(), authenticator) // : Session.getInstance(mailAccount.getSmtpProps(), authenticator); + + if(null != this.debugOutput){ + session.setDebugOut(debugOutput); + } + + return session; } // --------------------------------------------------------------- Private method end } From ecfa245ad9b9bc1b573a6a3b33b31f0e9b27bf6e Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 29 Dec 2020 19:37:26 +0800 Subject: [PATCH 23/54] release 5.5.6 --- 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-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 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index c16dcd747..776ee6ab9 100644 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-all diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml index 060fea685..ffce1bd70 100644 --- a/hutool-aop/pom.xml +++ b/hutool-aop/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-aop diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml index aba3006e2..48aa59a3c 100644 --- a/hutool-bloomFilter/pom.xml +++ b/hutool-bloomFilter/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-bloomFilter diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml index 50fcc725d..8c5102e8f 100644 --- a/hutool-bom/pom.xml +++ b/hutool-bom/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-bom diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml index 8dc292198..3dcf356c8 100644 --- a/hutool-cache/pom.xml +++ b/hutool-cache/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-cache diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml index c7f1f0dd7..82768f414 100644 --- a/hutool-captcha/pom.xml +++ b/hutool-captcha/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-captcha diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index 2d4ab74e7..fb828f874 100644 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-core diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml index 470afc39f..63c1caed3 100644 --- a/hutool-cron/pom.xml +++ b/hutool-cron/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-cron diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml index 2ac7b16c4..b7102bc4f 100644 --- a/hutool-crypto/pom.xml +++ b/hutool-crypto/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-crypto diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index ae70efe4f..9acb009d8 100644 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-db diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml index 0283149ea..9ceee97b5 100644 --- a/hutool-dfa/pom.xml +++ b/hutool-dfa/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-dfa diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index 124f14340..60128f809 100644 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-extra diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index e9dfaaaa8..4eb11f0bd 100644 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-http diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index ffda773bc..43e790810 100644 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-json diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index e0045f1cb..7ed044c11 100644 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-log diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index e67a3c9ed..a752f4993 100644 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-poi diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml index 9dbc5b786..99b911e53 100644 --- a/hutool-script/pom.xml +++ b/hutool-script/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-script diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml index 4af4e12bd..ecf27ec46 100644 --- a/hutool-setting/pom.xml +++ b/hutool-setting/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-setting diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml index 3b0de273e..36a0832e0 100644 --- a/hutool-socket/pom.xml +++ b/hutool-socket/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-socket diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml index d996cb109..2fda8fdbc 100644 --- a/hutool-system/pom.xml +++ b/hutool-system/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool-system diff --git a/pom.xml b/pom.xml index 260532fe9..47a5c39d2 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.6-SNAPSHOT + 5.5.6 hutool Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。 https://github.com/looly/hutool From d2fc1e598b7678cd3bb605e91421c966d22ef640 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 29 Dec 2020 19:50:59 +0800 Subject: [PATCH 24/54] prepare 5.5.7 --- CHANGELOG.md | 7 +++++++ README-EN.md | 8 ++++---- README.md | 8 ++++---- 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-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 +- 26 files changed, 38 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9280d944..e75e2a5e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,13 @@ ------------------------------------------------------------------------------------------------------------- +# 5.5.7 (2020-12-29) + +### 新特性 +### Bug修复 + +------------------------------------------------------------------------------------------------------------- + # 5.5.6 (2020-12-29) ### 新特性 diff --git a/README-EN.md b/README-EN.md index b1cf15e76..4ef40661b 100644 --- a/README-EN.md +++ b/README-EN.md @@ -125,19 +125,19 @@ Each module can be introduced individually, or all modules can be introduced by cn.hutool hutool-all - 5.5.6 + 5.5.7 ``` ### Gradle ``` -compile 'cn.hutool:hutool-all:5.5.6' +compile 'cn.hutool:hutool-all:5.5.7' ``` ## Download -- [Maven1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.6/) -- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.6/) +- [Maven1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.7/) +- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.7/) > 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 04edec2e5..f078dfd69 100644 --- a/README.md +++ b/README.md @@ -123,21 +123,21 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不 cn.hutool hutool-all - 5.5.6 + 5.5.7 ``` ### Gradle ``` -compile 'cn.hutool:hutool-all:5.5.6' +compile 'cn.hutool:hutool-all:5.5.7' ``` ### 非Maven项目 点击以下任一链接,下载`hutool-all-X.X.X.jar`即可: -- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.6/) -- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.6/) +- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.7/) +- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.7/) > 注意 > Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。 diff --git a/bin/version.txt b/bin/version.txt index 8c448afe6..21f56a9f8 100755 --- a/bin/version.txt +++ b/bin/version.txt @@ -1 +1 @@ -5.5.6 +5.5.7 diff --git a/docs/js/version.js b/docs/js/version.js index 458ea3ed9..2c5f13683 100644 --- a/docs/js/version.js +++ b/docs/js/version.js @@ -1 +1 @@ -var version = '5.5.6' \ No newline at end of file +var version = '5.5.7' \ No newline at end of file diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index 776ee6ab9..3ad19382f 100644 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-all diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml index ffce1bd70..9f68f2b6a 100644 --- a/hutool-aop/pom.xml +++ b/hutool-aop/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-aop diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml index 48aa59a3c..8fee87a21 100644 --- a/hutool-bloomFilter/pom.xml +++ b/hutool-bloomFilter/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-bloomFilter diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml index 8c5102e8f..43c9394ee 100644 --- a/hutool-bom/pom.xml +++ b/hutool-bom/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-bom diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml index 3dcf356c8..a6c81ce00 100644 --- a/hutool-cache/pom.xml +++ b/hutool-cache/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-cache diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml index 82768f414..10a218809 100644 --- a/hutool-captcha/pom.xml +++ b/hutool-captcha/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-captcha diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index fb828f874..efb3e7407 100644 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-core diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml index 63c1caed3..fc99fb8dc 100644 --- a/hutool-cron/pom.xml +++ b/hutool-cron/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-cron diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml index b7102bc4f..a841bde57 100644 --- a/hutool-crypto/pom.xml +++ b/hutool-crypto/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-crypto diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index 9acb009d8..e8e571787 100644 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-db diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml index 9ceee97b5..85217487f 100644 --- a/hutool-dfa/pom.xml +++ b/hutool-dfa/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-dfa diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index 60128f809..386ce9c35 100644 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-extra diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index 4eb11f0bd..53c41383e 100644 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-http diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index 43e790810..fedc0ed94 100644 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-json diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index 7ed044c11..8f38ac5a2 100644 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-log diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index a752f4993..ac001f8bb 100644 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-poi diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml index 99b911e53..4ffe4451d 100644 --- a/hutool-script/pom.xml +++ b/hutool-script/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-script diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml index ecf27ec46..9459e5c6d 100644 --- a/hutool-setting/pom.xml +++ b/hutool-setting/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-setting diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml index 36a0832e0..4463355d9 100644 --- a/hutool-socket/pom.xml +++ b/hutool-socket/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-socket diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml index 2fda8fdbc..0d472abe8 100644 --- a/hutool-system/pom.xml +++ b/hutool-system/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool-system diff --git a/pom.xml b/pom.xml index 47a5c39d2..b267e6271 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.6 + 5.5.7-SNAPSHOT hutool Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。 https://github.com/looly/hutool From b612eecb338ae2301e9dc95832abe583f91ca548 Mon Sep 17 00:00:00 2001 From: JJZhang Date: Thu, 31 Dec 2020 21:15:26 +0800 Subject: [PATCH 25/54] =?UTF-8?q?=E5=8F=AF=E9=80=89=E5=8F=82=E6=95=B0?= =?UTF-8?q?=EF=BC=8C=E6=96=B9=E6=B3=95=E9=87=8D=E8=BD=BD=E4=BC=98=E5=85=88?= =?UTF-8?q?=E7=BA=A7=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/hutool/core/bean/DynaBean.java | 354 +++++++++--------- .../cn/hutool/core/bean/DynaBeanTest.java | 50 +++ 2 files changed, 237 insertions(+), 167 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/DynaBean.java b/hutool-core/src/main/java/cn/hutool/core/bean/DynaBean.java index bf8280288..d3ce089a9 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/DynaBean.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/DynaBean.java @@ -16,187 +16,207 @@ import java.util.Map; * @since 3.0.7 */ public class DynaBean extends CloneSupport implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private final Class beanClass; - private final Object bean; + private final Class beanClass; + private final Object bean; - /** - * 创建一个{@link DynaBean} - * - * @param bean 普通Bean - * @return {@link DynaBean} - */ - public static DynaBean create(Object bean) { - return new DynaBean(bean); - } + /** + * 创建一个{@link DynaBean} + * + * @param bean 普通Bean + * @return {@link DynaBean} + */ + public static DynaBean create(Object bean) { + return new DynaBean(bean); + } - /** - * 创建一个{@link DynaBean} - * - * @param beanClass Bean类 - * @param params 构造Bean所需要的参数 - * @return {@link DynaBean} - */ - public static DynaBean create(Class beanClass, Object... params) { - return new DynaBean(beanClass, params); - } + /** + * 创建一个{@link DynaBean} + * + * @param beanClass Bean类 + * @return {@link DynaBean} + */ + public static DynaBean create(Class beanClass) { + return new DynaBean(beanClass); + } - //------------------------------------------------------------------------ Constructor start - /** - * 构造 - * - * @param beanClass Bean类 - * @param params 构造Bean所需要的参数 - */ - public DynaBean(Class beanClass, Object... params) { - this(ReflectUtil.newInstance(beanClass, params)); - } + /** + * 创建一个{@link DynaBean} + * + * @param beanClass Bean类 + * @param params 构造Bean所需要的参数 + * @return {@link DynaBean} + */ + public static DynaBean create(Class beanClass, Object... params) { + return new DynaBean(beanClass, params); + } - /** - * 构造 - * - * @param bean 原始Bean - */ - public DynaBean(Object bean) { - Assert.notNull(bean); - if (bean instanceof DynaBean) { - bean = ((DynaBean) bean).getBean(); - } - this.bean = bean; - this.beanClass = ClassUtil.getClass(bean); - } - //------------------------------------------------------------------------ Constructor end + //------------------------------------------------------------------------ Constructor start - /** - * 获得字段对应值 - * - * @param 属性值类型 - * @param fieldName 字段名 - * @return 字段值 - * @throws BeanException 反射获取属性值或字段值导致的异常 - */ - @SuppressWarnings("unchecked") - public T get(String fieldName) throws BeanException { - if (Map.class.isAssignableFrom(beanClass)) { - return (T) ((Map) bean).get(fieldName); - } else { - final PropDesc prop = BeanUtil.getBeanDesc(beanClass).getProp(fieldName); - if(null == prop){ - throw new BeanException("No public field or get method for {}", fieldName); - } - return (T) prop.getValue(bean); - } - } + /** + * 构造 + * + * @param beanClass Bean类 + * @param params 构造Bean所需要的参数 + */ + public DynaBean(Class beanClass, Object... params) { + this(ReflectUtil.newInstance(beanClass, params)); + } - /** - * 检查是否有指定名称的bean属性 - * - * @param fieldName 字段名 - * @return 是否有bean属性 - * @since 5.4.2 - */ - public boolean containsProp(String fieldName){ - return null != BeanUtil.getBeanDesc(beanClass).getProp(fieldName); - } + /** + * 构造 + * + * @param beanClass Bean类 + */ + public DynaBean(Class beanClass) { + this(ReflectUtil.newInstance(beanClass)); + } - /** - * 获得字段对应值,获取异常返回{@code null} - * - * @param 属性值类型 - * @param fieldName 字段名 - * @return 字段值 - * @since 3.1.1 - */ - public T safeGet(String fieldName) { - try { - return get(fieldName); - } catch (Exception e) { - return null; - } - } + /** + * 构造 + * + * @param bean 原始Bean + */ + public DynaBean(Object bean) { + Assert.notNull(bean); + if (bean instanceof DynaBean) { + bean = ((DynaBean) bean).getBean(); + } + this.bean = bean; + this.beanClass = ClassUtil.getClass(bean); + } + //------------------------------------------------------------------------ Constructor end - /** - * 设置字段值 - * - * @param fieldName 字段名 - * @param value 字段值 - * @throws BeanException 反射获取属性值或字段值导致的异常 - */ - @SuppressWarnings({"unchecked", "rawtypes"}) - public void set(String fieldName, Object value) throws BeanException { - if (Map.class.isAssignableFrom(beanClass)) { - ((Map) bean).put(fieldName, value); - } else { - final PropDesc prop = BeanUtil.getBeanDesc(beanClass).getProp(fieldName); - if(null == prop){ - throw new BeanException("No public field or set method for {}", fieldName); - } - prop.setValue(bean, value); - } - } + /** + * 获得字段对应值 + * + * @param 属性值类型 + * @param fieldName 字段名 + * @return 字段值 + * @throws BeanException 反射获取属性值或字段值导致的异常 + */ + @SuppressWarnings("unchecked") + public T get(String fieldName) throws BeanException { + if (Map.class.isAssignableFrom(beanClass)) { + return (T) ((Map) bean).get(fieldName); + } else { + final PropDesc prop = BeanUtil.getBeanDesc(beanClass).getProp(fieldName); + if (null == prop) { + throw new BeanException("No public field or get method for {}", fieldName); + } + return (T) prop.getValue(bean); + } + } - /** - * 执行原始Bean中的方法 - * - * @param methodName 方法名 - * @param params 参数 - * @return 执行结果,可能为null - */ - public Object invoke(String methodName, Object... params) { - return ReflectUtil.invoke(this.bean, methodName, params); - } + /** + * 检查是否有指定名称的bean属性 + * + * @param fieldName 字段名 + * @return 是否有bean属性 + * @since 5.4.2 + */ + public boolean containsProp(String fieldName) { + return null != BeanUtil.getBeanDesc(beanClass).getProp(fieldName); + } - /** - * 获得原始Bean - * - * @param Bean类型 - * @return bean - */ - @SuppressWarnings("unchecked") - public T getBean() { - return (T) this.bean; - } + /** + * 获得字段对应值,获取异常返回{@code null} + * + * @param 属性值类型 + * @param fieldName 字段名 + * @return 字段值 + * @since 3.1.1 + */ + public T safeGet(String fieldName) { + try { + return get(fieldName); + } catch (Exception e) { + return null; + } + } - /** - * 获得Bean的类型 - * - * @param Bean类型 - * @return Bean类型 - */ - @SuppressWarnings("unchecked") - public Class getBeanClass() { - return (Class) this.beanClass; - } + /** + * 设置字段值 + * + * @param fieldName 字段名 + * @param value 字段值 + * @throws BeanException 反射获取属性值或字段值导致的异常 + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + public void set(String fieldName, Object value) throws BeanException { + if (Map.class.isAssignableFrom(beanClass)) { + ((Map) bean).put(fieldName, value); + } else { + final PropDesc prop = BeanUtil.getBeanDesc(beanClass).getProp(fieldName); + if (null == prop) { + throw new BeanException("No public field or set method for {}", fieldName); + } + prop.setValue(bean, value); + } + } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((bean == null) ? 0 : bean.hashCode()); - return result; - } + /** + * 执行原始Bean中的方法 + * + * @param methodName 方法名 + * @param params 参数 + * @return 执行结果,可能为null + */ + public Object invoke(String methodName, Object... params) { + return ReflectUtil.invoke(this.bean, methodName, params); + } - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final DynaBean other = (DynaBean) obj; - if (bean == null) { - return other.bean == null; - } else return bean.equals(other.bean); - } + /** + * 获得原始Bean + * + * @param Bean类型 + * @return bean + */ + @SuppressWarnings("unchecked") + public T getBean() { + return (T) this.bean; + } - @Override - public String toString() { - return this.bean.toString(); - } + /** + * 获得Bean的类型 + * + * @param Bean类型 + * @return Bean类型 + */ + @SuppressWarnings("unchecked") + public Class getBeanClass() { + return (Class) this.beanClass; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((bean == null) ? 0 : bean.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final DynaBean other = (DynaBean) obj; + if (bean == null) { + return other.bean == null; + } else return bean.equals(other.bean); + } + + @Override + public String toString() { + return this.bean.toString(); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/DynaBeanTest.java b/hutool-core/src/test/java/cn/hutool/core/bean/DynaBeanTest.java index de54d20c7..3a7617d58 100644 --- a/hutool-core/src/test/java/cn/hutool/core/bean/DynaBeanTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/bean/DynaBeanTest.java @@ -33,6 +33,56 @@ public class DynaBeanTest { Object invoke = bean2.invoke("testMethod"); Assert.assertEquals("test for 李华", invoke); } + + + @Test + public void bean_by_static_clazz_constructor_Test() { + String name_before = "李华"; + int age_before = 12; + DynaBean bean = DynaBean.create(User.class); + bean.set("name", name_before); + bean.set("age", age_before); + + String name_after = bean.get("name"); + Assert.assertEquals(name_before, name_after); + int age_after = bean.get("age"); + Assert.assertEquals(age_before, age_after); + + //重复包装测试 + DynaBean bean2 = new DynaBean(bean); + User user2 = bean2.getBean(); + User user1 = bean.getBean(); + Assert.assertEquals(user1, user2); + + //执行指定方法 + Object invoke = bean2.invoke("testMethod"); + Assert.assertEquals("test for 李华", invoke); + } + + + @Test + public void bean_by_instance_clazz_constructor_Test() { + String name_before = "李华"; + int age_before = 12; + DynaBean bean = new DynaBean(User.class); + bean.set("name", name_before); + bean.set("age", age_before); + + String name_after = bean.get("name"); + Assert.assertEquals(name_before, name_after); + int age_after = bean.get("age"); + Assert.assertEquals(age_before, age_after); + + //重复包装测试 + DynaBean bean2 = new DynaBean(bean); + User user2 = bean2.getBean(); + User user1 = bean.getBean(); + Assert.assertEquals(user1, user2); + + //执行指定方法 + Object invoke = bean2.invoke("testMethod"); + Assert.assertEquals("test for 李华", invoke); + } public static class User{ private String name; From 387845b869399df83bdd8da741cfd3cbfcb256ce Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 2 Jan 2021 10:27:52 +0800 Subject: [PATCH 26/54] pr#245 --- CHANGELOG.md | 4 +- .../java/cn/hutool/core/bean/DynaBean.java | 368 +++++++++--------- .../cn/hutool/core/bean/DynaBeanTest.java | 121 +++--- 3 files changed, 239 insertions(+), 254 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e75e2a5e7..d857c36b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,11 @@ ------------------------------------------------------------------------------------------------------------- -# 5.5.7 (2020-12-29) +# 5.5.7 (2021-01-02) ### 新特性 +* 【core 】 DynaBean.create增加重载方法(pr#245@Gitee) + ### Bug修复 ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/DynaBean.java b/hutool-core/src/main/java/cn/hutool/core/bean/DynaBean.java index d3ce089a9..558ce9cad 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/DynaBean.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/DynaBean.java @@ -16,207 +16,207 @@ import java.util.Map; * @since 3.0.7 */ public class DynaBean extends CloneSupport implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private final Class beanClass; - private final Object bean; + private final Class beanClass; + private final Object bean; - /** - * 创建一个{@link DynaBean} - * - * @param bean 普通Bean - * @return {@link DynaBean} - */ - public static DynaBean create(Object bean) { - return new DynaBean(bean); - } + /** + * 创建一个DynaBean + * + * @param bean 普通Bean + * @return DynaBean + */ + public static DynaBean create(Object bean) { + return new DynaBean(bean); + } - /** - * 创建一个{@link DynaBean} - * - * @param beanClass Bean类 - * @return {@link DynaBean} - */ - public static DynaBean create(Class beanClass) { - return new DynaBean(beanClass); - } + /** + * 创建一个DynaBean + * + * @param beanClass Bean类 + * @return DynaBean + */ + public static DynaBean create(Class beanClass) { + return new DynaBean(beanClass); + } - /** - * 创建一个{@link DynaBean} - * - * @param beanClass Bean类 - * @param params 构造Bean所需要的参数 - * @return {@link DynaBean} - */ - public static DynaBean create(Class beanClass, Object... params) { - return new DynaBean(beanClass, params); - } + /** + * 创建一个DynaBean + * + * @param beanClass Bean类 + * @param params 构造Bean所需要的参数 + * @return DynaBean + */ + public static DynaBean create(Class beanClass, Object... params) { + return new DynaBean(beanClass, params); + } - //------------------------------------------------------------------------ Constructor start + //------------------------------------------------------------------------ Constructor start - /** - * 构造 - * - * @param beanClass Bean类 - * @param params 构造Bean所需要的参数 - */ - public DynaBean(Class beanClass, Object... params) { - this(ReflectUtil.newInstance(beanClass, params)); - } + /** + * 构造 + * + * @param beanClass Bean类 + * @param params 构造Bean所需要的参数 + */ + public DynaBean(Class beanClass, Object... params) { + this(ReflectUtil.newInstance(beanClass, params)); + } - /** - * 构造 - * - * @param beanClass Bean类 - */ - public DynaBean(Class beanClass) { - this(ReflectUtil.newInstance(beanClass)); - } + /** + * 构造 + * + * @param beanClass Bean类 + */ + public DynaBean(Class beanClass) { + this(ReflectUtil.newInstance(beanClass)); + } - /** - * 构造 - * - * @param bean 原始Bean - */ - public DynaBean(Object bean) { - Assert.notNull(bean); - if (bean instanceof DynaBean) { - bean = ((DynaBean) bean).getBean(); - } - this.bean = bean; - this.beanClass = ClassUtil.getClass(bean); - } - //------------------------------------------------------------------------ Constructor end + /** + * 构造 + * + * @param bean 原始Bean + */ + public DynaBean(Object bean) { + Assert.notNull(bean); + if (bean instanceof DynaBean) { + bean = ((DynaBean) bean).getBean(); + } + this.bean = bean; + this.beanClass = ClassUtil.getClass(bean); + } + //------------------------------------------------------------------------ Constructor end - /** - * 获得字段对应值 - * - * @param 属性值类型 - * @param fieldName 字段名 - * @return 字段值 - * @throws BeanException 反射获取属性值或字段值导致的异常 - */ - @SuppressWarnings("unchecked") - public T get(String fieldName) throws BeanException { - if (Map.class.isAssignableFrom(beanClass)) { - return (T) ((Map) bean).get(fieldName); - } else { - final PropDesc prop = BeanUtil.getBeanDesc(beanClass).getProp(fieldName); - if (null == prop) { - throw new BeanException("No public field or get method for {}", fieldName); - } - return (T) prop.getValue(bean); - } - } + /** + * 获得字段对应值 + * + * @param 属性值类型 + * @param fieldName 字段名 + * @return 字段值 + * @throws BeanException 反射获取属性值或字段值导致的异常 + */ + @SuppressWarnings("unchecked") + public T get(String fieldName) throws BeanException { + if (Map.class.isAssignableFrom(beanClass)) { + return (T) ((Map) bean).get(fieldName); + } else { + final PropDesc prop = BeanUtil.getBeanDesc(beanClass).getProp(fieldName); + if (null == prop) { + throw new BeanException("No public field or get method for {}", fieldName); + } + return (T) prop.getValue(bean); + } + } - /** - * 检查是否有指定名称的bean属性 - * - * @param fieldName 字段名 - * @return 是否有bean属性 - * @since 5.4.2 - */ - public boolean containsProp(String fieldName) { - return null != BeanUtil.getBeanDesc(beanClass).getProp(fieldName); - } + /** + * 检查是否有指定名称的bean属性 + * + * @param fieldName 字段名 + * @return 是否有bean属性 + * @since 5.4.2 + */ + public boolean containsProp(String fieldName) { + return null != BeanUtil.getBeanDesc(beanClass).getProp(fieldName); + } - /** - * 获得字段对应值,获取异常返回{@code null} - * - * @param 属性值类型 - * @param fieldName 字段名 - * @return 字段值 - * @since 3.1.1 - */ - public T safeGet(String fieldName) { - try { - return get(fieldName); - } catch (Exception e) { - return null; - } - } + /** + * 获得字段对应值,获取异常返回{@code null} + * + * @param 属性值类型 + * @param fieldName 字段名 + * @return 字段值 + * @since 3.1.1 + */ + public T safeGet(String fieldName) { + try { + return get(fieldName); + } catch (Exception e) { + return null; + } + } - /** - * 设置字段值 - * - * @param fieldName 字段名 - * @param value 字段值 - * @throws BeanException 反射获取属性值或字段值导致的异常 - */ - @SuppressWarnings({"unchecked", "rawtypes"}) - public void set(String fieldName, Object value) throws BeanException { - if (Map.class.isAssignableFrom(beanClass)) { - ((Map) bean).put(fieldName, value); - } else { - final PropDesc prop = BeanUtil.getBeanDesc(beanClass).getProp(fieldName); - if (null == prop) { - throw new BeanException("No public field or set method for {}", fieldName); - } - prop.setValue(bean, value); - } - } + /** + * 设置字段值 + * + * @param fieldName 字段名 + * @param value 字段值 + * @throws BeanException 反射获取属性值或字段值导致的异常 + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + public void set(String fieldName, Object value) throws BeanException { + if (Map.class.isAssignableFrom(beanClass)) { + ((Map) bean).put(fieldName, value); + } else { + final PropDesc prop = BeanUtil.getBeanDesc(beanClass).getProp(fieldName); + if (null == prop) { + throw new BeanException("No public field or set method for {}", fieldName); + } + prop.setValue(bean, value); + } + } - /** - * 执行原始Bean中的方法 - * - * @param methodName 方法名 - * @param params 参数 - * @return 执行结果,可能为null - */ - public Object invoke(String methodName, Object... params) { - return ReflectUtil.invoke(this.bean, methodName, params); - } + /** + * 执行原始Bean中的方法 + * + * @param methodName 方法名 + * @param params 参数 + * @return 执行结果,可能为null + */ + public Object invoke(String methodName, Object... params) { + return ReflectUtil.invoke(this.bean, methodName, params); + } - /** - * 获得原始Bean - * - * @param Bean类型 - * @return bean - */ - @SuppressWarnings("unchecked") - public T getBean() { - return (T) this.bean; - } + /** + * 获得原始Bean + * + * @param Bean类型 + * @return bean + */ + @SuppressWarnings("unchecked") + public T getBean() { + return (T) this.bean; + } - /** - * 获得Bean的类型 - * - * @param Bean类型 - * @return Bean类型 - */ - @SuppressWarnings("unchecked") - public Class getBeanClass() { - return (Class) this.beanClass; - } + /** + * 获得Bean的类型 + * + * @param Bean类型 + * @return Bean类型 + */ + @SuppressWarnings("unchecked") + public Class getBeanClass() { + return (Class) this.beanClass; + } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((bean == null) ? 0 : bean.hashCode()); - return result; - } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((bean == null) ? 0 : bean.hashCode()); + return result; + } - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final DynaBean other = (DynaBean) obj; - if (bean == null) { - return other.bean == null; - } else return bean.equals(other.bean); - } + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final DynaBean other = (DynaBean) obj; + if (bean == null) { + return other.bean == null; + } else return bean.equals(other.bean); + } - @Override - public String toString() { - return this.bean.toString(); - } + @Override + public String toString() { + return this.bean.toString(); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/DynaBeanTest.java b/hutool-core/src/test/java/cn/hutool/core/bean/DynaBeanTest.java index 3a7617d58..2ff28ae30 100644 --- a/hutool-core/src/test/java/cn/hutool/core/bean/DynaBeanTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/bean/DynaBeanTest.java @@ -1,112 +1,95 @@ package cn.hutool.core.bean; +import lombok.Data; import org.junit.Assert; import org.junit.Test; -import cn.hutool.core.bean.DynaBean; - /** * {@link DynaBean}单元测试 - * @author Looly * + * @author Looly */ public class DynaBeanTest { - + @Test - public void beanTest(){ + public void beanTest() { User user = new User(); DynaBean bean = DynaBean.create(user); bean.set("name", "李华"); bean.set("age", 12); - + String name = bean.get("name"); Assert.assertEquals(user.getName(), name); int age = bean.get("age"); Assert.assertEquals(user.getAge(), age); - + //重复包装测试 DynaBean bean2 = new DynaBean(bean); User user2 = bean2.getBean(); Assert.assertEquals(user, user2); - + //执行指定方法 Object invoke = bean2.invoke("testMethod"); Assert.assertEquals("test for 李华", invoke); } - @Test - public void bean_by_static_clazz_constructor_Test() { - String name_before = "李华"; - int age_before = 12; - DynaBean bean = DynaBean.create(User.class); - bean.set("name", name_before); - bean.set("age", age_before); + @Test + public void beanByStaticClazzConstructorTest() { + String name_before = "李华"; + int age_before = 12; + DynaBean bean = DynaBean.create(User.class); + bean.set("name", name_before); + bean.set("age", age_before); - String name_after = bean.get("name"); - Assert.assertEquals(name_before, name_after); - int age_after = bean.get("age"); - Assert.assertEquals(age_before, age_after); + String name_after = bean.get("name"); + Assert.assertEquals(name_before, name_after); + int age_after = bean.get("age"); + Assert.assertEquals(age_before, age_after); - //重复包装测试 - DynaBean bean2 = new DynaBean(bean); - User user2 = bean2.getBean(); - User user1 = bean.getBean(); - Assert.assertEquals(user1, user2); + //重复包装测试 + DynaBean bean2 = new DynaBean(bean); + User user2 = bean2.getBean(); + User user1 = bean.getBean(); + Assert.assertEquals(user1, user2); - //执行指定方法 - Object invoke = bean2.invoke("testMethod"); - Assert.assertEquals("test for 李华", invoke); - } + //执行指定方法 + Object invoke = bean2.invoke("testMethod"); + Assert.assertEquals("test for 李华", invoke); + } - @Test - public void bean_by_instance_clazz_constructor_Test() { - String name_before = "李华"; - int age_before = 12; - DynaBean bean = new DynaBean(User.class); - bean.set("name", name_before); - bean.set("age", age_before); + @Test + public void beanByInstanceClazzConstructorTest() { + String name_before = "李华"; + int age_before = 12; + DynaBean bean = new DynaBean(User.class); + bean.set("name", name_before); + bean.set("age", age_before); - String name_after = bean.get("name"); - Assert.assertEquals(name_before, name_after); - int age_after = bean.get("age"); - Assert.assertEquals(age_before, age_after); + String name_after = bean.get("name"); + Assert.assertEquals(name_before, name_after); + int age_after = bean.get("age"); + Assert.assertEquals(age_before, age_after); - //重复包装测试 - DynaBean bean2 = new DynaBean(bean); - User user2 = bean2.getBean(); - User user1 = bean.getBean(); - Assert.assertEquals(user1, user2); + //重复包装测试 + DynaBean bean2 = new DynaBean(bean); + User user2 = bean2.getBean(); + User user1 = bean.getBean(); + Assert.assertEquals(user1, user2); - //执行指定方法 - Object invoke = bean2.invoke("testMethod"); - Assert.assertEquals("test for 李华", invoke); - } - - public static class User{ + //执行指定方法 + Object invoke = bean2.invoke("testMethod"); + Assert.assertEquals("test for 李华", invoke); + } + + @Data + public static class User { private String name; private int age; - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - public int getAge() { - return age; - } - public void setAge(int age) { - this.age = age; - } - - public String testMethod(){ + + public String testMethod() { return "test for " + this.name; } - - @Override - public String toString() { - return "User [name=" + name + ", age=" + age + "]"; - } } } From 6110a20f0a84e778d945c45fc5c9dd98370a9ee7 Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 2 Jan 2021 11:20:19 +0800 Subject: [PATCH 27/54] add method for #1348 --- CHANGELOG.md | 1 + .../java/cn/hutool/core/util/IdcardUtil.java | 50 ++++++++++++++++--- .../cn/hutool/core/util/IdcardUtilTest.java | 14 +++++- .../http/ssl/AndroidSupportSSLFactory.java | 15 +++--- .../java/cn/hutool/json/JSONArrayTest.java | 29 ++++------- 5 files changed, 76 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d857c36b4..ca0a194e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### 新特性 * 【core 】 DynaBean.create增加重载方法(pr#245@Gitee) +* 【core 】 IdcardUtil增加重载是否忽略大小写(issue#1348@Github) ### Bug修复 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 af9dc87de..e1bef751a 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 @@ -147,7 +147,7 @@ public class IdcardUtil { } /** - * 是否有效身份证号 + * 是否有效身份证号,忽略X的大小写 * * @param idCard 身份证号,支持18位、15位和港澳台的10位 * @return 是否有效 @@ -198,9 +198,46 @@ public class IdcardUtil { * * * @param idcard 待验证的身份证 - * @return 是否有效的18位身份证 + * @return 是否有效的18位身份证,忽略x的大小写 */ public static boolean isValidCard18(String idcard) { + return isValidCard18(idcard, true); + } + + /** + *

    + * 判断18位身份证的合法性 + *

    + * 根据〖中华人民共和国国家标准GB11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。
    + * 排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。 + *

    + * 顺序码: 表示在同一地址码所标识的区域范围内,对同年、同月、同 日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配 给女性。 + *

    + *
      + *
    1. 第1、2位数字表示:所在省份的代码
    2. + *
    3. 第3、4位数字表示:所在城市的代码
    4. + *
    5. 第5、6位数字表示:所在区县的代码
    6. + *
    7. 第7~14位数字表示:出生年、月、日
    8. + *
    9. 第15、16位数字表示:所在地的派出所的代码
    10. + *
    11. 第17位数字表示性别:奇数表示男性,偶数表示女性
    12. + *
    13. 第18位数字是校检码,用来检验身份证的正确性。校检码可以是0~9的数字,有时也用x表示
    14. + *
    + *

    + * 第十八位数字(校验码)的计算方法为: + *

      + *
    1. 将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
    2. + *
    3. 将这17位数字和系数相乘的结果相加
    4. + *
    5. 用加出来和除以11,看余数是多少
    6. + *
    7. 余数只可能有0 1 2 3 4 5 6 7 8 9 10这11个数字。其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2
    8. + *
    9. 通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2
    10. + *
    + * + * @param idcard 待验证的身份证 + * @param ignoreCase 是否忽略大小写。{@code true}则忽略X大小写,否则严格匹配大写。 + * @return 是否有效的18位身份证 + * @since 5.5.7 + */ + public static boolean isValidCard18(String idcard, boolean ignoreCase) { if (CHINA_ID_MAX_LENGTH != idcard.length()) { return false; } @@ -217,13 +254,12 @@ public class IdcardUtil { } // 前17位 - String code17 = idcard.substring(0, 17); - // 第18位 - char code18 = Character.toLowerCase(idcard.charAt(17)); + final String code17 = idcard.substring(0, 17); if (ReUtil.isMatch(PatternPool.NUMBERS, code17)) { // 获取校验位 char val = getCheckCode18(code17); - return val == code18; + // 第18位 + return CharUtil.equals(val, idcard.charAt(17), ignoreCase); } return false; } @@ -586,7 +622,7 @@ public class IdcardUtil { case 3: return '9'; case 2: - return 'x'; + return 'X'; case 1: return '0'; case 0: 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 c25a9fdf8..4e3a85610 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 @@ -89,8 +89,20 @@ public class IdcardUtilTest { @Test public void isValidCard18Test(){ - final boolean isValidCard18 = IdcardUtil.isValidCard18("3301022011022000D6"); + boolean isValidCard18 = IdcardUtil.isValidCard18("3301022011022000D6"); Assert.assertFalse(isValidCard18); + + // 不忽略大小写情况下,X严格校验必须大写 + isValidCard18 = IdcardUtil.isValidCard18("33010219200403064x", false); + Assert.assertFalse(isValidCard18); + isValidCard18 = IdcardUtil.isValidCard18("33010219200403064X", false); + Assert.assertTrue(isValidCard18); + + // 非严格校验下大小写皆可 + isValidCard18 = IdcardUtil.isValidCard18("33010219200403064x"); + Assert.assertTrue(isValidCard18); + isValidCard18 = IdcardUtil.isValidCard18("33010219200403064X"); + Assert.assertTrue(isValidCard18); } @Test diff --git a/hutool-http/src/main/java/cn/hutool/http/ssl/AndroidSupportSSLFactory.java b/hutool-http/src/main/java/cn/hutool/http/ssl/AndroidSupportSSLFactory.java index a7a8cd6d9..fae1ddfcb 100644 --- a/hutool-http/src/main/java/cn/hutool/http/ssl/AndroidSupportSSLFactory.java +++ b/hutool-http/src/main/java/cn/hutool/http/ssl/AndroidSupportSSLFactory.java @@ -1,26 +1,27 @@ package cn.hutool.http.ssl; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; + import static cn.hutool.http.ssl.SSLSocketFactoryBuilder.SSLv3; import static cn.hutool.http.ssl.SSLSocketFactoryBuilder.TLSv1; import static cn.hutool.http.ssl.SSLSocketFactoryBuilder.TLSv11; import static cn.hutool.http.ssl.SSLSocketFactoryBuilder.TLSv12; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; - /** - * 兼容android低版本SSL连接 - * 咱在测试HttpUrlConnection的时候 - * 发现一部分手机无法连接[GithubPage] + * 兼容android低版本SSL连接
    + * 在测试HttpUrlConnection的时候,发现一部分手机无法连接[GithubPage] * + *

    * 最后发现原来是某些SSL协议没有开启 + * * @author MikaGuraNTK */ public class AndroidSupportSSLFactory extends CustomProtocolsSSLFactory { // Android低版本不重置的话某些SSL访问就会失败 private static final String[] protocols = {SSLv3, TLSv1, TLSv11, TLSv12}; - + public AndroidSupportSSLFactory() throws KeyManagementException, NoSuchAlgorithmException { super(protocols); } diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONArrayTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONArrayTest.java index 5b42385e9..d4954a092 100644 --- a/hutool-json/src/test/java/cn/hutool/json/JSONArrayTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONArrayTest.java @@ -11,6 +11,7 @@ import cn.hutool.core.util.CharsetUtil; import cn.hutool.json.test.bean.Exam; import cn.hutool.json.test.bean.JsonNode; import cn.hutool.json.test.bean.KeyBean; +import lombok.Data; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -202,6 +203,14 @@ public class JSONArrayTest { Assert.assertEquals("-0", nodeList.get(3).getName()); } + @Test + public void getByPathTest(){ + String jsonStr = "[{\"id\": \"1\",\"name\": \"a\"},{\"id\": \"2\",\"name\": \"b\"}]"; + final JSONArray jsonArray = JSONUtil.parseArray(jsonStr); + Assert.assertEquals("b", jsonArray.getByPath("[1].name")); + Assert.assertEquals("b", JSONUtil.getByPath(jsonArray, "[1].name")); + } + private static Map buildMap(String id, String parentId, String name) { Map map = new HashMap<>(); map.put("id", id); @@ -209,26 +218,10 @@ public class JSONArrayTest { map.put("name", name); return map; } - + + @Data static class User { private Integer id; private String name; - - public Integer getId() { - return id; - } - public void setId(Integer id) { - this.id = id; - } - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - @Override - public String toString() { - return "User [id=" + id + ", name=" + name + "]"; - } } } From 71177864be08a6c21ca9a10abb3ae434113e7de4 Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 2 Jan 2021 11:36:14 +0800 Subject: [PATCH 28/54] add method for #1342 --- CHANGELOG.md | 1 + .../java/cn/hutool/poi/excel/ExcelBase.java | 8 ++-- .../java/cn/hutool/poi/excel/ExcelWriter.java | 2 +- .../hutool/poi/excel/sax/SheetRidReader.java | 41 +++++++++++++++---- 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca0a194e6..ff4b20fc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### 新特性 * 【core 】 DynaBean.create增加重载方法(pr#245@Gitee) * 【core 】 IdcardUtil增加重载是否忽略大小写(issue#1348@Github) +* 【poi 】 SheetRidReader增加getRidByIndex方法(issue#1342@Github) ### Bug修复 diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelBase.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelBase.java index c9d191ae8..90da8bd7d 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelBase.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelBase.java @@ -145,7 +145,7 @@ public class ExcelBase> implements Closeable { } /** - * 获取指定坐标单元格,单元格不存在时返回null + * 获取指定坐标单元格,单元格不存在时返回{@code null} * * @param locationRef 单元格地址标识符,例如A11,B5 * @return {@link Cell} @@ -157,7 +157,7 @@ public class ExcelBase> implements Closeable { } /** - * 获取指定坐标单元格,单元格不存在时返回null + * 获取指定坐标单元格,单元格不存在时返回{@code null} * * @param x X坐标,从0计数,即列号 * @param y Y坐标,从0计数,即行号 @@ -193,7 +193,7 @@ public class ExcelBase> implements Closeable { } /** - * 获取指定坐标单元格,如果isCreateIfNotExist为false,则在单元格不存在时返回null + * 获取指定坐标单元格,如果isCreateIfNotExist为false,则在单元格不存在时返回{@code null} * * @param locationRef 单元格地址标识符,例如A11,B5 * @param isCreateIfNotExist 单元格不存在时是否创建 @@ -206,7 +206,7 @@ public class ExcelBase> implements Closeable { } /** - * 获取指定坐标单元格,如果isCreateIfNotExist为false,则在单元格不存在时返回null + * 获取指定坐标单元格,如果isCreateIfNotExist为false,则在单元格不存在时返回{@code null} * * @param x X坐标,从0计数,即列号 * @param y Y坐标,从0计数,即行号 diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelWriter.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelWriter.java index 46dda3f2c..6585b78ab 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelWriter.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelWriter.java @@ -233,7 +233,7 @@ public class ExcelWriter extends ExcelBase { /** * 重命名sheet * - * @param sheet sheet需要,0表示第一个sheet + * @param sheet sheet序号,0表示第一个sheet * @param sheetName 新的sheet名 * @return this * @since 4.1.8 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 65d697be5..530c3f762 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,5 +1,6 @@ package cn.hutool.poi.excel.sax; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; @@ -11,7 +12,7 @@ import org.xml.sax.helpers.DefaultHandler; import java.io.IOException; import java.io.InputStream; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; /** @@ -36,8 +37,8 @@ public class SheetRidReader extends DefaultHandler { private final static String SHEET_ID_ATTR = "sheetId"; private final static String NAME_ATTR = "name"; - private final Map ID_RID_MAP = new HashMap<>(); - private final Map NAME_RID_MAP = new HashMap<>(); + private final Map ID_RID_MAP = new LinkedHashMap<>(); + private final Map NAME_RID_MAP = new LinkedHashMap<>(); /** * 读取Wordkbook的XML中sheet标签中sheetId和rid的对应关系 @@ -79,7 +80,7 @@ public class SheetRidReader extends DefaultHandler { */ public Integer getRidBySheetIdBase0(int sheetId) { final Integer rid = getRidBySheetId(sheetId + 1); - if(null != rid){ + if (null != rid) { return rid - 1; } return null; @@ -104,7 +105,33 @@ public class SheetRidReader extends DefaultHandler { */ public Integer getRidByNameBase0(String sheetName) { final Integer rid = getRidByName(sheetName); - if(null != rid){ + if (null != rid) { + return rid - 1; + } + return null; + } + + /** + * 通过sheet的序号获取rid + * + * @param index 序号,从0开始 + * @return rid + * @since 5.5.7 + */ + public Integer getRidByIndex(int index) { + return CollUtil.get(this.NAME_RID_MAP.values(), index); + } + + /** + * 通过sheet的序号获取rid + * + * @param index 序号,从0开始 + * @return rid,从0开始 + * @since 5.5.7 + */ + public Integer getRidByIndexBase0(int index) { + final Integer rid = CollUtil.get(this.NAME_RID_MAP.values(), index); + if (null != rid) { return rid - 1; } return null; @@ -114,7 +141,7 @@ public class SheetRidReader extends DefaultHandler { public void startElement(String uri, String localName, String qName, Attributes attributes) { if (TAG_NAME.equalsIgnoreCase(localName)) { final String ridStr = attributes.getValue(RID_ATTR); - if(StrUtil.isEmpty(ridStr)){ + if (StrUtil.isEmpty(ridStr)) { return; } final int rid = Integer.parseInt(StrUtil.removePrefixIgnoreCase(ridStr, Excel07SaxReader.RID_PREFIX)); @@ -127,7 +154,7 @@ public class SheetRidReader extends DefaultHandler { // sheetId和rid映射 final String sheetIdStr = attributes.getValue(SHEET_ID_ATTR); - if(StrUtil.isNotEmpty(sheetIdStr)){ + if (StrUtil.isNotEmpty(sheetIdStr)) { ID_RID_MAP.put(Integer.parseInt(sheetIdStr), rid); } } From 99f6fe81104503f8ecad5b447c7edcf67cc24ea2 Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 2 Jan 2021 12:46:13 +0800 Subject: [PATCH 29/54] add section for #IZN95 --- CHANGELOG.md | 2 ++ .../java/cn/hutool/core/util/ZipUtilTest.java | 7 +++-- .../main/java/cn/hutool/extra/mail/Mail.java | 16 ++-------- .../cn/hutool/extra/mail/MailAccount.java | 31 +++++++++++++++++++ .../java/cn/hutool/extra/mail/MailUtil.java | 20 ++++++++++++ 5 files changed, 61 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff4b20fc1..38c61e5ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ * 【core 】 DynaBean.create增加重载方法(pr#245@Gitee) * 【core 】 IdcardUtil增加重载是否忽略大小写(issue#1348@Github) * 【poi 】 SheetRidReader增加getRidByIndex方法(issue#1342@Github) +* 【extra 】 MailAccount增加sslProtocols配置项(issue#IZN95@Gitee) +* 【extra 】 MailUtil增加getSession方法 ### Bug修复 diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ZipUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ZipUtilTest.java index fd33ae852..3f5b314cd 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/ZipUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/ZipUtilTest.java @@ -1,6 +1,7 @@ package cn.hutool.core.util; import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.lang.Console; import org.junit.Assert; import org.junit.Ignore; @@ -8,6 +9,7 @@ import org.junit.Test; import java.io.File; import java.io.FileOutputStream; +import java.io.IOException; import java.io.OutputStream; import java.nio.charset.Charset; @@ -102,8 +104,9 @@ public class ZipUtilTest { try (OutputStream out = new FileOutputStream(zip)){ //实际应用中, out 为 HttpServletResponse.getOutputStream ZipUtil.zip(out, Charset.defaultCharset(), false, null, new File(dir)); - } catch (Exception e) { - e.printStackTrace(); + } catch (IOException e) { + throw new IORuntimeException(e); } } + } diff --git a/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java b/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java index 95137a7a9..bab301ba0 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java @@ -12,7 +12,6 @@ import javax.activation.DataSource; import javax.activation.FileDataSource; import javax.activation.FileTypeMap; import javax.mail.Address; -import javax.mail.Authenticator; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.SendFailedException; @@ -407,7 +406,7 @@ public class Mail { */ private MimeMessage buildMsg() throws MessagingException { final Charset charset = this.mailAccount.getCharset(); - final MimeMessage msg = new MimeMessage(getSession(this.useGlobalSession)); + final MimeMessage msg = new MimeMessage(getSession()); // 发件人 final String from = this.mailAccount.getFrom(); if (StrUtil.isEmpty(from)) { @@ -460,19 +459,10 @@ public class Mail { * 获取默认邮件会话
    * 如果为全局单例的会话,则全局只允许一个邮件帐号,否则每次发送邮件会新建一个新的会话 * - * @param isSingleton 是否使用单例Session * @return 邮件会话 {@link Session} - * @since 4.0.2 */ - private Session getSession(boolean isSingleton) { - final MailAccount mailAccount = this.mailAccount; - Authenticator authenticator = null; - if (mailAccount.isAuth()) { - authenticator = new UserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass()); - } - - final Session session = isSingleton ? Session.getDefaultInstance(mailAccount.getSmtpProps(), authenticator) // - : Session.getInstance(mailAccount.getSmtpProps(), authenticator); + private Session getSession() { + final Session session = MailUtil.getSession(this.mailAccount, this.useGlobalSession); if(null != this.debugOutput){ session.setDebugOut(debugOutput); diff --git a/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java b/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java index 199c79368..33279de24 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java @@ -23,8 +23,10 @@ public class MailAccount implements Serializable { private static final String SMTP_CONNECTION_TIMEOUT = "mail.smtp.connectiontimeout"; private static final String SMTP_TIMEOUT = "mail.smtp.timeout"; + // SSL private static final String STARTTLS_ENABLE = "mail.smtp.starttls.enable"; private static final String SSL_ENABLE = "mail.smtp.ssl.enable"; + private static final String SSL_PROTOCOLS = "mail.smtp.ssl.protocols"; private static final String SOCKET_FACTORY = "mail.smtp.socketFactory.class"; private static final String SOCKET_FACTORY_FALLBACK = "mail.smtp.socketFactory.fallback"; private static final String SOCKET_FACTORY_PORT = "smtp.socketFactory.port"; @@ -80,6 +82,12 @@ public class MailAccount implements Serializable { * 使用 SSL安全连接 */ private Boolean sslEnable; + + /** + * SSL协议,多个协议用空格分隔 + */ + private String sslProtocols; + /** * 指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字 */ @@ -356,6 +364,25 @@ public class MailAccount implements Serializable { return this; } + /** + * 获取SSL协议,多个协议用空格分隔 + * @return SSL协议,多个协议用空格分隔 + * @since 5.5.7 + */ + public String getSslProtocols() { + return sslProtocols; + } + + /** + * 设置SSL协议,多个协议用空格分隔 + * + * @param sslProtocols SSL协议,多个协议用空格分隔 + * @since 5.5.7 + */ + public void setSslProtocols(String sslProtocols) { + this.sslProtocols = sslProtocols; + } + /** * 获取指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字 * @@ -479,6 +506,10 @@ public class MailAccount implements Serializable { p.put(SOCKET_FACTORY, socketFactoryClass); p.put(SOCKET_FACTORY_FALLBACK, String.valueOf(this.socketFactoryFallback)); p.put(SOCKET_FACTORY_PORT, String.valueOf(this.socketFactoryPort)); + // issue#IZN95@Gitee,在Linux下需自定义SSL协议版本 + if(StrUtil.isNotBlank(this.sslProtocols)){ + p.put(SSL_PROTOCOLS, this.sslProtocols); + } } return p; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/mail/MailUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/mail/MailUtil.java index 1af4c9491..eb0978f7a 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/mail/MailUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/mail/MailUtil.java @@ -5,6 +5,8 @@ import cn.hutool.core.io.IoUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.StrUtil; +import javax.mail.Authenticator; +import javax.mail.Session; import java.io.File; import java.io.InputStream; import java.util.Collection; @@ -346,6 +348,24 @@ public class MailUtil { return send(mailAccount, false, tos, ccs, bccs, subject, content, imageMap, isHtml, files); } + /** + * 根据配置文件,获取邮件客户端会话 + * + * @param mailAccount 邮件账户配置 + * @param isSingleton 是否单例(全局共享会话) + * @return {@link Session} + * @since 5.5.7 + */ + public static Session getSession(MailAccount mailAccount, boolean isSingleton){ + Authenticator authenticator = null; + if (mailAccount.isAuth()) { + authenticator = new UserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass()); + } + + return isSingleton ? Session.getDefaultInstance(mailAccount.getSmtpProps(), authenticator) // + : Session.getInstance(mailAccount.getSmtpProps(), authenticator); + } + // ------------------------------------------------------------------------------------------------------------------------ Private method start /** From bcaf05c5894340e3f8beb0a68a2a25539646544d Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 2 Jan 2021 13:40:43 +0800 Subject: [PATCH 30/54] add section for #IZN95 --- .../src/test/java/cn/hutool/core/util/IdcardUtilTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 4e3a85610..d58aa71bb 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 @@ -43,7 +43,7 @@ public class IdcardUtilTest { Assert.assertEquals("150102198807303035", convert15To18); String convert15To18Second = IdcardUtil.convert15To18("330102200403064"); - Assert.assertEquals("33010219200403064x", convert15To18Second); + Assert.assertEquals("33010219200403064X", convert15To18Second); } @Test From 3c2f0e46b0cbed159911182bacb302c177c8008c Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 3 Jan 2021 12:12:02 +0800 Subject: [PATCH 31/54] fix #I2BMP1 --- CHANGELOG.md | 3 +- .../cn/hutool/core/text/csv/CsvConfig.java | 38 +++++-- .../cn/hutool/core/text/csv/CsvParser.java | 89 ++++++++++----- .../cn/hutool/core/text/csv/CsvWriter.java | 105 +++++++++++++----- .../java/cn/hutool/core/util/CharUtil.java | 2 +- .../cn/hutool/core/text/csv/CsvUtilTest.java | 38 +++++-- hutool-core/src/test/resources/test.csv | 2 +- 7 files changed, 202 insertions(+), 75 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38c61e5ea..0ca63c2ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------------------------------------- -# 5.5.7 (2021-01-02) +# 5.5.7 (2021-01-03) ### 新特性 * 【core 】 DynaBean.create增加重载方法(pr#245@Gitee) @@ -13,6 +13,7 @@ * 【extra 】 MailUtil增加getSession方法 ### Bug修复 +* 【core 】 修复CsvReader读取双引号未转义问题(issur#I2BMP1@Gitee) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvConfig.java b/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvConfig.java index 65aa48c07..d143a27ba 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvConfig.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvConfig.java @@ -1,26 +1,34 @@ package cn.hutool.core.text.csv; -import java.io.Serializable; - import cn.hutool.core.util.CharUtil; +import java.io.Serializable; + /** - * CSV基础配置项 - * + * CSV基础配置项,此配置项可用于读取和写出CSV,定义了包括字段分隔符、文本包装符等符号 + * * @author looly * @since 4.0.5 */ -public class CsvConfig implements Serializable{ +public class CsvConfig implements Serializable { private static final long serialVersionUID = -8069578249066158459L; - - /** 字段分隔符,默认逗号',' */ + + /** + * 字段分隔符,默认逗号',' + */ protected char fieldSeparator = CharUtil.COMMA; - /** 文本分隔符,文本包装符,默认双引号'"' */ + /** + * 文本包装符,默认双引号'"' + */ protected char textDelimiter = CharUtil.DOUBLE_QUOTES; + /** + * 注释符号,用于区分注释行,默认'#' + */ + protected char commentCharacter = '#'; /** * 设置字段分隔符,默认逗号',' - * + * * @param fieldSeparator 字段分隔符,默认逗号',' */ public void setFieldSeparator(final char fieldSeparator) { @@ -29,10 +37,20 @@ public class CsvConfig implements Serializable{ /** * 设置 文本分隔符,文本包装符,默认双引号'"' - * + * * @param textDelimiter 文本分隔符,文本包装符,默认双引号'"' */ public void setTextDelimiter(char textDelimiter) { this.textDelimiter = textDelimiter; } + + /** + * 设置 注释符号,用于区分注释行 + * + * @param commentCharacter 注释符号,用于区分注释行 + * @since 5.5.7 + */ + public void setCommentCharacter(char commentCharacter) { + this.commentCharacter = commentCharacter; + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvParser.java b/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvParser.java index 0ccd01a16..0a362ed93 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvParser.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvParser.java @@ -32,33 +32,55 @@ public final class CsvParser implements Closeable, Serializable { private final CsvReadConfig config; private final char[] buf = new char[IoUtil.DEFAULT_LARGE_BUFFER_SIZE]; - /** 当前位置 */ + /** + * 当前位置 + */ private int bufPos; - /** 读取一段后数据长度 */ + /** + * 读取一段后数据长度 + */ private int bufLen; - /** 拷贝开始的位置,一般为上一行的结束位置 */ + /** + * 拷贝开始的位置,一般为上一行的结束位置 + */ private int copyStart; - /** 前一个特殊分界字符 */ + /** + * 前一个特殊分界字符 + */ private int preChar = -1; - /** 是否在引号包装内 */ + /** + * 是否在引号包装内 + */ private boolean inQuotes; - /** 当前读取字段 */ + /** + * 当前读取字段 + */ private final StrBuilder currentField = new StrBuilder(512); - - /** 标题行 */ + + /** + * 标题行 + */ private CsvRow header; - /** 当前行号 */ + /** + * 当前行号 + */ private long lineNo; - /** 第一行字段数,用于检查每行字段数是否一致 */ + /** + * 第一行字段数,用于检查每行字段数是否一致 + */ private int firstLineFieldCount = -1; - /** 最大字段数量 */ + /** + * 最大字段数量 + */ private int maxFieldCount; - /** 是否读取结束 */ + /** + * 是否读取结束 + */ private boolean finished; /** * CSV解析器 - * + * * @param reader Reader * @param config 配置,null则为默认配置 */ @@ -84,7 +106,7 @@ public final class CsvParser implements Closeable, Serializable { } /** - *读取下一行数据 + * 读取下一行数据 * * @return CsvRow * @throws IORuntimeException IO读取异常 @@ -97,7 +119,7 @@ public final class CsvParser implements Closeable, Serializable { startingLineNo = ++lineNo; currentFields = readLine(); fieldCount = currentFields.size(); - if(fieldCount < 1){ + if (fieldCount < 1) { break; } @@ -135,24 +157,24 @@ public final class CsvParser implements Closeable, Serializable { /** * 当前行做为标题行 - * + * * @param currentFields 当前行字段列表 */ private void initHeader(final List currentFields) { final Map localHeaderMap = new LinkedHashMap<>(currentFields.size()); for (int i = 0; i < currentFields.size(); i++) { final String field = currentFields.get(i); - if (StrUtil.isNotEmpty(field) && false ==localHeaderMap.containsKey(field)) { + if (StrUtil.isNotEmpty(field) && false == localHeaderMap.containsKey(field)) { localHeaderMap.put(field, i); } } - - header = new CsvRow(this.lineNo, Collections.unmodifiableMap(localHeaderMap), Collections.unmodifiableList(currentFields)); + + header = new CsvRow(this.lineNo, Collections.unmodifiableMap(localHeaderMap), Collections.unmodifiableList(currentFields)); } /** * 读取一行数据 - * + * * @return 一行数据 * @throws IORuntimeException IO异常 */ @@ -185,7 +207,7 @@ public final class CsvParser implements Closeable, Serializable { if (localPreChar == config.fieldSeparator || localCurrentField.hasContent()) { //剩余部分作为一个字段 - currentFields.add(StrUtil.unWrap(localCurrentField.toStringAndReset(), config.textDelimiter)); + addField(currentFields, localCurrentField.toStringAndReset()); } break; } @@ -208,36 +230,40 @@ public final class CsvParser implements Closeable, Serializable { } copyLen++; } else { + // 非引号内 if (c == config.fieldSeparator) { //一个字段结束 if (copyLen > 0) { localCurrentField.append(localBuf, localCopyStart, copyLen); copyLen = 0; } - currentFields.add(StrUtil.unWrap(localCurrentField.toStringAndReset(), config.textDelimiter)); + addField(currentFields, localCurrentField.toStringAndReset()); localCopyStart = localBufPos; } else if (c == config.textDelimiter) { // 引号开始 inQuotes = true; copyLen++; } else if (c == CharUtil.CR) { + // \r,直接结束 if (copyLen > 0) { localCurrentField.append(localBuf, localCopyStart, copyLen); } - currentFields.add(StrUtil.unWrap(localCurrentField.toStringAndReset(), config.textDelimiter)); + addField(currentFields, localCurrentField.toStringAndReset()); localPreChar = c; localCopyStart = localBufPos; break; } else if (c == CharUtil.LF) { + // \n if (localPreChar != CharUtil.CR) { if (copyLen > 0) { localCurrentField.append(localBuf, localCopyStart, copyLen); } - currentFields.add(StrUtil.unWrap(localCurrentField.toStringAndReset(), config.textDelimiter)); + addField(currentFields, localCurrentField.toStringAndReset()); localPreChar = c; localCopyStart = localBufPos; break; } + // 前一个字符是\r,已经处理过这个字段了,此处直接跳过 localCopyStart = localBufPos; } else { copyLen++; @@ -254,9 +280,22 @@ public final class CsvParser implements Closeable, Serializable { return currentFields; } - + @Override public void close() throws IOException { reader.close(); } + + /** + * 将字段加入字段列表并自动去包装和去转义 + * + * @param currentFields 当前的字段列表(即为行) + * @param field 字段 + */ + private void addField(List currentFields, String field) { + field = StrUtil.unWrap(field, config.textDelimiter); + char textDelimiter = this.config.textDelimiter; + field = StrUtil.replace(field, "" + textDelimiter + textDelimiter, textDelimiter + ""); + currentFields.add(StrUtil.unWrap(field, textDelimiter)); + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvWriter.java b/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvWriter.java index d9528bc26..a012827a6 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvWriter.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvWriter.java @@ -29,17 +29,24 @@ import java.util.Collection; public final class CsvWriter implements Closeable, Flushable, Serializable { private static final long serialVersionUID = 1L; - /** 写出器 */ + /** + * 写出器 + */ private final Writer writer; - /** 写出配置 */ + /** + * 写出配置 + */ private final CsvWriteConfig config; - /** 是否处于新行开始 */ + /** + * 是否处于新行开始 + */ private boolean newline = true; // --------------------------------------------------------------------------------------------------- Constructor start + /** * 构造,覆盖已有文件(如果存在),默认编码UTF-8 - * + * * @param filePath File CSV文件路径 */ public CsvWriter(String filePath) { @@ -48,7 +55,7 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { /** * 构造,覆盖已有文件(如果存在),默认编码UTF-8 - * + * * @param file File CSV文件 */ public CsvWriter(File file) { @@ -57,9 +64,9 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { /** * 构造,覆盖已有文件(如果存在) - * + * * @param filePath File CSV文件路径 - * @param charset 编码 + * @param charset 编码 */ public CsvWriter(String filePath, Charset charset) { this(FileUtil.file(filePath), charset); @@ -67,8 +74,8 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { /** * 构造,覆盖已有文件(如果存在) - * - * @param file File CSV文件 + * + * @param file File CSV文件 * @param charset 编码 */ public CsvWriter(File file, Charset charset) { @@ -77,9 +84,9 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { /** * 构造 - * + * * @param filePath File CSV文件路径 - * @param charset 编码 + * @param charset 编码 * @param isAppend 是否追加 */ public CsvWriter(String filePath, Charset charset, boolean isAppend) { @@ -88,9 +95,9 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { /** * 构造 - * - * @param file CSV文件 - * @param charset 编码 + * + * @param file CSV文件 + * @param charset 编码 * @param isAppend 是否追加 */ public CsvWriter(File file, Charset charset, boolean isAppend) { @@ -99,11 +106,11 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { /** * 构造 - * + * * @param filePath CSV文件路径 - * @param charset 编码 + * @param charset 编码 * @param isAppend 是否追加 - * @param config 写出配置,null则使用默认配置 + * @param config 写出配置,null则使用默认配置 */ public CsvWriter(String filePath, Charset charset, boolean isAppend, CsvWriteConfig config) { this(FileUtil.file(filePath), charset, isAppend, config); @@ -111,11 +118,11 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { /** * 构造 - * - * @param file CSV文件 - * @param charset 编码 + * + * @param file CSV文件 + * @param charset 编码 * @param isAppend 是否追加 - * @param config 写出配置,null则使用默认配置 + * @param config 写出配置,null则使用默认配置 */ public CsvWriter(File file, Charset charset, boolean isAppend, CsvWriteConfig config) { this(FileUtil.getWriter(file, charset, isAppend), config); @@ -123,7 +130,7 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { /** * 构造,使用默认配置 - * + * * @param writer {@link Writer} */ public CsvWriter(Writer writer) { @@ -132,7 +139,7 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { /** * 构造 - * + * * @param writer Writer * @param config 写出配置,null则使用默认配置 */ @@ -144,7 +151,7 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { /** * 设置是否始终使用文本分隔符,文本包装符,默认false,按需添加 - * + * * @param alwaysDelimitText 是否始终使用文本分隔符,文本包装符,默认false,按需添加 * @return this */ @@ -155,7 +162,7 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { /** * 设置换行符 - * + * * @param lineDelimiter 换行符 * @return this */ @@ -166,7 +173,7 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { /** * 将多行写出到Writer - * + * * @param lines 多行数据 * @return this * @throws IORuntimeException IO异常 @@ -183,7 +190,7 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { /** * 将多行写出到Writer - * + * * @param lines 多行数据,每行数据可以是集合或者数组 * @return this * @throws IORuntimeException IO异常 @@ -198,18 +205,55 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { return this; } + /** + * 写出一行 + * + * @param fields 字段列表 ({@code null} 值会被做为空值追加) + * @return this + * @throws IORuntimeException IO异常 + * @since 5.5.7 + */ + public CsvWriter writeLine(String... fields) throws IORuntimeException { + if (ArrayUtil.isEmpty(fields)) { + return writeLine(); + } + appendLine(fields); + return this; + } + /** * 追加新行(换行) * * @throws IORuntimeException IO异常 */ - public void writeLine() throws IORuntimeException { + public CsvWriter writeLine() throws IORuntimeException { try { writer.write(config.lineDelimiter); } catch (IOException e) { throw new IORuntimeException(e); } newline = true; + return this; + } + + /** + * 写出一行注释,注释符号可自定义 + * + * @param comment 注释内容 + * @return this + * @see CsvConfig#commentCharacter + * @since 5.5.7 + */ + public CsvWriter writeComment(String comment) { + try { + writer.write(this.config.commentCharacter); + writer.write(comment); + writer.write(config.lineDelimiter); + newline = true; + } catch (IOException e) { + throw new IORuntimeException(e); + } + return this; } @Override @@ -227,13 +271,14 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { } // --------------------------------------------------------------------------------------------------- Private method start + /** * 追加一行,末尾会自动换行,但是追加前不会换行 * * @param fields 字段列表 ({@code null} 值会被做为空值追加) * @throws IORuntimeException IO异常 */ - private void appendLine(final String... fields) throws IORuntimeException { + private void appendLine(String... fields) throws IORuntimeException { try { doAppendLine(fields); } catch (IOException e) { @@ -276,7 +321,7 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { if (null == value) { if (alwaysDelimitText) { - writer.write(new char[] { textDelimiter, textDelimiter }); + writer.write(new char[]{textDelimiter, textDelimiter}); } return; } diff --git a/hutool-core/src/main/java/cn/hutool/core/util/CharUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/CharUtil.java index edabec224..610b8baad 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/CharUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/CharUtil.java @@ -47,7 +47,7 @@ public class CharUtil { public static final char AMP = '&'; /** 字符常量:冒号 {@code ':'} */ public static final char COLON = ':'; - /** 字符常量:艾特 '@' */ + /** 字符常量:艾特 {@code '@'} */ public static final char AT = '@'; /** diff --git a/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvUtilTest.java index 43eea4a40..74b81a29c 100644 --- a/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvUtilTest.java @@ -1,8 +1,9 @@ package cn.hutool.core.text.csv; import cn.hutool.core.io.FileUtil; -import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.Console; import cn.hutool.core.util.CharsetUtil; +import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -16,26 +17,49 @@ public class CsvUtilTest { //从文件中读取CSV数据 CsvData data = reader.read(FileUtil.file("test.csv")); List rows = data.getRows(); - for (CsvRow csvRow : rows) { - Assert.notEmpty(csvRow.getRawList()); - } + final CsvRow row0 = rows.get(0); + Assert.assertEquals("sss,sss", row0.get(0)); + Assert.assertEquals("姓名", row0.get(1)); + Assert.assertEquals("性别", row0.get(2)); + Assert.assertEquals("关注\"对象\"", row0.get(3)); + Assert.assertEquals("年龄", row0.get(4)); + Assert.assertEquals("", row0.get(5)); + Assert.assertEquals("\"", row0.get(6)); } @Test public void readTest2() { CsvReader reader = CsvUtil.getReader(); - reader.read(FileUtil.getUtf8Reader("test.csv"), (csvRow)-> Assert.notEmpty(csvRow.getRawList())); + reader.read(FileUtil.getUtf8Reader("test.csv"), (csvRow)-> { + // 只有一行,所以直接判断 + Assert.assertEquals("sss,sss", csvRow.get(0)); + Assert.assertEquals("姓名", csvRow.get(1)); + Assert.assertEquals("性别", csvRow.get(2)); + Assert.assertEquals("关注\"对象\"", csvRow.get(3)); + Assert.assertEquals("年龄", csvRow.get(4)); + Assert.assertEquals("", csvRow.get(5)); + Assert.assertEquals("\"", csvRow.get(6)); + }); } @Test @Ignore public void writeTest() { - CsvWriter writer = CsvUtil.getWriter("e:/testWrite.csv", CharsetUtil.CHARSET_UTF_8); + CsvWriter writer = CsvUtil.getWriter("d:/test/testWrite.csv", CharsetUtil.CHARSET_UTF_8); writer.write( new String[] {"a1", "b1", "c1", "123345346456745756756785656"}, new String[] {"a2", "b2", "c2"}, new String[] {"a3", "b3", "c3"} ); } - + + @Test + @Ignore + public void readLfTest(){ + final CsvReader reader = CsvUtil.getReader(); + final CsvData read = reader.read(FileUtil.file("d:/test/rw_test.csv")); + for (CsvRow row : read) { + Console.log(row); + } + } } diff --git a/hutool-core/src/test/resources/test.csv b/hutool-core/src/test/resources/test.csv index a22b8335f..6c6ee2ff4 100644 --- a/hutool-core/src/test/resources/test.csv +++ b/hutool-core/src/test/resources/test.csv @@ -1 +1 @@ -"sss,sss",姓名,"性别",关注"对象",年龄 \ No newline at end of file +"sss,sss",姓名,"性别",关注"对象",年龄,"",""" \ No newline at end of file From f3238ae1e70d4f1323f47526a771516038da5404 Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 4 Jan 2021 05:36:20 +0800 Subject: [PATCH 32/54] fix CsvParser --- .../java/cn/hutool/core/io/BufferUtil.java | 85 ++++---- .../cn/hutool/core/text/csv/CsvParser.java | 186 +++++++++++++----- .../cn/hutool/core/text/csv/CsvUtilTest.java | 6 + hutool-core/src/test/resources/test.csv | 1 + 4 files changed, 190 insertions(+), 88 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/io/BufferUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/BufferUtil.java index fb15159da..007e0194e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/BufferUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/BufferUtil.java @@ -1,28 +1,28 @@ package cn.hutool.core.io; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; - import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.StrUtil; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; + /** * {@link ByteBuffer} 工具类
    * 此工具来自于 t-io 项目以及其它项目的相关部分收集
    * ByteBuffer的相关介绍见:https://www.cnblogs.com/ruber/p/6857159.html - * + * * @author tanyaowu, looly * @since 4.0.0 - * */ public class BufferUtil { /** * 拷贝到一个新的ByteBuffer - * - * @param src 源ByteBuffer + * + * @param src 源ByteBuffer * @param start 起始位置(包括) - * @param end 结束位置(不包括) + * @param end 结束位置(不包括) * @return 新的ByteBuffer */ public static ByteBuffer copy(ByteBuffer src, int start, int end) { @@ -31,8 +31,8 @@ public class BufferUtil { /** * 拷贝ByteBuffer - * - * @param src 源ByteBuffer + * + * @param src 源ByteBuffer * @param dest 目标ByteBuffer * @return 目标ByteBuffer */ @@ -42,9 +42,9 @@ public class BufferUtil { /** * 拷贝ByteBuffer - * - * @param src 源ByteBuffer - * @param dest 目标ByteBuffer + * + * @param src 源ByteBuffer + * @param dest 目标ByteBuffer * @param length 长度 * @return 目标ByteBuffer */ @@ -54,12 +54,12 @@ public class BufferUtil { /** * 拷贝ByteBuffer - * - * @param src 源ByteBuffer - * @param srcStart 源开始的位置 - * @param dest 目标ByteBuffer + * + * @param src 源ByteBuffer + * @param srcStart 源开始的位置 + * @param dest 目标ByteBuffer * @param destStart 目标开始的位置 - * @param length 长度 + * @param length 长度 * @return 目标ByteBuffer */ public static ByteBuffer copy(ByteBuffer src, int srcStart, ByteBuffer dest, int destStart, int length) { @@ -69,7 +69,7 @@ public class BufferUtil { /** * 读取剩余部分并转为UTF-8编码字符串 - * + * * @param buffer ByteBuffer * @return 字符串 * @since 4.5.0 @@ -80,8 +80,8 @@ public class BufferUtil { /** * 读取剩余部分并转为字符串 - * - * @param buffer ByteBuffer + * + * @param buffer ByteBuffer * @param charset 编码 * @return 字符串 * @since 4.5.0 @@ -92,7 +92,7 @@ public class BufferUtil { /** * 读取剩余部分bytes
    - * + * * @param buffer ByteBuffer * @return bytes */ @@ -106,8 +106,8 @@ public class BufferUtil { /** * 读取指定长度的bytes
    * 如果长度不足,则读取剩余部分,此时buffer必须为读模式 - * - * @param buffer ByteBuffer + * + * @param buffer ByteBuffer * @param maxLength 最大长度 * @return bytes */ @@ -123,10 +123,10 @@ public class BufferUtil { /** * 读取指定区间的数据 - * + * * @param buffer {@link ByteBuffer} - * @param start 开始位置 - * @param end 结束位置 + * @param start 开始位置 + * @param end 结束位置 * @return bytes */ public static byte[] readBytes(ByteBuffer buffer, int start, int end) { @@ -148,13 +148,13 @@ public class BufferUtil { /** * 一行的末尾位置,查找位置时位移ByteBuffer到结束位置
    * 支持的换行符如下: - * + * *

     	 * 1. \r\n
     	 * 2. \n
     	 * 
    * - * @param buffer {@link ByteBuffer} + * @param buffer {@link ByteBuffer} * @param maxLength 读取最大长度 * @return 末尾位置,未找到或达到最大长度返回-1 */ @@ -191,13 +191,13 @@ public class BufferUtil { /** * 读取一行,如果buffer中最后一部分并非完整一行,则返回null
    * 支持的换行符如下: - * + * *
     	 * 1. \r\n
     	 * 2. \n
     	 * 
    - * - * @param buffer ByteBuffer + * + * @param buffer ByteBuffer * @param charset 编码 * @return 一行 */ @@ -217,7 +217,7 @@ public class BufferUtil { /** * 创建新Buffer - * + * * @param data 数据 * @return {@link ByteBuffer} * @since 4.5.0 @@ -228,8 +228,8 @@ public class BufferUtil { /** * 从字符串创建新Buffer - * - * @param data 数据 + * + * @param data 数据 * @param charset 编码 * @return {@link ByteBuffer} * @since 4.5.0 @@ -237,10 +237,10 @@ public class BufferUtil { public static ByteBuffer create(CharSequence data, Charset charset) { return create(StrUtil.bytes(data, charset)); } - + /** * 从字符串创建新Buffer,使用UTF-8编码 - * + * * @param data 数据 * @return {@link ByteBuffer} * @since 4.5.0 @@ -248,4 +248,15 @@ public class BufferUtil { public static ByteBuffer createUtf8(CharSequence data) { return create(StrUtil.utf8Bytes(data)); } + + /** + * 创建{@link CharBuffer} + * + * @param capacity 容量 + * @return {@link CharBuffer} + * @since 5.5.7 + */ + public static CharBuffer createCharBuffer(int capacity) { + return CharBuffer.allocate(capacity); + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvParser.java b/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvParser.java index 0a362ed93..440556216 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvParser.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvParser.java @@ -31,19 +31,7 @@ public final class CsvParser implements Closeable, Serializable { private final Reader reader; private final CsvReadConfig config; - private final char[] buf = new char[IoUtil.DEFAULT_LARGE_BUFFER_SIZE]; - /** - * 当前位置 - */ - private int bufPos; - /** - * 读取一段后数据长度 - */ - private int bufLen; - /** - * 拷贝开始的位置,一般为上一行的结束位置 - */ - private int copyStart; + private final Buffer buf = new Buffer(IoUtil.DEFAULT_LARGE_BUFFER_SIZE); /** * 前一个特殊分界字符 */ @@ -70,7 +58,7 @@ public final class CsvParser implements Closeable, Serializable { */ private int firstLineFieldCount = -1; /** - * 最大字段数量 + * 最大字段数量,用于初始化行,减少扩容 */ private int maxFieldCount; /** @@ -181,42 +169,55 @@ public final class CsvParser implements Closeable, Serializable { private List readLine() throws IORuntimeException { final List currentFields = new ArrayList<>(maxFieldCount > 0 ? maxFieldCount : DEFAULT_ROW_CAPACITY); - final StrBuilder localCurrentField = currentField; - final char[] localBuf = this.buf; - int localBufPos = bufPos;//当前位置 - int localPreChar = preChar;//前一个特殊分界字符 - int localCopyStart = copyStart;//拷贝起始位置 + final StrBuilder currentField = this.currentField; + final Buffer buf = this.buf; + int preChar = this.preChar;//前一个特殊分界字符 int copyLen = 0; //拷贝长度 + boolean lineStart = true; + boolean inComment = false; while (true) { - if (bufLen == localBufPos) { + if (false == buf.hasRemaining()) { // 此Buffer读取结束,开始读取下一段 - if (copyLen > 0) { - localCurrentField.append(localBuf, localCopyStart, copyLen); + buf.appendTo(currentField, copyLen); + // 此处无需mark,read方法会重置mark } - try { - bufLen = reader.read(localBuf); - } catch (IOException e) { - throw new IORuntimeException(e); - } - - if (bufLen < 0) { + if (buf.read(this.reader) < 0) { // CSV读取结束 finished = true; - if (localPreChar == config.fieldSeparator || localCurrentField.hasContent()) { + if (currentField.hasContent() || preChar == config.fieldSeparator) { //剩余部分作为一个字段 - addField(currentFields, localCurrentField.toStringAndReset()); + addField(currentFields, currentField.toStringAndReset()); } break; } //重置 - localCopyStart = localBufPos = copyLen = 0; + copyLen = 0; } - final char c = localBuf[localBufPos++]; + final char c = buf.get(); + + // 注释行标记 + if(lineStart){ + if(c == this.config.commentCharacter){ + inComment = true; + } + lineStart = false; + } + // 注释行处理 + if(inComment){ + if ((c == CharUtil.CR || c == CharUtil.LF) && preChar != CharUtil.CR) { + // 注释行以换行符为结尾 + inComment = false; + } + // 跳过注释行中的任何字符 + buf.mark(); + preChar = c; + continue; + } if (inQuotes) { //引号内,做为内容,直到引号结束 @@ -224,21 +225,23 @@ public final class CsvParser implements Closeable, Serializable { // End of quoted text inQuotes = false; } else { - if ((c == CharUtil.CR || c == CharUtil.LF) && localPreChar != CharUtil.CR) { + // 新行 + if ((c == CharUtil.CR || c == CharUtil.LF) && preChar != CharUtil.CR) { lineNo++; } } + // 普通字段字符 copyLen++; } else { // 非引号内 if (c == config.fieldSeparator) { //一个字段结束 if (copyLen > 0) { - localCurrentField.append(localBuf, localCopyStart, copyLen); + buf.appendTo(currentField, copyLen); copyLen = 0; } - addField(currentFields, localCurrentField.toStringAndReset()); - localCopyStart = localBufPos; + buf.mark(); + addField(currentFields, currentField.toStringAndReset()); } else if (c == config.textDelimiter) { // 引号开始 inQuotes = true; @@ -246,37 +249,36 @@ public final class CsvParser implements Closeable, Serializable { } else if (c == CharUtil.CR) { // \r,直接结束 if (copyLen > 0) { - localCurrentField.append(localBuf, localCopyStart, copyLen); + buf.appendTo(currentField, copyLen); } - addField(currentFields, localCurrentField.toStringAndReset()); - localPreChar = c; - localCopyStart = localBufPos; + buf.mark(); + addField(currentFields, currentField.toStringAndReset()); + preChar = c; break; } else if (c == CharUtil.LF) { // \n - if (localPreChar != CharUtil.CR) { + if (preChar != CharUtil.CR) { if (copyLen > 0) { - localCurrentField.append(localBuf, localCopyStart, copyLen); + buf.appendTo(currentField, copyLen); } - addField(currentFields, localCurrentField.toStringAndReset()); - localPreChar = c; - localCopyStart = localBufPos; + buf.mark(); + addField(currentFields, currentField.toStringAndReset()); + preChar = c; break; } // 前一个字符是\r,已经处理过这个字段了,此处直接跳过 - localCopyStart = localBufPos; + buf.mark(); } else { + // 普通字符 copyLen++; } } - localPreChar = c; + preChar = c; } // restore fields - bufPos = localBufPos; - preChar = localPreChar; - copyStart = localCopyStart; + this.preChar = preChar; return currentFields; } @@ -298,4 +300,86 @@ public final class CsvParser implements Closeable, Serializable { field = StrUtil.replace(field, "" + textDelimiter + textDelimiter, textDelimiter + ""); currentFields.add(StrUtil.unWrap(field, textDelimiter)); } + + /** + * 内部Buffer + * + * @author looly + */ + private static class Buffer { + final char[] buf; + + /** + * 标记位置,用于读数据 + */ + private int mark; + /** + * 当前位置 + */ + private int position; + /** + * 读取的数据长度,一般小于buf.length,-1表示无数据 + */ + private int limit; + + Buffer(int capacity) { + buf = new char[capacity]; + } + + /** + * 是否还有未读数据 + * + * @return 是否还有未读数据 + */ + public final boolean hasRemaining() { + return position < limit; + } + + /** + * 读取到缓存 + * + * @param reader {@link Reader} + */ + int read(Reader reader) { + int length; + try { + length = reader.read(this.buf); + } catch (IOException e) { + throw new IORuntimeException(e); + } + this.mark = 0; + this.position = 0; + this.limit = length; + return length; + } + + /** + * 先获取当前字符,再将当前位置后移一位
    + * 此方法不检查是否到了数组末尾,请自行使用{@link #hasRemaining()}判断。 + * + * @return 当前位置字符 + * @see #hasRemaining() + */ + char get() { + return this.buf[this.position++]; + } + + /** + * 标记位置记为下次读取位置 + */ + void mark() { + this.mark = this.position; + } + + /** + * 将数据追加到{@link StrBuilder},追加结束后需手动调用{@link #mark()} 重置读取位置 + * + * @param builder {@link StrBuilder} + * @param length 追加的长度 + * @see #mark() + */ + void appendTo(StrBuilder builder, int length) { + builder.append(this.buf, this.mark, length); + } + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvUtilTest.java index 74b81a29c..0ace0b405 100644 --- a/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvUtilTest.java @@ -41,6 +41,12 @@ public class CsvUtilTest { Assert.assertEquals("\"", csvRow.get(6)); }); } + + @Test + public void readTest3() { + CsvReader reader = CsvUtil.getReader(); + reader.read(FileUtil.getUtf8Reader("test.csv"), Console::log); + } @Test @Ignore diff --git a/hutool-core/src/test/resources/test.csv b/hutool-core/src/test/resources/test.csv index 6c6ee2ff4..9c5057d09 100644 --- a/hutool-core/src/test/resources/test.csv +++ b/hutool-core/src/test/resources/test.csv @@ -1 +1,2 @@ +# 这是一行注释,读取时应忽略 "sss,sss",姓名,"性别",关注"对象",年龄,"",""" \ No newline at end of file From d8b1c24305a63c184648d8ad250b5a964b1e9c7f Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 4 Jan 2021 18:08:16 +0800 Subject: [PATCH 33/54] fix code --- hutool-http/src/main/java/cn/hutool/http/HttpRequest.java | 4 ++-- hutool-http/src/test/java/cn/hutool/http/HttpRequestTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java b/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java index 22efdeef7..7d14e0a9a 100644 --- a/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java +++ b/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java @@ -1064,10 +1064,10 @@ public class HttpRequest extends HttpBase { this.httpConnection = HttpConnection .create(this.url.toURL(this.urlHandler), this.proxy)// - .setMethod(this.method)// - .setHttpsInfo(this.hostnameVerifier, this.ssf)// .setConnectTimeout(this.connectionTimeout)// .setReadTimeout(this.readTimeout)// + .setMethod(this.method)// + .setHttpsInfo(this.hostnameVerifier, this.ssf)// // 定义转发 .setInstanceFollowRedirects(this.maxRedirectCount > 0) // 流方式上传数据 diff --git a/hutool-http/src/test/java/cn/hutool/http/HttpRequestTest.java b/hutool-http/src/test/java/cn/hutool/http/HttpRequestTest.java index aabf78763..30036b80c 100644 --- a/hutool-http/src/test/java/cn/hutool/http/HttpRequestTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/HttpRequestTest.java @@ -25,7 +25,7 @@ public class HttpRequestTest { @Test @Ignore public void getHttpsTest() { - String body = HttpRequest.get("https://www.gjifa.com/pc/").execute().body(); + String body = HttpRequest.get("https://www.hutool.cn/").timeout(10).execute().body(); Console.log(body); } From eb59d21431e595a9fff556e96742bbb080fd1a92 Mon Sep 17 00:00:00 2001 From: hjc Date: Mon, 4 Jan 2021 22:44:58 +0800 Subject: [PATCH 34/54] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E6=B7=BB=E5=8A=A0ipv6?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/cn/hutool/core/net/NetUtil.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java b/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java index 910887cd3..0924c2da7 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java @@ -10,6 +10,7 @@ import cn.hutool.core.util.StrUtil; import java.io.IOException; import java.io.OutputStream; +import java.math.BigInteger; import java.net.DatagramSocket; import java.net.HttpCookie; import java.net.IDN; @@ -33,6 +34,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.TreeSet; +import java.util.regex.Pattern; /** * 网络相关工具 @@ -76,6 +78,53 @@ public class NetUtil { return Ipv4Util.ipv4ToLong(strIP); } + /** + * 检测给定的IP字符串符合哪个版本 + * @param ipStr 需要检测的字符串 + * @return 版本号['IPv4', 'IPv6', 'Neither'] + */ + public static String getIpVersion(String ipStr) { + Pattern patternIpv4 = Pattern.compile("^(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$"); + Pattern patternIpv6 = Pattern.compile("^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:)|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}(:[0-9A-Fa-f]{1,4}){1,2})|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){1,3})|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){1,4})|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){1,5})|([0-9A-Fa-f]{1,4}:(:[0-9A-Fa-f]{1,4}){1,6})|(:(:[0-9A-Fa-f]{1,4}){1,7})|(([0-9A-Fa-f]{1,4}:){6}(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){5}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){0,1}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|([0-9A-Fa-f]{1,4}:(:[0-9A-Fa-f]{1,4}){0,4}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(:(:[0-9A-Fa-f]{1,4}){0,5}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}))$"); + if (patternIpv6.matcher(ipStr).matches()) { + return "IPv6"; + } else if (patternIpv4.matcher(ipStr).matches()) { + return "IPv4"; + } else { + return "Neither"; + } + } + + /** + * 将IPv6地址字符串转为大整数 + * + * @param IPv6Str 字符串 + * @return 大整数, 如发生异常返回 null + */ + public static BigInteger ipv6ToBitInteger(String IPv6Str) { + try { + InetAddress address = InetAddress.getByName(IPv6Str); + if (address instanceof Inet6Address) { + return new BigInteger(1, address.getAddress()); + } + } catch (UnknownHostException e) {} + return null; + } + + /** + * 将大整数转换成ipv6字符串 + * + * @param bigInteger 大整数 + * @return IPv6字符串, 如发生异常返回 null + */ + public static String bigIntegerToIPv6(BigInteger bigInteger) { + try { + String ipv6 = InetAddress.getByAddress(bigInteger.toByteArray()).toString().substring(1); + return ipv6; + } catch (UnknownHostException e) {} + return null; + } + /** * 检测本地端口可用性
    * 来自org.springframework.util.SocketUtils From e90e168c00593a0584f21cb5387a60b2ad9a8e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E8=89=AF?= <841369634@qq.com> Date: Tue, 5 Jan 2021 14:24:54 +0800 Subject: [PATCH 35/54] optimize: exclude all `pom.xml` from `hutool-all.jar` --- hutool-all/pom.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index 3ad19382f..000c18a44 100644 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -130,6 +130,14 @@ ${project.groupId}:*:* + + + *:* + + META-INF/maven/** + + + From b13ec78f61668b12eae852a8664ca85b92ac9b85 Mon Sep 17 00:00:00 2001 From: dimples <1126834403@qq.com> Date: Wed, 6 Jan 2021 00:30:06 +0800 Subject: [PATCH 36/54] =?UTF-8?q?Window=20FTP=E6=9C=8D=E5=8A=A1=E5=99=A8?= =?UTF-8?q?=E4=B8=8A=E4=B8=8B=E8=BD=BD=E5=B8=A6=E4=B8=AD=E6=96=87=E7=9A=84?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E7=BB=93=E6=9E=9C=E4=B8=BA=E7=A9=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/cn/hutool/extra/ftp/Ftp.java | 70 ++++++++++++++++--- .../java/cn/hutool/extra/ftp/FtpConfig.java | 33 ++++++++- 2 files changed, 91 insertions(+), 12 deletions(-) diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java b/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java index 2ae68c917..059c09349 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java @@ -1,13 +1,7 @@ package cn.hutool.extra.ftp; -import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.lang.Filter; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.CharsetUtil; -import cn.hutool.core.util.StrUtil; import org.apache.commons.net.ftp.FTPClient; +import org.apache.commons.net.ftp.FTPClientConfig; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPReply; @@ -16,9 +10,18 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.Filter; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.StrUtil; + /** * FTP客户端封装
    * 此客户端基于Apache-Commons-Net @@ -81,7 +84,22 @@ public class Ftp extends AbstractFtp { * @param charset 编码 */ public Ftp(String host, int port, String user, String password, Charset charset) { - this(host, port, user, password, charset, null); + this(host, port, user, password, charset,null, null, null); + } + + /** + * 构造 + * + * @param host 域名或IP + * @param port 端口 + * @param user 用户名 + * @param password 密码 + * @param charset 编码 + * @param serverLanguageCode 服务器语言 例如:zh + * @param systemKey 服务器标识 例如:org.apache.commons.net.ftp.FTPClientConfig.SYST_NT + */ + public Ftp(String host, int port, String user, String password, Charset charset, String serverLanguageCode, String systemKey) { + this(host, port, user, password, charset, serverLanguageCode, systemKey, null); } /** @@ -94,8 +112,8 @@ public class Ftp extends AbstractFtp { * @param charset 编码 * @param mode 模式 */ - public Ftp(String host, int port, String user, String password, Charset charset, FtpMode mode) { - this(new FtpConfig(host, port, user, password, charset), mode); + public Ftp(String host, int port, String user, String password, Charset charset, String serverLanguageCode, String systemKey, FtpMode mode) { + this(new FtpConfig(host, port, user, password, charset, serverLanguageCode, systemKey), mode); } /** @@ -143,7 +161,7 @@ public class Ftp extends AbstractFtp { * @return this */ public Ftp init(String host, int port, String user, String password, FtpMode mode) { - return init(new FtpConfig(host, port, user, password, this.ftpConfig.getCharset()), mode); + return init(new FtpConfig(host, port, user, password, this.ftpConfig.getCharset(), null, null), mode); } /** @@ -161,6 +179,11 @@ public class Ftp extends AbstractFtp { // 连接ftp服务器 client.connect(config.getHost(), config.getPort()); client.setSoTimeout((int) config.getSoTimeout()); + // 下载中文文件 + if (StrUtil.isNotBlank(config.getSystemKey()) && StrUtil.isNotBlank(config.getServerLanguageCode())){ + FTPClientConfig conf = new FTPClientConfig(config.getSystemKey()); + conf.setServerLanguageCode(config.getServerLanguageCode()); + } // 登录ftp服务器 client.login(config.getUser(), config.getPassword()); } catch (IOException e) { @@ -597,6 +620,31 @@ public class Ftp extends AbstractFtp { } } + /** + * 下载文件到输出流 + * + * @param path 文件路径 + * @param fileName 文件名 + * @param out 输出位置 + */ + public void download(String path, String fileName, OutputStream out, String fileNameCharset) { + String pwd = null; + if (this.backToPwd) { + pwd = pwd(); + } + + cd(path); + try { + client.setFileType(FTPClient.BINARY_FILE_TYPE); + client.retrieveFile(new String(fileName.getBytes(fileNameCharset), StandardCharsets.ISO_8859_1), out); + } catch (IOException e) { + throw new FtpException(e); + } finally { + if (backToPwd) { + cd(pwd); + } + } + } /** * 获取FTPClient客户端对象 * diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ftp/FtpConfig.java b/hutool-extra/src/main/java/cn/hutool/extra/ftp/FtpConfig.java index f87d494d0..d5bb25a69 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/ftp/FtpConfig.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/ftp/FtpConfig.java @@ -46,6 +46,17 @@ public class FtpConfig implements Serializable { */ private long soTimeout; + /** + * 设置服务器语言 + */ + private String serverLanguageCode; + + /** + * 设置服务器系统关键词 + * @see org.apache.commons.net.ftp.FTPClientConfig + */ + private String systemKey; + /** * 构造 */ @@ -61,12 +72,14 @@ public class FtpConfig implements Serializable { * @param password 密码 * @param charset 编码 */ - public FtpConfig(String host, int port, String user, String password, Charset charset) { + public FtpConfig(String host, int port, String user, String password, Charset charset, String serverLanguageCode, String systemKey) { this.host = host; this.port = port; this.user = user; this.password = password; this.charset = charset; + this.serverLanguageCode = serverLanguageCode; + this.systemKey = systemKey; } public String getHost() { @@ -131,4 +144,22 @@ public class FtpConfig implements Serializable { this.soTimeout = soTimeout; return this; } + + public String getServerLanguageCode() { + return serverLanguageCode; + } + + public FtpConfig setServerLanguageCode(String serverLanguageCode) { + this.serverLanguageCode = serverLanguageCode; + return this; + } + + public String getSystemKey() { + return systemKey; + } + + public FtpConfig setSystemKey(String systemKey) { + this.systemKey = systemKey; + return this; + } } From 2effcb4c0e39cda501800b42531cad2387f491a2 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 6 Jan 2021 11:42:47 +0800 Subject: [PATCH 37/54] add method for #I2C42H --- CHANGELOG.md | 3 +- .../main/java/cn/hutool/setting/Setting.java | 31 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ca63c2ce..53fc15f21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------------------------------------- -# 5.5.7 (2021-01-03) +# 5.5.7 (2021-01-06) ### 新特性 * 【core 】 DynaBean.create增加重载方法(pr#245@Gitee) @@ -11,6 +11,7 @@ * 【poi 】 SheetRidReader增加getRidByIndex方法(issue#1342@Github) * 【extra 】 MailAccount增加sslProtocols配置项(issue#IZN95@Gitee) * 【extra 】 MailUtil增加getSession方法 +* 【setting】 新增setByGroup和putByGroup,set和put标记为过期(issue#I2C42H@Gitee) ### Bug修复 * 【core 】 修复CsvReader读取双引号未转义问题(issur#I2BMP1@Gitee) diff --git a/hutool-setting/src/main/java/cn/hutool/setting/Setting.java b/hutool-setting/src/main/java/cn/hutool/setting/Setting.java index 44eaff7ce..8f0d3a88b 100644 --- a/hutool-setting/src/main/java/cn/hutool/setting/Setting.java +++ b/hutool-setting/src/main/java/cn/hutool/setting/Setting.java @@ -519,11 +519,25 @@ public class Setting extends AbsSetting implements Map { * @param key 键 * @param value 值 * @return 此key之前存在的值,如果没有返回null + * @deprecated 此方法与getXXX参数顺序不一致容易造成问题,建议使用{@link #putByGroup(String, String, String)} */ + @Deprecated public String put(String group, String key, String value) { return this.groupedMap.put(group, key, value); } + /** + * 将键值对加入到对应分组中 + * + * @param key 键 + * @param group 分组 + * @param value 值 + * @return 此key之前存在的值,如果没有返回null + */ + public String putByGroup(String key, String group, String value) { + return this.groupedMap.put(group, key, value); + } + /** * 从指定分组中删除指定值 * @@ -622,12 +636,29 @@ public class Setting extends AbsSetting implements Map { * @param key 键 * @param value 值 * @return 此key之前存在的值,如果没有返回null + * @deprecated 此方法与getXXX参数顺序不一致容易引起,请使用{@link #setByGroup(String, String, String)} */ + @Deprecated public Setting set(String group, String key, String value) { this.put(group, key, value); return this; } + /** + * 将键值对加入到对应分组中
    + * 此方法用于与getXXX统一参数顺序 + * + * @param key 键 + * @param group 分组 + * @param value 值 + * @return 此key之前存在的值,如果没有返回null + * @since 5.5.7 + */ + public Setting setByGroup(String key, String group, String value) { + this.putByGroup(key, group, value); + return this; + } + // ------------------------------------------------- Override Map interface @Override public boolean isEmpty() { From 19f39309be90f3c376bfdf50f7c4c1444dd15bb6 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 6 Jan 2021 16:01:48 +0800 Subject: [PATCH 38/54] fix code --- CHANGELOG.md | 2 ++ .../java/cn/hutool/crypto/symmetric/SymmetricAlgorithm.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53fc15f21..aadac2683 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ * 【extra 】 MailAccount增加sslProtocols配置项(issue#IZN95@Gitee) * 【extra 】 MailUtil增加getSession方法 * 【setting】 新增setByGroup和putByGroup,set和put标记为过期(issue#I2C42H@Gitee) +* 【crypto 】 修改SymmetricAlgorithm注释(issue#1360@Github) +* 【all 】 pom中将META-INF/maven下全部exclude(pr#1355@Github) ### Bug修复 * 【core 】 修复CsvReader读取双引号未转义问题(issur#I2BMP1@Gitee) diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/SymmetricAlgorithm.java b/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/SymmetricAlgorithm.java index bedc93327..fa1dda559 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/SymmetricAlgorithm.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/SymmetricAlgorithm.java @@ -8,7 +8,7 @@ package cn.hutool.crypto.symmetric; * */ public enum SymmetricAlgorithm { - /** 默认的AES加密方式:AES/CBC/PKCS5Padding */ + /** 默认的AES加密方式:AES/ECB/PKCS5Padding */ AES("AES"), ARCFOUR("ARCFOUR"), Blowfish("Blowfish"), From 2a89327d182d9f438b043ace4be7e65f1c28c6bd Mon Sep 17 00:00:00 2001 From: dimples <1126834403@qq.com> Date: Wed, 6 Jan 2021 19:19:02 +0800 Subject: [PATCH 39/54] =?UTF-8?q?FTP=E4=B8=8B=E8=BD=BD=E4=B8=AD=E6=96=87?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java b/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java index 059c09349..3294d39af 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java @@ -84,7 +84,7 @@ public class Ftp extends AbstractFtp { * @param charset 编码 */ public Ftp(String host, int port, String user, String password, Charset charset) { - this(host, port, user, password, charset,null, null, null); + this(host, port, user, password, charset,null, null); } /** From 1deed5d9cfe3d8acddef0f64d97c0b9d2b399a00 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 7 Jan 2021 09:16:47 +0800 Subject: [PATCH 40/54] fix test --- CHANGELOG.md | 1 + .../main/java/cn/hutool/core/net/NetUtil.java | 39 ++++++------------- .../java/cn/hutool/core/io/FileUtilTest.java | 3 ++ 3 files changed, 16 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aadac2683..d157fe8e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ * 【setting】 新增setByGroup和putByGroup,set和put标记为过期(issue#I2C42H@Gitee) * 【crypto 】 修改SymmetricAlgorithm注释(issue#1360@Github) * 【all 】 pom中将META-INF/maven下全部exclude(pr#1355@Github) +* 【core 】 pom中将META-INF/maven下全部exclude(pr#1355@Github) ### Bug修复 * 【core 】 修复CsvReader读取双引号未转义问题(issur#I2BMP1@Gitee) diff --git a/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java b/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java index 0924c2da7..0797b1677 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java @@ -34,7 +34,6 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.TreeSet; -import java.util.regex.Pattern; /** * 网络相关工具 @@ -78,28 +77,12 @@ public class NetUtil { return Ipv4Util.ipv4ToLong(strIP); } - /** - * 检测给定的IP字符串符合哪个版本 - * @param ipStr 需要检测的字符串 - * @return 版本号['IPv4', 'IPv6', 'Neither'] - */ - public static String getIpVersion(String ipStr) { - Pattern patternIpv4 = Pattern.compile("^(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$"); - Pattern patternIpv6 = Pattern.compile("^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:)|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}(:[0-9A-Fa-f]{1,4}){1,2})|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){1,3})|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){1,4})|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){1,5})|([0-9A-Fa-f]{1,4}:(:[0-9A-Fa-f]{1,4}){1,6})|(:(:[0-9A-Fa-f]{1,4}){1,7})|(([0-9A-Fa-f]{1,4}:){6}(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){5}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){0,1}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|([0-9A-Fa-f]{1,4}:(:[0-9A-Fa-f]{1,4}){0,4}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(:(:[0-9A-Fa-f]{1,4}){0,5}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}))$"); - if (patternIpv6.matcher(ipStr).matches()) { - return "IPv6"; - } else if (patternIpv4.matcher(ipStr).matches()) { - return "IPv4"; - } else { - return "Neither"; - } - } - /** * 将IPv6地址字符串转为大整数 * * @param IPv6Str 字符串 * @return 大整数, 如发生异常返回 null + * @since 5.5.7 */ public static BigInteger ipv6ToBitInteger(String IPv6Str) { try { @@ -107,7 +90,8 @@ public class NetUtil { if (address instanceof Inet6Address) { return new BigInteger(1, address.getAddress()); } - } catch (UnknownHostException e) {} + } catch (UnknownHostException ignore) { + } return null; } @@ -116,13 +100,14 @@ public class NetUtil { * * @param bigInteger 大整数 * @return IPv6字符串, 如发生异常返回 null + * @since 5.5.7 */ public static String bigIntegerToIPv6(BigInteger bigInteger) { try { - String ipv6 = InetAddress.getByAddress(bigInteger.toByteArray()).toString().substring(1); - return ipv6; - } catch (UnknownHostException e) {} - return null; + return InetAddress.getByAddress(bigInteger.toByteArray()).toString().substring(1); + } catch (UnknownHostException ignore) { + return null; + } } /** @@ -561,7 +546,7 @@ public class NetUtil { byte[] mac = null; try { final NetworkInterface networkInterface = NetworkInterface.getByInetAddress(inetAddress); - if(null != networkInterface){ + if (null != networkInterface) { mac = networkInterface.getHardwareAddress(); } } catch (SocketException e) { @@ -596,9 +581,9 @@ public class NetUtil { } final InetAddress localhost = getLocalhost(); - if(null != localhost){ + if (null != localhost) { String name = localhost.getHostName(); - if(StrUtil.isEmpty(name)){ + if (StrUtil.isEmpty(name)) { name = localhost.getHostAddress(); } localhostName = name; @@ -787,7 +772,7 @@ public class NetUtil { * @since 5.3.2 */ public static boolean isOpen(InetSocketAddress address, int timeout) { - try (Socket sc = new Socket()){ + try (Socket sc = new Socket()) { sc.connect(address, timeout); return true; } catch (Exception e) { diff --git a/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java index 68c0a955c..6cfafe7bb 100644 --- a/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java @@ -377,6 +377,9 @@ public class FileUtilTest { String mimeType = FileUtil.getMimeType("test2Write.jpg"); Assert.assertEquals("image/jpeg", mimeType); + mimeType = FileUtil.getMimeType("test2Write.html"); + Assert.assertEquals("text/html", mimeType); + mimeType = FileUtil.getMimeType("main.css"); Assert.assertEquals("text/css", mimeType); From 0e31ba2fc59f337b2daea877c69b2d32b7f4f6a9 Mon Sep 17 00:00:00 2001 From: bwcx_jzy Date: Thu, 7 Jan 2021 11:24:05 +0800 Subject: [PATCH 41/54] =?UTF-8?q?CollUtil.forEach=20=E5=A2=9E=E5=8A=A0null?= =?UTF-8?q?=20=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/hutool/core/collection/CollUtil.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java index 7f629bc0f..01f6c0bea 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java @@ -2560,6 +2560,9 @@ public class CollUtil { * @since 5.4.7 */ public static void forEach(Iterable iterable, Consumer consumer) { + if(iterable == null){ + return; + } forEach(iterable.iterator(), consumer); } @@ -2571,6 +2574,9 @@ public class CollUtil { * @param consumer {@link Consumer} 遍历的每条数据处理器 */ public static void forEach(Iterator iterator, Consumer consumer) { + if(iterator == null){ + return; + } int index = 0; while (iterator.hasNext()) { consumer.accept(iterator.next(), index); @@ -2586,6 +2592,9 @@ public class CollUtil { * @param consumer {@link Consumer} 遍历的每条数据处理器 */ public static void forEach(Enumeration enumeration, Consumer consumer) { + if(enumeration == null){ + return; + } int index = 0; while (enumeration.hasMoreElements()) { consumer.accept(enumeration.nextElement(), index); @@ -2603,6 +2612,9 @@ public class CollUtil { * @param kvConsumer {@link KVConsumer} 遍历的每条数据处理器 */ public static void forEach(Map map, KVConsumer kvConsumer) { + if(map == null){ + return; + } int index = 0; for (Entry entry : map.entrySet()) { kvConsumer.accept(entry.getKey(), entry.getValue(), index); From 0800ffe1e5579d1f53cce58c9942062143a57531 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 7 Jan 2021 17:09:16 +0800 Subject: [PATCH 42/54] fix json.parse bug #1363 --- CHANGELOG.md | 3 ++- .../src/main/java/cn/hutool/http/server/SimpleServer.java | 5 +++++ .../java/cn/hutool/http/server/handler/package-info.java | 4 ++++ .../test/java/cn/hutool/http/server/SimpleServerTest.java | 4 ++++ hutool-json/src/main/java/cn/hutool/json/JSONUtil.java | 2 +- 5 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 hutool-http/src/main/java/cn/hutool/http/server/handler/package-info.java diff --git a/CHANGELOG.md b/CHANGELOG.md index d157fe8e9..9d44a4d0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------------------------------------- -# 5.5.7 (2021-01-06) +# 5.5.7 (2021-01-07) ### 新特性 * 【core 】 DynaBean.create增加重载方法(pr#245@Gitee) @@ -18,6 +18,7 @@ ### Bug修复 * 【core 】 修复CsvReader读取双引号未转义问题(issur#I2BMP1@Gitee) +* 【json 】 JSONUtil.parse修复config无效问题(issur#1363@Github) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-http/src/main/java/cn/hutool/http/server/SimpleServer.java b/hutool-http/src/main/java/cn/hutool/http/server/SimpleServer.java index f62141613..8af896aad 100644 --- a/hutool-http/src/main/java/cn/hutool/http/server/SimpleServer.java +++ b/hutool-http/src/main/java/cn/hutool/http/server/SimpleServer.java @@ -2,6 +2,8 @@ package cn.hutool.http.server; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.lang.Console; +import cn.hutool.core.thread.GlobalThreadPool; +import cn.hutool.core.util.StrUtil; import cn.hutool.http.server.action.Action; import cn.hutool.http.server.action.RootAction; import cn.hutool.http.server.handler.ActionHandler; @@ -53,6 +55,7 @@ public class SimpleServer { } catch (IOException e) { throw new IORuntimeException(e); } + setExecutor(GlobalThreadPool.getExecutor()); } /** @@ -63,6 +66,8 @@ public class SimpleServer { * @return this */ public SimpleServer addHandler(String path, HttpHandler handler) { + // 非/开头的路径会报错 + path = StrUtil.addPrefixIfNot(path, StrUtil.SLASH); this.server.createContext(path, handler); return this; } diff --git a/hutool-http/src/main/java/cn/hutool/http/server/handler/package-info.java b/hutool-http/src/main/java/cn/hutool/http/server/handler/package-info.java new file mode 100644 index 000000000..9c88626c2 --- /dev/null +++ b/hutool-http/src/main/java/cn/hutool/http/server/handler/package-info.java @@ -0,0 +1,4 @@ +/** + * {@link com.sun.net.httpserver.HttpHandler} 实现包装 + */ +package cn.hutool.http.server.handler; \ No newline at end of file diff --git a/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java b/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java index bca649874..fc06d0db8 100644 --- a/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java @@ -45,6 +45,10 @@ public class SimpleServerTest { response.write(request.getMultipart().getParamMap().toString(), ContentType.TEXT_PLAIN.toString()); } ) + .addAction("test/zeroStr", (req, res)->{ + res.addHeader("Content-Length", "0".length() + ""); + res.write("0"); + }) .start(); } } diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java b/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java index 3afa65cc2..1715f9a4e 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java @@ -218,7 +218,7 @@ public final class JSONUtil { json = (JSON) obj; } else if (obj instanceof CharSequence) { final String jsonStr = StrUtil.trim((CharSequence) obj); - json = StrUtil.startWith(jsonStr, '[') ? parseArray(jsonStr) : parseObj(jsonStr); + json = isJsonArray(jsonStr) ? parseArray(jsonStr, config) : parseObj(jsonStr, config); } else if (obj instanceof Iterable || obj instanceof Iterator || ArrayUtil.isArray(obj)) {// 列表 json = new JSONArray(obj, config); } else {// 对象 From c9a180abce0117b926a1e10aa8a1edc13ea71e23 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 7 Jan 2021 17:43:19 +0800 Subject: [PATCH 43/54] fix bug for #1358 --- CHANGELOG.md | 1 + .../http/server/HttpServerResponse.java | 73 ++++++++++++++++--- .../hutool/http/server/SimpleServerTest.java | 6 +- .../java/cn/hutool/json/JSONUtilTest.java | 9 +++ 4 files changed, 76 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d44a4d0e..78f6d9d03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ ### Bug修复 * 【core 】 修复CsvReader读取双引号未转义问题(issur#I2BMP1@Gitee) * 【json 】 JSONUtil.parse修复config无效问题(issur#1363@Github) +* 【http 】 修复SimpleServer返回响应内容Content-Lenth不正确的问题(issur#1358@Github) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-http/src/main/java/cn/hutool/http/server/HttpServerResponse.java b/hutool-http/src/main/java/cn/hutool/http/server/HttpServerResponse.java index 848250d15..fe19c206f 100644 --- a/hutool-http/src/main/java/cn/hutool/http/server/HttpServerResponse.java +++ b/hutool-http/src/main/java/cn/hutool/http/server/HttpServerResponse.java @@ -46,7 +46,7 @@ public class HttpServerResponse extends HttpServerBase { } /** - * 发送HTTP状态码 + * 发送HTTP状态码,Content-Length为0不定长度,会输出Transfer-encoding: chunked * * @param httpStatusCode HTTP状态码,见HttpStatus * @return this @@ -64,6 +64,17 @@ public class HttpServerResponse extends HttpServerBase { return send(HttpStatus.HTTP_OK); } + /** + * 发送成功状态码 + * + * @param bodyLength 响应体长度,默认0表示不定长度,会输出Transfer-encoding: chunked + * @return this + * @since 5.5.7 + */ + public HttpServerResponse sendOk(int bodyLength) { + return send(HttpStatus.HTTP_OK, bodyLength); + } + /** * 发送404错误页 * @@ -91,7 +102,7 @@ public class HttpServerResponse extends HttpServerBase { * 发送HTTP状态码 * * @param httpStatusCode HTTP状态码,见HttpStatus - * @param bodyLength 响应体长度,默认0 + * @param bodyLength 响应体长度,默认0表示不定长度,会输出Transfer-encoding: chunked * @return this */ public HttpServerResponse send(int httpStatusCode, long bodyLength) { @@ -290,7 +301,8 @@ public class HttpServerResponse extends HttpServerBase { * @return this */ public HttpServerResponse write(byte[] data) { - return write(new ByteArrayInputStream(data)); + final ByteArrayInputStream in = new ByteArrayInputStream(data); + return write(in, in.available()); } /** @@ -302,8 +314,21 @@ public class HttpServerResponse extends HttpServerBase { * @since 5.2.6 */ public HttpServerResponse write(InputStream in, String contentType) { + return write(in, 0, contentType); + } + + /** + * 返回数据给客户端 + * + * @param in 需要返回客户端的内容 + * @param length 内容长度,默认0表示不定长度,会输出Transfer-encoding: chunked + * @param contentType 返回的类型 + * @return this + * @since 5.2.7 + */ + public HttpServerResponse write(InputStream in, int length, String contentType) { setContentType(contentType); - return write(in); + return write(in, length); } /** @@ -313,9 +338,23 @@ public class HttpServerResponse extends HttpServerBase { * @return this */ public HttpServerResponse write(InputStream in) { + return write(in, 0); + } + + /** + * 写出数据到客户端 + * + * @param in 数据流 + * @param length 指定响应内容长度,默认0表示不定长度,会输出Transfer-encoding: chunked + * @return this + */ + public HttpServerResponse write(InputStream in, int length) { + if (false == isSendCode) { + sendOk(Math.max(0, length)); + } OutputStream out = null; try { - out = getOut(); + out = this.httpExchange.getResponseBody(); IoUtil.copy(in, out); } finally { IoUtil.close(out); @@ -332,12 +371,16 @@ public class HttpServerResponse extends HttpServerBase { * @since 5.2.6 */ public HttpServerResponse write(File file) { + final long fileSize = file.length(); + if(fileSize > Integer.MAX_VALUE){ + throw new IllegalArgumentException("File size is too bigger than " + Integer.MAX_VALUE); + } final String fileName = file.getName(); final String contentType = ObjectUtil.defaultIfNull(HttpUtil.getMimeType(fileName), "application/octet-stream"); BufferedInputStream in = null; try { in = FileUtil.getInputStream(file); - write(in, contentType, fileName); + write(in, (int)fileSize, contentType, fileName); } finally { IoUtil.close(in); } @@ -352,13 +395,25 @@ public class HttpServerResponse extends HttpServerBase { * @param fileName 文件名 * @since 5.2.6 */ - public void write(InputStream in, String contentType, String fileName) { + public void write(InputStream in, String contentType, String fileName) { + write(in, 0, contentType, fileName); + } + + /** + * 返回文件数据给客户端(文件下载) + * + * @param in 需要返回客户端的内容 + * @param contentType 返回的类型 + * @param fileName 文件名 + * @since 5.2.7 + */ + public HttpServerResponse write(InputStream in, int length, String contentType, String fileName) { final Charset charset = ObjectUtil.defaultIfNull(this.charset, DEFAULT_CHARSET); - if(false == contentType.startsWith("text/")){ + if (false == contentType.startsWith("text/")) { // 非文本类型数据直接走下载 setHeader(Header.CONTENT_DISPOSITION, StrUtil.format("attachment;filename={}", URLUtil.encode(fileName, charset))); } - write(in, contentType); + return write(in, length, contentType); } } diff --git a/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java b/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java index fc06d0db8..a16c96a1a 100644 --- a/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java @@ -45,10 +45,8 @@ public class SimpleServerTest { response.write(request.getMultipart().getParamMap().toString(), ContentType.TEXT_PLAIN.toString()); } ) - .addAction("test/zeroStr", (req, res)->{ - res.addHeader("Content-Length", "0".length() + ""); - res.write("0"); - }) + // 测试输出响应内容是否能正常返回Content-Length头信息 + .addAction("test/zeroStr", (req, res)-> res.write("0")) .start(); } } diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java index 4d599d1c0..9dcd583cc 100644 --- a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java @@ -10,6 +10,7 @@ import cn.hutool.json.test.bean.UserC; import org.junit.Assert; import org.junit.Test; +import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -163,6 +164,14 @@ public class JSONUtilTest { Assert.assertEquals("12.00", jsonObject.getBigDecimal("test").setScale(2).toString()); } + @Test + public void doubleTest2() { + String json = "{\"test\": 12.00}"; + final JSONObject jsonObject = JSONUtil.parseObj(json); + jsonObject.set("test2", new BigInteger("12")); + Console.log(jsonObject); + } + @Test public void parseObjTest() { // 测试转义 From 0a768ad2c6f3448759bdd3027225c2d461161908 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 7 Jan 2021 21:06:05 +0800 Subject: [PATCH 44/54] add filter --- CHANGELOG.md | 8 +- .../cn/hutool/http/server/HttpServerBase.java | 11 ++ .../cn/hutool/http/server/SimpleServer.java | 101 ++++++++++++++++-- .../hutool/http/server/filter/HttpFilter.java | 26 +++++ .../http/server/filter/SimpleFilter.java | 17 +++ .../http/server/filter/package-info.java | 4 + .../hutool/http/server/SimpleServerTest.java | 9 +- 7 files changed, 165 insertions(+), 11 deletions(-) create mode 100644 hutool-http/src/main/java/cn/hutool/http/server/filter/HttpFilter.java create mode 100644 hutool-http/src/main/java/cn/hutool/http/server/filter/SimpleFilter.java create mode 100644 hutool-http/src/main/java/cn/hutool/http/server/filter/package-info.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 78f6d9d03..0fd0102d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,12 +14,12 @@ * 【setting】 新增setByGroup和putByGroup,set和put标记为过期(issue#I2C42H@Gitee) * 【crypto 】 修改SymmetricAlgorithm注释(issue#1360@Github) * 【all 】 pom中将META-INF/maven下全部exclude(pr#1355@Github) -* 【core 】 pom中将META-INF/maven下全部exclude(pr#1355@Github) +* 【http 】 SimpleServer中增加addFilter等方法,并使用全局线程池 ### Bug修复 -* 【core 】 修复CsvReader读取双引号未转义问题(issur#I2BMP1@Gitee) -* 【json 】 JSONUtil.parse修复config无效问题(issur#1363@Github) -* 【http 】 修复SimpleServer返回响应内容Content-Lenth不正确的问题(issur#1358@Github) +* 【core 】 修复CsvReader读取双引号未转义问题(issue#I2BMP1@Gitee) +* 【json 】 JSONUtil.parse修复config无效问题(issue#1363@Github) +* 【http 】 修复SimpleServer返回响应内容Content-Length不正确的问题(issue#1358@Github) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-http/src/main/java/cn/hutool/http/server/HttpServerBase.java b/hutool-http/src/main/java/cn/hutool/http/server/HttpServerBase.java index ff146ff89..d0b425e39 100644 --- a/hutool-http/src/main/java/cn/hutool/http/server/HttpServerBase.java +++ b/hutool-http/src/main/java/cn/hutool/http/server/HttpServerBase.java @@ -1,6 +1,7 @@ package cn.hutool.http.server; import cn.hutool.core.util.CharsetUtil; +import com.sun.net.httpserver.HttpContext; import com.sun.net.httpserver.HttpExchange; import java.nio.charset.Charset; @@ -34,4 +35,14 @@ public class HttpServerBase { public HttpExchange getHttpExchange() { return this.httpExchange; } + + /** + * 获取{@link HttpContext} + * + * @return {@link HttpContext} + * @since 5.5.7 + */ + public HttpContext getHttpContext() { + return getHttpExchange().getHttpContext(); + } } diff --git a/hutool-http/src/main/java/cn/hutool/http/server/SimpleServer.java b/hutool-http/src/main/java/cn/hutool/http/server/SimpleServer.java index 8af896aad..bf2fe3157 100644 --- a/hutool-http/src/main/java/cn/hutool/http/server/SimpleServer.java +++ b/hutool-http/src/main/java/cn/hutool/http/server/SimpleServer.java @@ -6,13 +6,22 @@ import cn.hutool.core.thread.GlobalThreadPool; import cn.hutool.core.util.StrUtil; import cn.hutool.http.server.action.Action; import cn.hutool.http.server.action.RootAction; +import cn.hutool.http.server.filter.HttpFilter; +import cn.hutool.http.server.filter.SimpleFilter; import cn.hutool.http.server.handler.ActionHandler; +import com.sun.net.httpserver.Filter; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsServer; import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.Executor; /** @@ -23,7 +32,8 @@ import java.util.concurrent.Executor; */ public class SimpleServer { - HttpServer server; + private final HttpServer server; + private final List filters; /** * 构造 @@ -50,26 +60,105 @@ public class SimpleServer { * @param address 监听地址 */ public SimpleServer(InetSocketAddress address) { + this(address, null); + } + + /** + * 构造 + * + * @param address 监听地址 + * @param configurator https配置信息,用于使用自定义SSL(TLS)证书等 + */ + public SimpleServer(InetSocketAddress address, HttpsConfigurator configurator) { try { - this.server = HttpServer.create(address, 0); + if(null != configurator){ + final HttpsServer server = HttpsServer.create(address, 0); + server.setHttpsConfigurator(configurator); + this.server = server; + } else{ + this.server = HttpServer.create(address, 0); + } } catch (IOException e) { throw new IORuntimeException(e); } setExecutor(GlobalThreadPool.getExecutor()); + filters = new ArrayList<>(); + } + + /** + * 增加请求过滤器,此过滤器对所有请求有效
    + * 此方法需在以下方法前之前调用: + * + *
      + *
    • {@link #setRoot(File)}
    • + *
    • {@link #setRoot(String)}
    • + *
    • {@link #createContext(String, HttpHandler)}
    • + *
    • {@link #addHandler(String, HttpHandler)}
    • + *
    • {@link #addAction(String, Action)}
    • + *
    + * + * @param filter {@link Filter} 请求过滤器 + * @return this + * @since 5.5.7 + */ + public SimpleServer addFilter(Filter filter) { + this.filters.add(filter); + return this; + } + + /** + * 增加请求过滤器,此过滤器对所有请求有效
    + * 此方法需在以下方法前之前调用: + * + *
      + *
    • {@link #setRoot(File)}
    • + *
    • {@link #setRoot(String)}
    • + *
    • {@link #createContext(String, HttpHandler)}
    • + *
    • {@link #addHandler(String, HttpHandler)}
    • + *
    • {@link #addAction(String, Action)}
    • + *
    + * + * @param filter {@link Filter} 请求过滤器 + * @return this + * @since 5.5.7 + */ + public SimpleServer addFilter(HttpFilter filter) { + return addFilter(new SimpleFilter() { + @Override + public void doFilter(HttpExchange httpExchange, Chain chain) throws IOException { + filter.doFilter(new HttpServerRequest(httpExchange), new HttpServerResponse(httpExchange), chain); + } + }); } /** * 增加请求处理规则 * - * @param path 路径 - * @param handler 处理器 + * @param path 路径,例如:/a/b 或者 a/b + * @param handler 处理器,包括请求和响应处理 * @return this + * @see #createContext(String, HttpHandler) */ public SimpleServer addHandler(String path, HttpHandler handler) { + createContext(path, handler); + return this; + } + + /** + * 创建请求映射上下文,创建后,用户访问指定路径可使用{@link HttpHandler} 中的规则进行处理 + * + * @param path 路径,例如:/a/b 或者 a/b + * @param handler 处理器,包括请求和响应处理 + * @return {@link HttpContext} + * @since 5.5.7 + */ + public HttpContext createContext(String path, HttpHandler handler) { // 非/开头的路径会报错 path = StrUtil.addPrefixIfNot(path, StrUtil.SLASH); - this.server.createContext(path, handler); - return this; + final HttpContext context = this.server.createContext(path, handler); + // 增加整体过滤器 + context.getFilters().addAll(this.filters); + return context; } /** diff --git a/hutool-http/src/main/java/cn/hutool/http/server/filter/HttpFilter.java b/hutool-http/src/main/java/cn/hutool/http/server/filter/HttpFilter.java new file mode 100644 index 000000000..1b65d7af2 --- /dev/null +++ b/hutool-http/src/main/java/cn/hutool/http/server/filter/HttpFilter.java @@ -0,0 +1,26 @@ +package cn.hutool.http.server.filter; + +import cn.hutool.http.server.HttpServerRequest; +import cn.hutool.http.server.HttpServerResponse; +import com.sun.net.httpserver.Filter; + +import java.io.IOException; + +/** + * 过滤器接口,用于简化{@link Filter} 使用 + * + * @author looly + * @since 5.5.7 + */ +@FunctionalInterface +public interface HttpFilter { + + /** + * 执行过滤 + * @param req {@link HttpServerRequest} 请求对象,用于获取请求内容 + * @param res {@link HttpServerResponse} 响应对象,用于写出内容 + * @param chain {@link Filter.Chain} + * @throws IOException IO异常 + */ + void doFilter(HttpServerRequest req, HttpServerResponse res, Filter.Chain chain) throws IOException; +} diff --git a/hutool-http/src/main/java/cn/hutool/http/server/filter/SimpleFilter.java b/hutool-http/src/main/java/cn/hutool/http/server/filter/SimpleFilter.java new file mode 100644 index 000000000..c0f6f787d --- /dev/null +++ b/hutool-http/src/main/java/cn/hutool/http/server/filter/SimpleFilter.java @@ -0,0 +1,17 @@ +package cn.hutool.http.server.filter; + +import com.sun.net.httpserver.Filter; + +/** + * 匿名简单过滤器,跳过了描述 + * + * @author looly + * @since 5.5.7 + */ +public abstract class SimpleFilter extends Filter { + + @Override + public String description() { + return "Anonymous Filter"; + } +} diff --git a/hutool-http/src/main/java/cn/hutool/http/server/filter/package-info.java b/hutool-http/src/main/java/cn/hutool/http/server/filter/package-info.java new file mode 100644 index 000000000..feae032a7 --- /dev/null +++ b/hutool-http/src/main/java/cn/hutool/http/server/filter/package-info.java @@ -0,0 +1,4 @@ +/** + * {@link com.sun.net.httpserver.Filter} 实现包装 + */ +package cn.hutool.http.server.filter; \ No newline at end of file diff --git a/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java b/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java index a16c96a1a..842ecccd0 100644 --- a/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java @@ -11,6 +11,10 @@ public class SimpleServerTest { public static void main(String[] args) { HttpUtil.createServer(8888) + .addFilter(((req, res, chain) -> { + Console.log("Filter: " + req.getPath()); + chain.doFilter(req.getHttpExchange()); + })) // 设置默认根目录,classpath/html .setRoot(FileUtil.file("html")) // get数据测试,返回请求的PATH @@ -46,7 +50,10 @@ public class SimpleServerTest { } ) // 测试输出响应内容是否能正常返回Content-Length头信息 - .addAction("test/zeroStr", (req, res)-> res.write("0")) + .addAction("test/zeroStr", (req, res)-> { + res.write("0"); + Console.log("Write 0 OK"); + }) .start(); } } From 80c39662110322a86772f5c914483003dcff2958 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 7 Jan 2021 21:40:53 +0800 Subject: [PATCH 45/54] fix code --- .../src/main/java/cn/hutool/json/JSONString.java | 4 ++-- .../src/main/java/cn/hutool/json/JSONSupport.java | 2 +- .../src/test/java/cn/hutool/json/JSONUtilTest.java | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONString.java b/hutool-json/src/main/java/cn/hutool/json/JSONString.java index dcf232c33..1d07078c3 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONString.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONString.java @@ -1,8 +1,8 @@ package cn.hutool.json; /** - * JSONString接口定义了一个toJSONString()
    - * 实现此接口的类可以通过实现toJSONString()方法来改变转JSON字符串的方式。 + * {@code JSONString}接口定义了一个{@code toJSONString()}
    + * 实现此接口的类可以通过实现{@code toJSONString()}方法来改变转JSON字符串的方式。 * * @author Looly * diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java b/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java index b9a026b47..44e7155c1 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java @@ -35,7 +35,7 @@ public class JSONSupport implements JSONString{ * @return 美化的JSON */ public String toPrettyString() { - return toJSON().toJSONString(4); + return toJSON().toStringPretty(); } @Override diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java index 9dcd583cc..f42855c0b 100644 --- a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java @@ -4,13 +4,13 @@ import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.NumberUtil; import cn.hutool.json.test.bean.Price; import cn.hutool.json.test.bean.UserA; import cn.hutool.json.test.bean.UserC; import org.junit.Assert; import org.junit.Test; -import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -165,11 +165,11 @@ public class JSONUtilTest { } @Test - public void doubleTest2() { - String json = "{\"test\": 12.00}"; - final JSONObject jsonObject = JSONUtil.parseObj(json); - jsonObject.set("test2", new BigInteger("12")); - Console.log(jsonObject); + public void customValueTest() { + final JSONObject jsonObject = JSONUtil.createObj() + .set("test2", (JSONString) () -> NumberUtil.decimalFormat("#.0", 12.00D)); + + Assert.assertEquals("{\"test2\":12.0}", jsonObject.toString()); } @Test From 64555cdc87303029139680cb2bd6dac98678f5e1 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 7 Jan 2021 21:44:43 +0800 Subject: [PATCH 46/54] add null check pr#250 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fd0102d5..8da8f5cb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ * 【crypto 】 修改SymmetricAlgorithm注释(issue#1360@Github) * 【all 】 pom中将META-INF/maven下全部exclude(pr#1355@Github) * 【http 】 SimpleServer中增加addFilter等方法,并使用全局线程池 +* 【core 】 CollUtil.forEach 增加null 判断(pr#250@Gitee) ### Bug修复 * 【core 】 修复CsvReader读取双引号未转义问题(issue#I2BMP1@Gitee) From 7fd389c0b320ac93c90506f46d4eb9ed5bee42a7 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 7 Jan 2021 22:47:42 +0800 Subject: [PATCH 47/54] fix trust bug --- CHANGELOG.md | 1 + .../main/java/cn/hutool/core/net}/DefaultTrustManager.java | 5 +++-- .../src/main/java/cn/hutool/core/net/SSLContextBuilder.java | 2 +- hutool-http/src/test/java/cn/hutool/http/HttpUtilTest.java | 3 --- .../src/main/java/cn/hutool/json/InternalJSONUtil.java | 2 +- 5 files changed, 6 insertions(+), 7 deletions(-) rename {hutool-http/src/main/java/cn/hutool/http/ssl => hutool-core/src/main/java/cn/hutool/core/net}/DefaultTrustManager.java (75%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8da8f5cb5..0291d91c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ * 【core 】 修复CsvReader读取双引号未转义问题(issue#I2BMP1@Gitee) * 【json 】 JSONUtil.parse修复config无效问题(issue#1363@Github) * 【http 】 修复SimpleServer返回响应内容Content-Length不正确的问题(issue#1358@Github) +* 【http 】 修复Https请求部分环境下报证书验证异常问题(issue#I2C1BZ@Github) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-http/src/main/java/cn/hutool/http/ssl/DefaultTrustManager.java b/hutool-core/src/main/java/cn/hutool/core/net/DefaultTrustManager.java similarity index 75% rename from hutool-http/src/main/java/cn/hutool/http/ssl/DefaultTrustManager.java rename to hutool-core/src/main/java/cn/hutool/core/net/DefaultTrustManager.java index 008d1a025..a31bbe153 100644 --- a/hutool-http/src/main/java/cn/hutool/http/ssl/DefaultTrustManager.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/DefaultTrustManager.java @@ -1,12 +1,13 @@ -package cn.hutool.http.ssl; +package cn.hutool.core.net; import javax.net.ssl.X509TrustManager; import java.security.cert.X509Certificate; /** - * 证书管理 + * 默认信任管理器,默认信任所有客户端和服务端证书 * * @author Looly + * @since 5.5.7 */ public class DefaultTrustManager implements X509TrustManager { diff --git a/hutool-core/src/main/java/cn/hutool/core/net/SSLContextBuilder.java b/hutool-core/src/main/java/cn/hutool/core/net/SSLContextBuilder.java index 776142391..dd32dc864 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/SSLContextBuilder.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/SSLContextBuilder.java @@ -52,7 +52,7 @@ public class SSLContextBuilder { private String protocol = TLS; private KeyManager[] keyManagers; - private TrustManager[] trustManagers; + private TrustManager[] trustManagers = {new DefaultTrustManager()}; private SecureRandom secureRandom = new SecureRandom(); 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 3cc5d25c1..3f3ebd7b6 100644 --- a/hutool-http/src/test/java/cn/hutool/http/HttpUtilTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/HttpUtilTest.java @@ -4,9 +4,6 @@ import cn.hutool.core.io.FileUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.ReUtil; -import cn.hutool.http.Header; -import cn.hutool.http.HttpRequest; -import cn.hutool.http.HttpUtil; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; diff --git a/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java b/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java index 95b8099c3..f71597c9d 100644 --- a/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java +++ b/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java @@ -253,7 +253,7 @@ final class InternalJSONUtil { //默认使用时间戳 long timeMillis; if (dateObj instanceof TemporalAccessor) { - timeMillis = DateUtil.toInstant((TemporalAccessor) dateObj).toEpochMilli(); + timeMillis = TemporalAccessorUtil.toEpochMilli((TemporalAccessor) dateObj); } else if (dateObj instanceof Date) { timeMillis = ((Date) dateObj).getTime(); } else if (dateObj instanceof Calendar) { From 14f2357fd85c823940d44a41d7b9a43c81e1ed04 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 7 Jan 2021 23:20:55 +0800 Subject: [PATCH 48/54] add method --- CHANGELOG.md | 1 + .../main/java/cn/hutool/extra/ftp/Ftp.java | 92 +++++++++---------- .../java/cn/hutool/extra/ftp/FtpConfig.java | 43 ++++++--- 3 files changed, 76 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0291d91c0..85f98d855 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ * 【all 】 pom中将META-INF/maven下全部exclude(pr#1355@Github) * 【http 】 SimpleServer中增加addFilter等方法,并使用全局线程池 * 【core 】 CollUtil.forEach 增加null 判断(pr#250@Gitee) +* 【extra 】 FtpConfig增加serverLanguageCode和systemKey配置,Ftp.download增加重载(pr#248@Gitee) ### Bug修复 * 【core 】 修复CsvReader读取双引号未转义问题(issue#I2BMP1@Gitee) diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java b/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java index 3294d39af..21f2498d0 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java @@ -1,5 +1,12 @@ package cn.hutool.extra.ftp; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.Filter; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.StrUtil; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPClientConfig; import org.apache.commons.net.ftp.FTPFile; @@ -14,14 +21,6 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; -import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.lang.Filter; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.CharsetUtil; -import cn.hutool.core.util.StrUtil; - /** * FTP客户端封装
    * 此客户端基于Apache-Commons-Net @@ -84,19 +83,19 @@ public class Ftp extends AbstractFtp { * @param charset 编码 */ public Ftp(String host, int port, String user, String password, Charset charset) { - this(host, port, user, password, charset,null, null); + this(host, port, user, password, charset, null, null); } /** * 构造 * - * @param host 域名或IP - * @param port 端口 - * @param user 用户名 - * @param password 密码 - * @param charset 编码 + * @param host 域名或IP + * @param port 端口 + * @param user 用户名 + * @param password 密码 + * @param charset 编码 * @param serverLanguageCode 服务器语言 例如:zh - * @param systemKey 服务器标识 例如:org.apache.commons.net.ftp.FTPClientConfig.SYST_NT + * @param systemKey 服务器标识 例如:org.apache.commons.net.ftp.FTPClientConfig.SYST_NT */ public Ftp(String host, int port, String user, String password, Charset charset, String serverLanguageCode, String systemKey) { this(host, port, user, password, charset, serverLanguageCode, systemKey, null); @@ -173,17 +172,25 @@ public class Ftp extends AbstractFtp { */ public Ftp init(FtpConfig config, FtpMode mode) { final FTPClient client = new FTPClient(); - client.setControlEncoding(config.getCharset().toString()); + final Charset charset = config.getCharset(); + if (null != charset) { + client.setControlEncoding(charset.toString()); + } client.setConnectTimeout((int) config.getConnectionTimeout()); + final String systemKey = config.getSystemKey(); + if (StrUtil.isNotBlank(systemKey)) { + final FTPClientConfig conf = new FTPClientConfig(systemKey); + final String serverLanguageCode = config.getServerLanguageCode(); + if (StrUtil.isNotBlank(serverLanguageCode)) { + conf.setServerLanguageCode(config.getServerLanguageCode()); + } + client.configure(conf); + } + try { // 连接ftp服务器 client.connect(config.getHost(), config.getPort()); client.setSoTimeout((int) config.getSoTimeout()); - // 下载中文文件 - if (StrUtil.isNotBlank(config.getSystemKey()) && StrUtil.isNotBlank(config.getServerLanguageCode())){ - FTPClientConfig conf = new FTPClientConfig(config.getSystemKey()); - conf.setServerLanguageCode(config.getServerLanguageCode()); - } // 登录ftp服务器 client.login(config.getUser(), config.getPassword()); } catch (IOException e) { @@ -367,6 +374,7 @@ public class Ftp extends AbstractFtp { /** * 获取服务端目录状态。 + * * @param path 路径 * @return 状态int,服务端不同,返回不同 * @since 5.4.3 @@ -602,12 +610,29 @@ public class Ftp extends AbstractFtp { * @param out 输出位置 */ public void download(String path, String fileName, OutputStream out) { + download(path, fileName, out, null); + } + + /** + * 下载文件到输出流 + * + * @param path 文件路径 + * @param fileName 文件名 + * @param out 输出位置 + * @param fileNameCharset 文件名编码 + * @since 5.5.7 + */ + public void download(String path, String fileName, OutputStream out, Charset fileNameCharset) { String pwd = null; if (this.backToPwd) { pwd = pwd(); } cd(path); + + if (null != fileNameCharset) { + fileName = new String(fileName.getBytes(fileNameCharset), StandardCharsets.ISO_8859_1); + } try { client.setFileType(FTPClient.BINARY_FILE_TYPE); client.retrieveFile(fileName, out); @@ -620,31 +645,6 @@ public class Ftp extends AbstractFtp { } } - /** - * 下载文件到输出流 - * - * @param path 文件路径 - * @param fileName 文件名 - * @param out 输出位置 - */ - public void download(String path, String fileName, OutputStream out, String fileNameCharset) { - String pwd = null; - if (this.backToPwd) { - pwd = pwd(); - } - - cd(path); - try { - client.setFileType(FTPClient.BINARY_FILE_TYPE); - client.retrieveFile(new String(fileName.getBytes(fileNameCharset), StandardCharsets.ISO_8859_1), out); - } catch (IOException e) { - throw new FtpException(e); - } finally { - if (backToPwd) { - cd(pwd); - } - } - } /** * 获取FTPClient客户端对象 * diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ftp/FtpConfig.java b/hutool-extra/src/main/java/cn/hutool/extra/ftp/FtpConfig.java index d5bb25a69..e50fa620c 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/ftp/FtpConfig.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/ftp/FtpConfig.java @@ -11,7 +11,7 @@ import java.nio.charset.Charset; public class FtpConfig implements Serializable { private static final long serialVersionUID = 1L; - public static FtpConfig create(){ + public static FtpConfig create() { return new FtpConfig(); } @@ -46,16 +46,15 @@ public class FtpConfig implements Serializable { */ private long soTimeout; - /** - * 设置服务器语言 - */ + /** + * 设置服务器语言 + */ private String serverLanguageCode; - /** - * 设置服务器系统关键词 - * @see org.apache.commons.net.ftp.FTPClientConfig - */ - private String systemKey; + /** + * 设置服务器系统关键词 + */ + private String systemKey; /** * 构造 @@ -66,11 +65,27 @@ public class FtpConfig implements Serializable { /** * 构造 * - * @param host 主机 - * @param port 端口 - * @param user 用户名 - * @param password 密码 - * @param charset 编码 + * @param host 主机 + * @param port 端口 + * @param user 用户名 + * @param password 密码 + * @param charset 编码 + */ + public FtpConfig(String host, int port, String user, String password, Charset charset) { + this(host, port, user, password, charset, null, null); + } + + /** + * 构造 + * + * @param host 主机 + * @param port 端口 + * @param user 用户名 + * @param password 密码 + * @param charset 编码 + * @param serverLanguageCode 服务器语言 + * @param systemKey 系统关键字 + * @since 5.5.7 */ public FtpConfig(String host, int port, String user, String password, Charset charset, String serverLanguageCode, String systemKey) { this.host = host; From f187dbd307ca974ea0368922115d87644ecd763d Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 7 Jan 2021 23:30:51 +0800 Subject: [PATCH 49/54] fix comment --- hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java | 1 + hutool-core/src/main/java/cn/hutool/core/text/csv/CsvWriter.java | 1 + 2 files changed, 2 insertions(+) diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java index 7a1b423cd..f4033da94 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java @@ -2922,6 +2922,7 @@ public class FileUtil extends PathUtil { * * @param dest 目标文件 * @param in 输入流 + * @param isCloseIn 是否关闭输入流 * @return dest * @throws IORuntimeException IO异常 * @since 5.5.6 diff --git a/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvWriter.java b/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvWriter.java index a012827a6..60d27685b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvWriter.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvWriter.java @@ -224,6 +224,7 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { /** * 追加新行(换行) * + * @return this * @throws IORuntimeException IO异常 */ public CsvWriter writeLine() throws IORuntimeException { From 96db7dba81d76c4e50a3c30e91793b04ccd6370e Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 7 Jan 2021 23:34:05 +0800 Subject: [PATCH 50/54] release 5.5.7 --- 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-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 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index 000c18a44..e239cb3f0 100644 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-all diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml index 9f68f2b6a..5d337fdd7 100644 --- a/hutool-aop/pom.xml +++ b/hutool-aop/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-aop diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml index 8fee87a21..a767a56e3 100644 --- a/hutool-bloomFilter/pom.xml +++ b/hutool-bloomFilter/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-bloomFilter diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml index 43c9394ee..48184050a 100644 --- a/hutool-bom/pom.xml +++ b/hutool-bom/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-bom diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml index a6c81ce00..de3142a3d 100644 --- a/hutool-cache/pom.xml +++ b/hutool-cache/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-cache diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml index 10a218809..e320cbc6a 100644 --- a/hutool-captcha/pom.xml +++ b/hutool-captcha/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-captcha diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index efb3e7407..de46de954 100644 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-core diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml index fc99fb8dc..6ffd975a3 100644 --- a/hutool-cron/pom.xml +++ b/hutool-cron/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-cron diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml index a841bde57..cc89c8582 100644 --- a/hutool-crypto/pom.xml +++ b/hutool-crypto/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-crypto diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index e8e571787..8bbcf1004 100644 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-db diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml index 85217487f..98626fc74 100644 --- a/hutool-dfa/pom.xml +++ b/hutool-dfa/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-dfa diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index 386ce9c35..33bdca9a1 100644 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-extra diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index 53c41383e..2f966e673 100644 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-http diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index fedc0ed94..eb77d0c2a 100644 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-json diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index 8f38ac5a2..b07dea43c 100644 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-log diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index ac001f8bb..a3ef5a974 100644 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-poi diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml index 4ffe4451d..a13468cc2 100644 --- a/hutool-script/pom.xml +++ b/hutool-script/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-script diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml index 9459e5c6d..6583069e9 100644 --- a/hutool-setting/pom.xml +++ b/hutool-setting/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-setting diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml index 4463355d9..5d6181940 100644 --- a/hutool-socket/pom.xml +++ b/hutool-socket/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-socket diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml index 0d472abe8..2d0821ca2 100644 --- a/hutool-system/pom.xml +++ b/hutool-system/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool-system diff --git a/pom.xml b/pom.xml index b267e6271..8c005007a 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.7-SNAPSHOT + 5.5.7 hutool Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。 https://github.com/looly/hutool From fd085c2e4c4e9a1e4c9a8dd824632f156df25254 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 7 Jan 2021 23:53:19 +0800 Subject: [PATCH 51/54] prepare 5.5.8 --- README-EN.md | 8 ++++---- README.md | 8 ++++---- 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-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 +- 25 files changed, 31 insertions(+), 31 deletions(-) diff --git a/README-EN.md b/README-EN.md index 4ef40661b..aa86df374 100644 --- a/README-EN.md +++ b/README-EN.md @@ -125,19 +125,19 @@ Each module can be introduced individually, or all modules can be introduced by cn.hutool hutool-all - 5.5.7 + 5.5.8 ``` ### Gradle ``` -compile 'cn.hutool:hutool-all:5.5.7' +compile 'cn.hutool:hutool-all:5.5.8' ``` ## Download -- [Maven1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.7/) -- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.7/) +- [Maven1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.8/) +- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.8/) > 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 f078dfd69..ffecd8237 100644 --- a/README.md +++ b/README.md @@ -123,21 +123,21 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不 cn.hutool hutool-all - 5.5.7 + 5.5.8 ``` ### Gradle ``` -compile 'cn.hutool:hutool-all:5.5.7' +compile 'cn.hutool:hutool-all:5.5.8' ``` ### 非Maven项目 点击以下任一链接,下载`hutool-all-X.X.X.jar`即可: -- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.7/) -- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.7/) +- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.8/) +- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.8/) > 注意 > Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。 diff --git a/bin/version.txt b/bin/version.txt index 21f56a9f8..751e09b70 100755 --- a/bin/version.txt +++ b/bin/version.txt @@ -1 +1 @@ -5.5.7 +5.5.8 diff --git a/docs/js/version.js b/docs/js/version.js index 2c5f13683..decf88231 100644 --- a/docs/js/version.js +++ b/docs/js/version.js @@ -1 +1 @@ -var version = '5.5.7' \ No newline at end of file +var version = '5.5.8' \ No newline at end of file diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index e239cb3f0..e65e6920f 100644 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-all diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml index 5d337fdd7..308e4be56 100644 --- a/hutool-aop/pom.xml +++ b/hutool-aop/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-aop diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml index a767a56e3..31547d408 100644 --- a/hutool-bloomFilter/pom.xml +++ b/hutool-bloomFilter/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-bloomFilter diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml index 48184050a..23c1dc7a9 100644 --- a/hutool-bom/pom.xml +++ b/hutool-bom/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-bom diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml index de3142a3d..4287e94cd 100644 --- a/hutool-cache/pom.xml +++ b/hutool-cache/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-cache diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml index e320cbc6a..1606d7911 100644 --- a/hutool-captcha/pom.xml +++ b/hutool-captcha/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-captcha diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index de46de954..4c3a2e46a 100644 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-core diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml index 6ffd975a3..6bf05e325 100644 --- a/hutool-cron/pom.xml +++ b/hutool-cron/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-cron diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml index cc89c8582..0b57d757c 100644 --- a/hutool-crypto/pom.xml +++ b/hutool-crypto/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-crypto diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index 8bbcf1004..8f11e132f 100644 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-db diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml index 98626fc74..12c8d441f 100644 --- a/hutool-dfa/pom.xml +++ b/hutool-dfa/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-dfa diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index 33bdca9a1..d38169335 100644 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-extra diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index 2f966e673..bc0c78e63 100644 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-http diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index eb77d0c2a..99f484c82 100644 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-json diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index b07dea43c..5150aa8db 100644 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-log diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index a3ef5a974..d57a3bfed 100644 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-poi diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml index a13468cc2..b7d1d103f 100644 --- a/hutool-script/pom.xml +++ b/hutool-script/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-script diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml index 6583069e9..8328fff8f 100644 --- a/hutool-setting/pom.xml +++ b/hutool-setting/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-setting diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml index 5d6181940..4116aab82 100644 --- a/hutool-socket/pom.xml +++ b/hutool-socket/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-socket diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml index 2d0821ca2..1be684c74 100644 --- a/hutool-system/pom.xml +++ b/hutool-system/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool-system diff --git a/pom.xml b/pom.xml index 8c005007a..a3a5bf13e 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.5.7 + 5.5.8-SNAPSHOT hutool Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。 https://github.com/looly/hutool From 12dba92423824d8ff726aa5fe4459e8cf9390354 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 7 Jan 2021 23:54:26 +0800 Subject: [PATCH 52/54] prepare 5.5.8 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85f98d855..fcb1a4ad0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,13 @@ ------------------------------------------------------------------------------------------------------------- +# 5.5.8 (2021-01-08) + +### 新特性 +### Bug修复 + +------------------------------------------------------------------------------------------------------------- + # 5.5.7 (2021-01-07) ### 新特性 From bab6ab5a2767d180cef7998d5b7f0ea6a829b15a Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 8 Jan 2021 09:40:33 +0800 Subject: [PATCH 53/54] add test --- .../src/test/java/cn/hutool/core/lang/SnowflakeTest.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/SnowflakeTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/SnowflakeTest.java index 795dddde4..451a9394b 100644 --- a/hutool-core/src/test/java/cn/hutool/core/lang/SnowflakeTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/SnowflakeTest.java @@ -5,6 +5,7 @@ import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.thread.ConcurrencyTester; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -66,4 +67,12 @@ public class SnowflakeTest { } }); } + + @Test + public void getSnowflakeLengthTest(){ + for (int i = 0; i < 1000; i++) { + final long l = IdUtil.getSnowflake(0, 0).nextId(); + Assert.assertEquals(19, StrUtil.toString(l).length()); + } + } } From 49fab3986f21aeec6fbd418ff62061433fd2751e Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 9 Jan 2021 18:51:40 +0800 Subject: [PATCH 54/54] fix copy #I2CKTI --- CHANGELOG.md | 5 +- .../main/java/cn/hutool/core/io/FileUtil.java | 15 +++-- .../java/cn/hutool/core/io/file/PathUtil.java | 64 ++++++++++++++++--- .../core/io/file/visitor/CopyVisitor.java | 34 ++++++++-- .../cn/hutool/core/io/file/PathUtilTest.java | 16 ++++- 5 files changed, 112 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fcb1a4ad0..0d19e2c0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,11 @@ ------------------------------------------------------------------------------------------------------------- -# 5.5.8 (2021-01-08) +# 5.5.8 (2021-01-09) ### 新特性 ### Bug修复 +* 【core 】 修复FileUtil.move以及PathUtil.copy等无法自动创建父目录的问题(issue#I2CKTI@Gitee) ------------------------------------------------------------------------------------------------------------- @@ -29,7 +30,7 @@ * 【core 】 修复CsvReader读取双引号未转义问题(issue#I2BMP1@Gitee) * 【json 】 JSONUtil.parse修复config无效问题(issue#1363@Github) * 【http 】 修复SimpleServer返回响应内容Content-Length不正确的问题(issue#1358@Github) -* 【http 】 修复Https请求部分环境下报证书验证异常问题(issue#I2C1BZ@Github) +* 【http 】 修复Https请求部分环境下报证书验证异常问题(issue#I2C1BZ@Gitee) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java index f4033da94..c652deade 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java @@ -638,12 +638,10 @@ public class FileUtil extends PathUtil { * @return 父目录 */ public static File mkParentDirs(File file) { - final File parentFile = file.getParentFile(); - if (null != parentFile && false == parentFile.exists()) { - //noinspection ResultOfMethodCallIgnored - parentFile.mkdirs(); + if(null == file){ + return null; } - return parentFile; + return mkdir(file.getParentFile()); } /** @@ -1022,6 +1020,7 @@ public class FileUtil extends PathUtil { * @param isOverride 是否覆盖目标文件 * @return 目标文件 * @since 3.0.9 + * @see PathUtil#rename(Path, String, boolean) */ public static File rename(File file, String newName, boolean isRetainExt, boolean isOverride) { if (isRetainExt) { @@ -3192,6 +3191,12 @@ public class FileUtil extends PathUtil { contentType = "application/x-javascript"; } } + + // 补充 + if(null == contentType){ + contentType = getMimeType(Paths.get(filePath)); + } + return contentType; } diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java index 1c877e6ef..e8588cc60 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java @@ -153,7 +153,8 @@ public class PathUtil { } /** - * 通过JDK7+的 {@link Files#copy(Path, Path, CopyOption...)} 方法拷贝文件 + * 通过JDK7+的 {@link Files#copy(Path, Path, CopyOption...)} 方法拷贝文件
    + * 此方法不支持递归拷贝目录,如果src传入是目录,只会在目标目录中创建空目录 * * @param src 源文件路径,如果为目录只在目标中创建新目录 * @param dest 目标文件或目录,如果为目录使用与源文件相同的文件名 @@ -166,7 +167,8 @@ public class PathUtil { } /** - * 通过JDK7+的 {@link Files#copy(Path, Path, CopyOption...)} 方法拷贝文件 + * 通过JDK7+的 {@link Files#copy(Path, Path, CopyOption...)} 方法拷贝文件
    + * 此方法不支持递归拷贝目录,如果src传入是目录,只会在目标目录中创建空目录 * * @param src 源文件路径,如果为目录只在目标中创建新目录 * @param target 目标文件或目录,如果为目录使用与源文件相同的文件名 @@ -180,6 +182,8 @@ public class PathUtil { Assert.notNull(target, "Destination File or directiory is null !"); final Path targetPath = isDirectory(target) ? target.resolve(src.getFileName()) : target; + // 创建级联父目录 + mkParentDirs(targetPath); try { return Files.copy(src, targetPath, options); } catch (IOException e) { @@ -188,9 +192,15 @@ public class PathUtil { } /** - * 拷贝文件或目录 + * 拷贝文件或目录,拷贝规则为: * - * @param src 源文件路径,如果为目录只在目标中创建新目录 + *
      + *
    • 源文件为目录,目标也为目录或不存在,则拷贝整个目录到目标目录下
    • + *
    • 源文件为文件,目标为目录或不存在,则拷贝文件到目标目录下
    • + *
    • 源文件为文件,目标也为文件,则在{@link StandardCopyOption#REPLACE_EXISTING}情况下覆盖之
    • + *
    + * + * @param src 源文件路径,如果为目录会在目标中创建新目录 * @param target 目标文件或目录,如果为目录使用与源文件相同的文件名 * @param options {@link StandardCopyOption} * @return Path @@ -198,17 +208,21 @@ public class PathUtil { * @since 5.5.1 */ public static Path copy(Path src, Path target, CopyOption... options) throws IORuntimeException { - if (isFile(src, false)) { - return copyFile(src, target, options); + if (isDirectory(src)) { + return copyContent(src, target.resolve(src.getFileName()), options); } - return copyContent(src, target.resolve(src.getFileName()), options); + return copyFile(src, target, options); } /** - * 拷贝目录下的所有文件或目录到目标目录中 + * 拷贝目录下的所有文件或目录到目标目录中,此方法不支持文件对文件的拷贝。 + *
      + *
    • 源文件为目录,目标也为目录或不存在,则拷贝目录下所有文件和目录到目标目录下
    • + *
    • 源文件为文件,目标为目录或不存在,则拷贝文件到目标目录下
    • + *
    * * @param src 源文件路径,如果为目录只在目标中创建新目录 - * @param target 目标文件或目录,如果为目录使用与源文件相同的文件名 + * @param target 目标目录,如果为目录使用与源文件相同的文件名 * @param options {@link StandardCopyOption} * @return Path * @throws IORuntimeException IO异常 @@ -450,6 +464,8 @@ public class PathUtil { if (isDirectory(target)) { target = target.resolve(src.getFileName()); } + // 自动创建目标的父目录 + mkParentDirs(target); try { return Files.move(src, target, options); } catch (IOException e) { @@ -546,6 +562,7 @@ public class PathUtil { * @param file 文件 * @return MimeType * @since 5.5.5 + * @see Files#probeContentType(Path) */ public static String getMimeType(Path file) { try { @@ -554,4 +571,33 @@ public class PathUtil { throw new IORuntimeException(e); } } + + /** + * 创建所给目录及其父目录 + * + * @param dir 目录 + * @return 目录 + * @since 5.5.7 + */ + public static Path mkdir(Path dir) { + if (null != dir && false == exists(dir, false)) { + try { + Files.createDirectories(dir); + } catch (IOException e) { + throw new IORuntimeException(e); + } + } + return dir; + } + + /** + * 创建所给文件或目录的父目录 + * + * @param path 文件或目录 + * @return 父目录 + * @since 5.5.7 + */ + public static Path mkParentDirs(Path path) { + return mkdir(path.getParent()); + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/CopyVisitor.java b/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/CopyVisitor.java index e633e8ac8..1bdf5aecb 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/CopyVisitor.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/CopyVisitor.java @@ -1,5 +1,7 @@ package cn.hutool.core.io.file.visitor; +import cn.hutool.core.io.file.PathUtil; + import java.io.IOException; import java.nio.file.FileAlreadyExistsException; import java.nio.file.FileVisitResult; @@ -9,17 +11,28 @@ import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; /** - * 文件拷贝的FileVisitor实现,用于递归遍历拷贝目录 + * 文件拷贝的FileVisitor实现,用于递归遍历拷贝目录,此类非线程安全
    + * 此类在遍历源目录并复制过程中会自动创建目标目录中不存在的上级目录。 * * @author looly * @since 5.5.1 */ public class CopyVisitor extends SimpleFileVisitor { - final Path source; - final Path target; + private final Path source; + private final Path target; + private boolean isTargetCreated; + /** + * 构造 + * + * @param source 源Path + * @param target 目标Path + */ public CopyVisitor(Path source, Path target) { + if(PathUtil.exists(target, false) && false == PathUtil.isDirectory(target)){ + throw new IllegalArgumentException("Target must be a directory"); + } this.source = source; this.target = target; } @@ -27,11 +40,13 @@ public class CopyVisitor extends SimpleFileVisitor { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + initTarget(); + // 将当前目录相对于源路径转换为相对于目标路径 final Path targetDir = target.resolve(source.relativize(dir)); try { Files.copy(dir, targetDir); } catch (FileAlreadyExistsException e) { - if (!Files.isDirectory(targetDir)) + if (false == Files.isDirectory(targetDir)) throw e; } return FileVisitResult.CONTINUE; @@ -40,7 +55,18 @@ public class CopyVisitor extends SimpleFileVisitor { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + initTarget(); Files.copy(file, target.resolve(source.relativize(file))); return FileVisitResult.CONTINUE; } + + /** + * 初始化目标文件或目录 + */ + private void initTarget(){ + if(false == this.isTargetCreated){ + PathUtil.mkdir(this.target); + this.isTargetCreated = true; + } + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java index 684ab56c0..b394edbd9 100644 --- a/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java @@ -25,7 +25,16 @@ public class PathUtilTest { public void copyTest(){ PathUtil.copy( Paths.get("d:/Red2_LYY"), - Paths.get("d:/test/") + Paths.get("d:/test/aaa/aaa.txt") + ); + } + + @Test + @Ignore + public void copyContentTest(){ + PathUtil.copyContent( + Paths.get("d:/Red2_LYY"), + Paths.get("d:/test/aaa/") ); } @@ -37,7 +46,10 @@ public class PathUtilTest { @Test public void getMimeTypeTest(){ - final String mimeType = PathUtil.getMimeType(Paths.get("d:/test/test.jpg")); + String mimeType = PathUtil.getMimeType(Paths.get("d:/test/test.jpg")); Assert.assertEquals("image/jpeg", mimeType); + + mimeType = PathUtil.getMimeType(Paths.get("d:/test/test.mov")); + Assert.assertEquals("video/quicktime", mimeType); } }