mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-08-18 20:38:02 +08:00
Compare commits
22 Commits
d2ed2124b6
...
v7-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10d660fb06 | ||
|
|
831fed4bb3 | ||
|
|
4d0074e6a6 | ||
|
|
707daa94f7 | ||
|
|
60b80340fc | ||
|
|
0255f8a365 | ||
|
|
f20536ea12 | ||
|
|
cc0b4b10c7 | ||
|
|
0d0c7622b6 | ||
|
|
e89cb0bdea | ||
|
|
bf3376f464 | ||
|
|
a621066525 | ||
|
|
8bb82a9d92 | ||
|
|
27f77f83a7 | ||
|
|
04bb0183e5 | ||
|
|
98a03945f7 | ||
|
|
be20536ba1 | ||
|
|
a4a02bdbd6 | ||
|
|
7391526b74 | ||
|
|
0978d2ce1b | ||
|
|
55794a1725 | ||
|
|
8f94b5ba2e |
@@ -128,18 +128,18 @@ Each module can be introduced individually, or all modules can be introduced by
|
||||
<dependency>
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### 🍐Gradle
|
||||
```
|
||||
implementation 'cn.hutool.v7:hutool-all:7.0.0-M1'
|
||||
implementation 'cn.hutool.v7:hutool-all:7.0.0-M2'
|
||||
```
|
||||
|
||||
## 📥Download
|
||||
|
||||
- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/v7/hutool-all/7.0.0-M1/)
|
||||
- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/v7/hutool-all/7.0.0-M2/)
|
||||
|
||||
> 🔔️note:
|
||||
> Hutool 7.x supports JDK17 and is not tested on Android platforms, and cannot guarantee that all tool classes or tool methods are available.
|
||||
|
||||
@@ -84,7 +84,7 @@ Hutool目前主要版本4.x、5.x、6.x、7.x,选择如下:
|
||||
| 4.x | jdk1.7 | [cn.hutool/hutool-all/4.x](https://mvnrepository.com/artifact/cn.hutool/hutool-all/4.6.17) | jdk1.7编译 |
|
||||
| 5.x | jdk1.8 | [cn.hutool/hutool-all/5.x ](https://mvnrepository.com/artifact/cn.hutool/hutool-all) | jdk1.8编译,使用JavaEE,适配JDK11、17、21 |
|
||||
| 6.x | jdk1.8 | [org.dromara.hutool/hutool-all/6.x ](https://mvnrepository.com/artifact/org.dromara.hutool/hutool-all) | jdk1.8编译,使用Jakarta EE,适配JDK11、17、21 |
|
||||
| 7.x | jdk17 | [cn.hutool.v7/hutool-all/6.x ](https://mvnrepository.com/artifact/org.dromara.hutool/hutool-all) | jdk17编译,使用Jakarta EE,适配17+ |
|
||||
| 7.x | jdk17 | [cn.hutool.v7/hutool-all/7.x ](https://mvnrepository.com/artifact/cn.hutool.v7/hutool-all) | jdk17编译,使用Jakarta EE,适配17+ |
|
||||
|
||||
## 🛠️包含组件
|
||||
|
||||
@@ -131,21 +131,21 @@ Hutool目前主要版本4.x、5.x、6.x、7.x,选择如下:
|
||||
<dependency>
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### 🍐Gradle
|
||||
|
||||
```
|
||||
implementation 'cn.hutool.v7:hutool-all:7.0.0-M1'
|
||||
implementation 'cn.hutool.v7:hutool-all:7.0.0-M2'
|
||||
```
|
||||
|
||||
### 📥下载jar
|
||||
|
||||
点击以下链接,下载`hutool-all-X.X.X.jar`即可:
|
||||
|
||||
- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/v7/hutool-all/7.0.0-M1/)
|
||||
- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/v7/hutool-all/7.0.0-M2/)
|
||||
|
||||
> 🔔️注意
|
||||
> Hutool 7.x支持JDK17,对Android平台没有测试,不能保证所有工具类或工具方法可用。
|
||||
|
||||
@@ -1 +1 @@
|
||||
7.0.0-M1
|
||||
7.0.0-M2
|
||||
|
||||
@@ -1 +1 @@
|
||||
var version = '7.0.0-M1'
|
||||
var version = '7.0.0-M2'
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-ai</artifactId>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-all</artifactId>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-bom</artifactId>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-core</artifactId>
|
||||
|
||||
@@ -389,9 +389,9 @@ public class MapUtil extends MapGetUtil {
|
||||
final HashMap<Object, Object> map = new HashMap<>((int) (array.length * 1.5));
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
final Object object = array[i];
|
||||
if (object instanceof Map.Entry entry) {
|
||||
if (object instanceof final Map.Entry entry) {
|
||||
map.put(entry.getKey(), entry.getValue());
|
||||
} else if (object instanceof Object[] entry) {
|
||||
} else if (object instanceof final Object[] entry) {
|
||||
if (entry.length > 1) {
|
||||
map.put(entry[0], entry[1]);
|
||||
}
|
||||
@@ -404,7 +404,7 @@ public class MapUtil extends MapGetUtil {
|
||||
map.put(key, value);
|
||||
}
|
||||
}
|
||||
} else if (object instanceof Iterator iter) {
|
||||
} else if (object instanceof final Iterator iter) {
|
||||
if (iter.hasNext()) {
|
||||
final Object key = iter.next();
|
||||
if (iter.hasNext()) {
|
||||
@@ -838,7 +838,7 @@ public class MapUtil extends MapGetUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (map instanceof TreeMap<K, V> result) {
|
||||
if (map instanceof final TreeMap<K, V> result) {
|
||||
// 已经是可排序Map,此时只有比较器一致才返回原map
|
||||
if (null == comparator || comparator.equals(result.comparator())) {
|
||||
return result;
|
||||
@@ -1399,4 +1399,45 @@ public class MapUtil extends MapGetUtil {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将多层级Map处理为一个层级Map类型
|
||||
*
|
||||
* @param map 入参Map
|
||||
* @return 单层级Map返回值
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
*/
|
||||
public static <K, V> Map<K, V> flatten(final Map<K, V> map) {
|
||||
return flatten(map, new HashMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归调用将多层级Map处理为一个层级Map类型
|
||||
*
|
||||
* @param map 入参Map
|
||||
* @param flatMap 单层级Map返回值
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @return 单层级Map返回值
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <K, V> Map<K, V> flatten(final Map<K, V> map, Map<K, V> flatMap) {
|
||||
Assert.notNull(map);
|
||||
if(null == flatMap){
|
||||
flatMap = new HashMap<>();
|
||||
}
|
||||
|
||||
final Map<K, V> finalFlatMap = flatMap;
|
||||
map.forEach((k, v) -> {
|
||||
// 避免嵌套循环
|
||||
if (v instanceof Map && v != map) {
|
||||
flatten((Map<K, V>) v, finalFlatMap);
|
||||
} else {
|
||||
finalFlatMap.put(k, v);
|
||||
}
|
||||
});
|
||||
|
||||
return flatMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import cn.hutool.v7.core.lang.Opt;
|
||||
import cn.hutool.v7.core.math.NumberUtil;
|
||||
import cn.hutool.v7.core.util.ObjUtil;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Collection;
|
||||
@@ -100,6 +101,7 @@ public class EasyStream<T> extends AbstractEnhancedWrappedStream<T, EasyStream<T
|
||||
*/
|
||||
public static <T> Builder<T> builder() {
|
||||
return new Builder<T>() {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final Stream.Builder<T> streamBuilder = Stream.builder();
|
||||
|
||||
|
||||
@@ -23,10 +23,14 @@ import cn.hutool.v7.core.map.MapUtil;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collector;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
/**
|
||||
* CollectionStream测试方法
|
||||
*/
|
||||
@@ -35,17 +39,17 @@ public class CollStreamUtilTest {
|
||||
@Test
|
||||
public void testToIdentityMap() {
|
||||
Map<Long, Student> map = CollStreamUtil.toIdentityMap(null, Student::getStudentId);
|
||||
Assertions.assertEquals(map, Collections.EMPTY_MAP);
|
||||
assertEquals(Collections.EMPTY_MAP, map);
|
||||
final List<Student> list = new ArrayList<>();
|
||||
map = CollStreamUtil.toIdentityMap(list, Student::getStudentId);
|
||||
Assertions.assertEquals(map, Collections.EMPTY_MAP);
|
||||
assertEquals(Collections.EMPTY_MAP, map);
|
||||
list.add(new Student(1, 1, 1, "张三"));
|
||||
list.add(new Student(1, 1, 2, "李四"));
|
||||
list.add(new Student(1, 1, 3, "王五"));
|
||||
map = CollStreamUtil.toIdentityMap(list, Student::getStudentId);
|
||||
Assertions.assertEquals(map.get(1L).getName(), "张三");
|
||||
Assertions.assertEquals(map.get(2L).getName(), "李四");
|
||||
Assertions.assertEquals(map.get(3L).getName(), "王五");
|
||||
assertEquals("张三", map.get(1L).getName());
|
||||
assertEquals("李四", map.get(2L).getName());
|
||||
assertEquals("王五", map.get(3L).getName());
|
||||
Assertions.assertNull(map.get(4L));
|
||||
|
||||
// 测试value为空时
|
||||
@@ -57,17 +61,17 @@ public class CollStreamUtilTest {
|
||||
@Test
|
||||
public void testToMap() {
|
||||
Map<Long, String> map = CollStreamUtil.toMap(null, Student::getStudentId, Student::getName);
|
||||
Assertions.assertEquals(map, Collections.EMPTY_MAP);
|
||||
assertEquals(Collections.EMPTY_MAP, map);
|
||||
final List<Student> list = new ArrayList<>();
|
||||
map = CollStreamUtil.toMap(list, Student::getStudentId, Student::getName);
|
||||
Assertions.assertEquals(map, Collections.EMPTY_MAP);
|
||||
assertEquals(Collections.EMPTY_MAP, map);
|
||||
list.add(new Student(1, 1, 1, "张三"));
|
||||
list.add(new Student(1, 1, 2, "李四"));
|
||||
list.add(new Student(1, 1, 3, "王五"));
|
||||
map = CollStreamUtil.toMap(list, Student::getStudentId, Student::getName);
|
||||
Assertions.assertEquals(map.get(1L), "张三");
|
||||
Assertions.assertEquals(map.get(2L), "李四");
|
||||
Assertions.assertEquals(map.get(3L), "王五");
|
||||
assertEquals("张三", map.get(1L));
|
||||
assertEquals("李四", map.get(2L));
|
||||
assertEquals("王五", map.get(3L));
|
||||
Assertions.assertNull(map.get(4L));
|
||||
|
||||
// 测试value为空时
|
||||
@@ -79,10 +83,10 @@ public class CollStreamUtilTest {
|
||||
@Test
|
||||
public void testGroupByKey() {
|
||||
Map<Long, List<Student>> map = CollStreamUtil.groupByKey(null, Student::getClassId);
|
||||
Assertions.assertEquals(map, Collections.EMPTY_MAP);
|
||||
assertEquals(Collections.EMPTY_MAP, map);
|
||||
final List<Student> list = new ArrayList<>();
|
||||
map = CollStreamUtil.groupByKey(list, Student::getClassId);
|
||||
Assertions.assertEquals(map, Collections.EMPTY_MAP);
|
||||
assertEquals(Collections.EMPTY_MAP, map);
|
||||
list.add(new Student(1, 1, 1, "张三"));
|
||||
list.add(new Student(1, 2, 2, "李四"));
|
||||
list.add(new Student(2, 1, 1, "擎天柱"));
|
||||
@@ -102,16 +106,16 @@ public class CollStreamUtilTest {
|
||||
final List<Student> class3 = new ArrayList<>();
|
||||
class3.add(new Student(2, 3, 2, "霸天虎"));
|
||||
compare.put(3L, class3);
|
||||
Assertions.assertEquals(map, compare);
|
||||
assertEquals(map, compare);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroupBy2Key() {
|
||||
Map<Long, Map<Long, List<Student>>> map = CollStreamUtil.groupBy2Key(null, Student::getTermId, Student::getClassId);
|
||||
Assertions.assertEquals(map, Collections.EMPTY_MAP);
|
||||
assertEquals(Collections.EMPTY_MAP, map);
|
||||
final List<Student> list = new ArrayList<>();
|
||||
map = CollStreamUtil.groupBy2Key(list, Student::getTermId, Student::getClassId);
|
||||
Assertions.assertEquals(map, Collections.EMPTY_MAP);
|
||||
assertEquals(Collections.EMPTY_MAP, map);
|
||||
list.add(new Student(1, 1, 1, "张三"));
|
||||
list.add(new Student(1, 2, 2, "李四"));
|
||||
list.add(new Student(1, 2, 3, "王五"));
|
||||
@@ -141,17 +145,17 @@ public class CollStreamUtilTest {
|
||||
list22.add(new Student(2, 2, 3, "霸天虎"));
|
||||
map2.put(2L, list22);
|
||||
compare.put(2L, map2);
|
||||
Assertions.assertEquals(map, compare);
|
||||
assertEquals(map, compare);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroup2Map() {
|
||||
Map<Long, Map<Long, Student>> map = CollStreamUtil.group2Map(null, Student::getTermId, Student::getClassId);
|
||||
Assertions.assertEquals(map, Collections.EMPTY_MAP);
|
||||
assertEquals(Collections.EMPTY_MAP, map);
|
||||
|
||||
final List<Student> list = new ArrayList<>();
|
||||
map = CollStreamUtil.group2Map(list, Student::getTermId, Student::getClassId);
|
||||
Assertions.assertEquals(map, Collections.EMPTY_MAP);
|
||||
assertEquals(Collections.EMPTY_MAP, map);
|
||||
list.add(new Student(1, 1, 1, "张三"));
|
||||
list.add(new Student(1, 2, 1, "李四"));
|
||||
list.add(new Student(2, 2, 1, "王五"));
|
||||
@@ -164,27 +168,28 @@ public class CollStreamUtilTest {
|
||||
final Map<Long, Student> map2 = new HashMap<>();
|
||||
map2.put(2L, new Student(2, 2, 1, "王五"));
|
||||
compare.put(2L, map2);
|
||||
Assertions.assertEquals(compare, map);
|
||||
assertEquals(compare, map);
|
||||
|
||||
// 对null友好
|
||||
final Map<Long, Map<Long, Student>> termIdClassIdStudentMap = CollStreamUtil.group2Map(Arrays.asList(null, new Student(2, 2, 1, "王五")), Student::getTermId, Student::getClassId);
|
||||
final Map<Long, Map<Long, Student>> termIdClassIdStudentCompareMap = new HashMap<Long, Map<Long, Student>>() {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
{
|
||||
put(null, MapUtil.empty());
|
||||
put(2L, MapUtil.of(2L, new Student(2, 2, 1, "王五")));
|
||||
}};
|
||||
Assertions.assertEquals(termIdClassIdStudentCompareMap, termIdClassIdStudentMap);
|
||||
assertEquals(termIdClassIdStudentCompareMap, termIdClassIdStudentMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroupKeyValue() {
|
||||
Map<Long, List<Long>> map = CollStreamUtil.groupKeyValue(null, Student::getTermId, Student::getClassId);
|
||||
Assertions.assertEquals(map, Collections.EMPTY_MAP);
|
||||
assertEquals(Collections.EMPTY_MAP, map);
|
||||
|
||||
final List<Student> list = new ArrayList<>();
|
||||
map = CollStreamUtil.groupKeyValue(list, Student::getTermId, Student::getClassId);
|
||||
Assertions.assertEquals(map, Collections.EMPTY_MAP);
|
||||
assertEquals(Collections.EMPTY_MAP, map);
|
||||
list.add(new Student(1, 1, 1, "张三"));
|
||||
list.add(new Student(1, 2, 1, "李四"));
|
||||
list.add(new Student(2, 2, 1, "王五"));
|
||||
@@ -193,7 +198,7 @@ public class CollStreamUtilTest {
|
||||
final Map<Long, List<Long>> compare = new HashMap<>();
|
||||
compare.put(1L, Arrays.asList(1L, 2L));
|
||||
compare.put(2L, Collections.singletonList(2L));
|
||||
Assertions.assertEquals(compare, map);
|
||||
assertEquals(compare, map);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -202,12 +207,12 @@ public class CollStreamUtilTest {
|
||||
|
||||
// 参数null测试
|
||||
Map<Long, List<Student>> map = CollStreamUtil.groupBy(null, Student::getTermId, Collectors.toList());
|
||||
Assertions.assertEquals(map, Collections.EMPTY_MAP);
|
||||
assertEquals(Collections.EMPTY_MAP, map);
|
||||
|
||||
// 参数空数组测试
|
||||
final List<Student> list = new ArrayList<>();
|
||||
map = CollStreamUtil.groupBy(list, Student::getTermId, Collectors.toList());
|
||||
Assertions.assertEquals(map, Collections.EMPTY_MAP);
|
||||
assertEquals(Collections.EMPTY_MAP, map);
|
||||
|
||||
// 放入元素
|
||||
list.add(new Student(1, 1, 1, "张三"));
|
||||
@@ -216,11 +221,11 @@ public class CollStreamUtilTest {
|
||||
// 先根据termId分组,再通过classId比较,找出最大值所属的那个Student,返回的Optional
|
||||
final Map<Long, Optional<Student>> longOptionalMap = CollStreamUtil.groupBy(list, Student::getTermId, Collectors.maxBy(Comparator.comparing(Student::getClassId)));
|
||||
//noinspection OptionalGetWithoutIsPresent
|
||||
Assertions.assertEquals("李四", longOptionalMap.get(1L).get().getName());
|
||||
assertEquals("李四", longOptionalMap.get(1L).get().getName());
|
||||
|
||||
// 先根据termId分组,再转换为Map<studentId,name>
|
||||
final Map<Long, HashMap<Long, String>> groupThen = CollStreamUtil.groupBy(list, Student::getTermId, Collector.of(HashMap::new, (m, v) -> m.put(v.getStudentId(), v.getName()), (l, r) -> l));
|
||||
Assertions.assertEquals(
|
||||
assertEquals(
|
||||
MapUtil.builder()
|
||||
.put(1L, MapUtil.builder().put(1L, "李四").build())
|
||||
.put(2L, MapUtil.builder().put(1L, "王五").build())
|
||||
@@ -235,23 +240,23 @@ public class CollStreamUtilTest {
|
||||
final Map<Long, List<Student>> termIdStudentsCompareMap = new HashMap<>();
|
||||
termIdStudentsCompareMap.put(null, Collections.emptyList());
|
||||
termIdStudentsCompareMap.put(1L, Arrays.asList(new Student(1L, 1, 1, "张三"), new Student(1L, 2, 1, "李四")));
|
||||
Assertions.assertEquals(termIdStudentsCompareMap, termIdStudentsMap);
|
||||
assertEquals(termIdStudentsCompareMap, termIdStudentsMap);
|
||||
|
||||
final Map<Long, Long> termIdCountMap = CollStreamUtil.groupBy(students, Student::getTermId, Collectors.counting());
|
||||
final Map<Long, Long> termIdCountCompareMap = new HashMap<>();
|
||||
termIdCountCompareMap.put(null, 2L);
|
||||
termIdCountCompareMap.put(1L, 2L);
|
||||
Assertions.assertEquals(termIdCountCompareMap, termIdCountMap);
|
||||
assertEquals(termIdCountCompareMap, termIdCountMap);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTranslate2List() {
|
||||
List<String> list = CollStreamUtil.toList(null, Student::getName);
|
||||
Assertions.assertEquals(list, Collections.EMPTY_LIST);
|
||||
assertEquals(Collections.EMPTY_LIST, list);
|
||||
final List<Student> students = new ArrayList<>();
|
||||
list = CollStreamUtil.toList(students, Student::getName);
|
||||
Assertions.assertEquals(list, Collections.EMPTY_LIST);
|
||||
assertEquals(Collections.EMPTY_LIST, list);
|
||||
students.add(new Student(1, 1, 1, "张三"));
|
||||
students.add(new Student(1, 2, 2, "李四"));
|
||||
students.add(new Student(2, 1, 1, "李四"));
|
||||
@@ -264,16 +269,16 @@ public class CollStreamUtilTest {
|
||||
compare.add("李四");
|
||||
compare.add("李四");
|
||||
compare.add("霸天虎");
|
||||
Assertions.assertEquals(list, compare);
|
||||
assertEquals(list, compare);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTranslate2Set() {
|
||||
Set<String> set = CollStreamUtil.toSet(null, Student::getName);
|
||||
Assertions.assertEquals(set, Collections.EMPTY_SET);
|
||||
assertEquals(Collections.EMPTY_SET, set);
|
||||
final List<Student> students = new ArrayList<>();
|
||||
set = CollStreamUtil.toSet(students, Student::getName);
|
||||
Assertions.assertEquals(set, Collections.EMPTY_SET);
|
||||
assertEquals(Collections.EMPTY_SET, set);
|
||||
students.add(new Student(1, 1, 1, "张三"));
|
||||
students.add(new Student(1, 2, 2, "李四"));
|
||||
students.add(new Student(2, 1, 1, "李四"));
|
||||
@@ -284,7 +289,7 @@ public class CollStreamUtilTest {
|
||||
compare.add("张三");
|
||||
compare.add("李四");
|
||||
compare.add("霸天虎");
|
||||
Assertions.assertEquals(set, compare);
|
||||
assertEquals(set, compare);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantValue")
|
||||
@@ -293,19 +298,19 @@ public class CollStreamUtilTest {
|
||||
Map<Long, Student> map1 = null;
|
||||
Map<Long, Student> map2 = Collections.emptyMap();
|
||||
Map<Long, String> map = CollStreamUtil.merge(map1, map2, (s1, s2) -> s1.getName() + s2.getName());
|
||||
Assertions.assertEquals(map, Collections.EMPTY_MAP);
|
||||
assertEquals(Collections.EMPTY_MAP, map);
|
||||
map1 = new HashMap<>();
|
||||
map1.put(1L, new Student(1, 1, 1, "张三"));
|
||||
map = CollStreamUtil.merge(map1, map2, this::merge);
|
||||
final Map<Long, String> temp = new HashMap<>();
|
||||
temp.put(1L, "张三");
|
||||
Assertions.assertEquals(map, temp);
|
||||
assertEquals(map, temp);
|
||||
map2 = new HashMap<>();
|
||||
map2.put(1L, new Student(2, 1, 1, "李四"));
|
||||
map = CollStreamUtil.merge(map1, map2, this::merge);
|
||||
final Map<Long, String> compare = new HashMap<>();
|
||||
compare.put(1L, "张三李四");
|
||||
Assertions.assertEquals(map, compare);
|
||||
assertEquals(map, compare);
|
||||
}
|
||||
|
||||
private String merge(final Student student1, final Student student2) {
|
||||
@@ -327,16 +332,16 @@ public class CollStreamUtilTest {
|
||||
sets.add(ListUtil.of("John", "Jack"));
|
||||
sets.add(ListUtil.of('I', 'J'));
|
||||
|
||||
final List<List<Object>> collect = CollStreamUtil.cartesianProduct(sets, 0).collect(Collectors.toList());
|
||||
Assertions.assertEquals(8, collect.size());
|
||||
Assertions.assertEquals("[10, John, I]", collect.get(0).toString());
|
||||
Assertions.assertEquals("[10, John, J]", collect.get(1).toString());
|
||||
Assertions.assertEquals("[10, Jack, I]", collect.get(2).toString());
|
||||
Assertions.assertEquals("[10, Jack, J]", collect.get(3).toString());
|
||||
Assertions.assertEquals("[20, John, I]", collect.get(4).toString());
|
||||
Assertions.assertEquals("[20, John, J]", collect.get(5).toString());
|
||||
Assertions.assertEquals("[20, Jack, I]", collect.get(6).toString());
|
||||
Assertions.assertEquals("[20, Jack, J]", collect.get(7).toString());
|
||||
final List<List<Object>> collect = CollStreamUtil.cartesianProduct(sets, 0).toList();
|
||||
assertEquals(8, collect.size());
|
||||
assertEquals("[10, John, I]", collect.get(0).toString());
|
||||
assertEquals("[10, John, J]", collect.get(1).toString());
|
||||
assertEquals("[10, Jack, I]", collect.get(2).toString());
|
||||
assertEquals("[10, Jack, J]", collect.get(3).toString());
|
||||
assertEquals("[20, John, I]", collect.get(4).toString());
|
||||
assertEquals("[20, John, J]", collect.get(5).toString());
|
||||
assertEquals("[20, Jack, I]", collect.get(6).toString());
|
||||
assertEquals("[20, Jack, J]", collect.get(7).toString());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -351,4 +356,38 @@ public class CollStreamUtilTest {
|
||||
private long studentId;//班级id
|
||||
private String name;//学生名称
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToMap_KeyCollision_SilentlyOverwrite() {
|
||||
final List<Student> list = new ArrayList<>();
|
||||
list.add(new Student(1, 101, 1, "张三"));
|
||||
list.add(new Student(1, 102, 1, "李四"));
|
||||
final Map<Long, String> map = CollStreamUtil.toMap(list, Student::getStudentId, Student::getName, false);
|
||||
|
||||
assertEquals(1, map.size());
|
||||
assertEquals("李四", map.get(1L)); // 确保后面的值覆盖前面的
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToMap_NullKeyOrValue() {
|
||||
final List<Student> list = new ArrayList<>();
|
||||
list.add(new Student(1, 1, 1L, "张三"));
|
||||
list.add(null);
|
||||
list.add(new Student(1, 2, 2L, null));
|
||||
|
||||
assertThrows(NullPointerException.class, () -> {
|
||||
CollStreamUtil.toMap(list, Student::getStudentId, Student::getName);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToMap_LargeInputPerformance() {
|
||||
final List<Student> list = new ArrayList<>();
|
||||
for (long i = 0; i < 10000; i++) {
|
||||
list.add(new Student(1, 1, i, "学生" + i));
|
||||
}
|
||||
final Map<Long, String> map = CollStreamUtil.toMap(list, Student::getStudentId, Student::getName);
|
||||
|
||||
assertEquals(10000, map.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1300,4 +1300,64 @@ public class CollUtilTest {
|
||||
assertTrue(subtract.contains(2));
|
||||
assertTrue(subtract.contains(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPadLeft_NegativeMinLen_ShouldNotModifyList() {
|
||||
final List<String> list = ListUtil.of("a", "b", "c");
|
||||
final List<String> original = ListUtil.of("a", "b", "c");
|
||||
|
||||
CollUtil.padLeft(list, -5, "x");
|
||||
|
||||
assertEquals(original, list, "List should remain unchanged when minLen is negative");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPadLeft_EmptyList_MinLenZero() {
|
||||
final List<String> list = ListUtil.of();
|
||||
|
||||
CollUtil.padLeft(list, 0, "x");
|
||||
|
||||
assertTrue(list.isEmpty(), "List should remain empty when minLen is 0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubtractWithDuplicates() {
|
||||
final Collection<String> coll1 = new ArrayList<>(Arrays.asList("a", "b", "b", "c"));
|
||||
final Collection<String> coll2 = Collections.singletonList("b");
|
||||
final Collection<String> result = CollUtil.subtract(coll1, coll2);
|
||||
|
||||
final List<String> expected = Arrays.asList("a", "c");
|
||||
final List<String> resultList = new ArrayList<>(result);
|
||||
Collections.sort(resultList);
|
||||
Collections.sort(expected);
|
||||
assertEquals(expected, resultList);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lastIndexOf_NoMatchExists() {
|
||||
final List<String> list = ListUtil.of("a", "b", "c");
|
||||
final int idx = CollUtil.lastIndexOf(list, item -> item.equals("z"));
|
||||
assertEquals(-1, idx);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lastIndexOf_MatcherIsNull_MatchAll() {
|
||||
final List<String> list = ListUtil.of("x", "y", "z");
|
||||
final int idx = CollUtil.lastIndexOf(list, null);
|
||||
assertEquals(2, idx);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lastIndexOf_EmptyCollection() {
|
||||
final List<String> list = ListUtil.of();
|
||||
final int idx = CollUtil.lastIndexOf(list, Objects::nonNull);
|
||||
assertEquals(-1, idx);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lastIndexOf_SingletonCollection_Match() {
|
||||
final List<String> list = ListUtil.of("foo");
|
||||
final int idx = CollUtil.lastIndexOf(list, item -> item.equals("foo"));
|
||||
assertEquals(0, idx);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -30,8 +30,7 @@ import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* {@link FileUtil} 单元测试类
|
||||
@@ -156,7 +155,7 @@ public class FileUtilTest {
|
||||
final File destFile1 = FileUtil.file("d:/hutool.jpg");
|
||||
|
||||
final boolean notEquals = FileUtil.equals(srcFile1, destFile1);
|
||||
Assertions.assertFalse(notEquals);
|
||||
assertFalse(notEquals);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -434,7 +433,7 @@ public class FileUtilTest {
|
||||
public void isSubTest() {
|
||||
final File file = new File("d:/test");
|
||||
final File file2 = new File("d:/test2/aaa");
|
||||
Assertions.assertFalse(FileUtil.isSub(file, file2));
|
||||
assertFalse(FileUtil.isSub(file, file2));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -507,7 +506,7 @@ public class FileUtilTest {
|
||||
assertTrue(FileUtil.isAbsolutePath(path));
|
||||
|
||||
path = "test\\aaa.txt";
|
||||
Assertions.assertFalse(FileUtil.isAbsolutePath(path));
|
||||
assertFalse(FileUtil.isAbsolutePath(path));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -536,4 +535,42 @@ public class FileUtilTest {
|
||||
FileUtil.checkSlip(FileUtil.file("test/a"), FileUtil.file("test/../a"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSub_SubIsAncestorOfParentTest() {
|
||||
final File parent = new File("d:/home/user/docs/notes");
|
||||
final File sub = new File("d:/home/user/docs");
|
||||
assertFalse(FileUtil.isSub(parent, sub));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSub_SamePathTest() {
|
||||
final File parent = new File("d:/home/user/docs");
|
||||
final File sub = new File("d:/home/user/docs");
|
||||
assertTrue(FileUtil.isSub(parent, sub));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSub_NonexistentPathsTest() {
|
||||
final File parent = new File("d:/unlikely/to/exist/parent");
|
||||
final File sub = new File("d:/unlikely/to/exist/parent/child/file.txt");
|
||||
assertTrue(FileUtil.isSub(parent, sub));
|
||||
|
||||
final File nonchild = new File("d:/also/unlikely/path.txt");
|
||||
assertFalse(FileUtil.isSub(parent, nonchild));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSub_NullParentTest() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
FileUtil.isSub(null, new java.io.File("d:/any/path"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSub_NullSubTest() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
FileUtil.isSub(new java.io.File("d:/any/path"), null);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-cron</artifactId>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-crypto</artifactId>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-db</artifactId>
|
||||
|
||||
@@ -26,6 +26,7 @@ import cn.hutool.v7.db.transaction.TransactionLevel;
|
||||
import cn.hutool.v7.log.LogUtil;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.io.Serial;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
@@ -37,6 +38,7 @@ import java.sql.SQLException;
|
||||
* @since 4.1.2
|
||||
*/
|
||||
public class Db extends AbstractDb<Db> {
|
||||
@Serial
|
||||
private static final long serialVersionUID = -3378415769645309514L;
|
||||
|
||||
// region ----- of
|
||||
|
||||
@@ -24,6 +24,7 @@ import cn.hutool.v7.db.dialect.DialectName;
|
||||
import cn.hutool.v7.db.sql.SqlBuilder;
|
||||
import cn.hutool.v7.db.sql.StatementUtil;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.util.Arrays;
|
||||
@@ -35,6 +36,7 @@ import java.util.List;
|
||||
* @author wb04307201
|
||||
*/
|
||||
public class DmDialect extends AnsiSqlDialect {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 3415348435502927423L;
|
||||
|
||||
/**
|
||||
@@ -78,7 +80,7 @@ public class DmDialect extends AnsiSqlDialect {
|
||||
// 构建字段部分和参数占位符部分
|
||||
entity.forEach((field, value) -> {
|
||||
if (StrUtil.isNotBlank(field) && keyList.contains(field)) {
|
||||
if (keyFieldsPart.length() > 0) {
|
||||
if (!keyFieldsPart.isEmpty()) {
|
||||
keyFieldsPart.append(" and ");
|
||||
}
|
||||
keyFieldsPart.append(field).append("= ?");
|
||||
@@ -88,7 +90,7 @@ public class DmDialect extends AnsiSqlDialect {
|
||||
|
||||
entity.forEach((field, value) -> {
|
||||
if (StrUtil.isNotBlank(field) && !keyList.contains(field)) {
|
||||
if (updateFieldsPart.length() > 0) {
|
||||
if (!updateFieldsPart.isEmpty()) {
|
||||
// 非第一个参数,追加逗号
|
||||
updateFieldsPart.append(", ");
|
||||
}
|
||||
@@ -99,7 +101,7 @@ public class DmDialect extends AnsiSqlDialect {
|
||||
|
||||
entity.forEach((field, value) -> {
|
||||
if (StrUtil.isNotBlank(field)) {
|
||||
if (insertFieldsPart.length() > 0) {
|
||||
if (!insertFieldsPart.isEmpty()) {
|
||||
// 非第一个参数,追加逗号
|
||||
insertFieldsPart.append(", ");
|
||||
insertPlaceHolder.append(", ");
|
||||
|
||||
@@ -26,6 +26,7 @@ import cn.hutool.v7.db.config.DbConfig;
|
||||
import cn.hutool.v7.db.dialect.DialectName;
|
||||
import cn.hutool.v7.db.sql.SqlBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
@@ -35,6 +36,7 @@ import java.sql.PreparedStatement;
|
||||
* @author loolly
|
||||
*/
|
||||
public class H2Dialect extends AnsiSqlDialect {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1490520247974768214L;
|
||||
|
||||
/**
|
||||
@@ -70,7 +72,7 @@ public class H2Dialect extends AnsiSqlDialect {
|
||||
// 构建字段部分和参数占位符部分
|
||||
entity.forEach((field, value) -> {
|
||||
if (StrUtil.isNotBlank(field)) {
|
||||
if (fieldsPart.length() > 0) {
|
||||
if (!fieldsPart.isEmpty()) {
|
||||
// 非第一个参数,追加逗号
|
||||
fieldsPart.append(", ");
|
||||
placeHolder.append(", ");
|
||||
|
||||
@@ -25,6 +25,7 @@ import cn.hutool.v7.db.sql.QuoteWrapper;
|
||||
import cn.hutool.v7.db.sql.SqlBuilder;
|
||||
import cn.hutool.v7.db.sql.StatementUtil;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.util.ArrayList;
|
||||
@@ -37,6 +38,7 @@ import java.util.List;
|
||||
* @author daoyou.dev
|
||||
*/
|
||||
public class HanaDialect extends AnsiSqlDialect {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,12 +23,15 @@ import cn.hutool.v7.db.config.DbConfig;
|
||||
import cn.hutool.v7.db.dialect.DialectName;
|
||||
import cn.hutool.v7.db.sql.SqlBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* Oracle 方言
|
||||
*
|
||||
* @author loolly
|
||||
*/
|
||||
public class OracleDialect extends AnsiSqlDialect {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 6122761762247483015L;
|
||||
|
||||
private static final String DEFAULT_TABLE_ALIAS = "table_alias_";
|
||||
|
||||
@@ -22,6 +22,7 @@ import cn.hutool.v7.db.config.DbConfig;
|
||||
import cn.hutool.v7.db.dialect.DialectName;
|
||||
import cn.hutool.v7.db.sql.Query;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
@@ -32,6 +33,7 @@ import java.sql.PreparedStatement;
|
||||
* @since 5.7.2
|
||||
*/
|
||||
public class PhoenixDialect extends AnsiSqlDialect {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,6 +27,7 @@ import cn.hutool.v7.db.dialect.DialectName;
|
||||
import cn.hutool.v7.db.sql.QuoteWrapper;
|
||||
import cn.hutool.v7.db.sql.SqlBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
@@ -37,6 +38,7 @@ import java.sql.PreparedStatement;
|
||||
* @author loolly
|
||||
*/
|
||||
public class PostgresqlDialect extends AnsiSqlDialect {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 3889210427543389642L;
|
||||
|
||||
/**
|
||||
@@ -66,7 +68,7 @@ public class PostgresqlDialect extends AnsiSqlDialect {
|
||||
// 构建字段部分和参数占位符部分
|
||||
entity.forEach((field, value) -> {
|
||||
if (StrUtil.isNotBlank(field)) {
|
||||
if (fieldsPart.length() > 0) {
|
||||
if (!fieldsPart.isEmpty()) {
|
||||
// 非第一个参数,追加逗号
|
||||
fieldsPart.append(", ");
|
||||
placeHolder.append(", ");
|
||||
|
||||
@@ -24,6 +24,8 @@ import cn.hutool.v7.db.dialect.DialectName;
|
||||
import cn.hutool.v7.db.sql.QuoteWrapper;
|
||||
import cn.hutool.v7.db.sql.SqlBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* SQLServer2005-2008方言实现<br>
|
||||
* 参考:jdbc-plus
|
||||
@@ -31,6 +33,7 @@ import cn.hutool.v7.db.sql.SqlBuilder;
|
||||
* @author niliwei, Looly
|
||||
*/
|
||||
public class SqlServer2005Dialect extends AnsiSqlDialect {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String DEFAULT_TABLE_ALIAS = "table_alias_";
|
||||
|
||||
@@ -23,12 +23,15 @@ import cn.hutool.v7.db.dialect.DialectName;
|
||||
import cn.hutool.v7.db.sql.SqlBuilder;
|
||||
import cn.hutool.v7.db.sql.QuoteWrapper;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* SQLServer2012 方言
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
public class SqlServer2012Dialect extends AnsiSqlDialect {
|
||||
@Serial
|
||||
private static final long serialVersionUID = -37598166015777797L;
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,12 +20,15 @@ import cn.hutool.v7.db.config.DbConfig;
|
||||
import cn.hutool.v7.db.dialect.DialectName;
|
||||
import cn.hutool.v7.db.sql.QuoteWrapper;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* SqlLite3方言
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
public class Sqlite3Dialect extends AnsiSqlDialect {
|
||||
@Serial
|
||||
private static final long serialVersionUID = -3527642408849291634L;
|
||||
|
||||
/**
|
||||
|
||||
@@ -108,6 +108,8 @@ public class DriverIdentifier implements DriverNames {
|
||||
new StartsWithDriverMatcher(DRIVER_KINGBASE8, "jdbc:kingbase8:"),
|
||||
// 南大通用
|
||||
new StartsWithDriverMatcher(DRIVER_GBASE, "jdbc:gbase:"),
|
||||
// 南大通用8s
|
||||
new StartsWithDriverMatcher(DRIVER_GBASE8S, "jdbc:gbasedbt-sqli:"),
|
||||
// 虚谷
|
||||
new StartsWithDriverMatcher(DRIVER_XUGU, "jdbc:xugu:"),
|
||||
// 神通
|
||||
|
||||
@@ -128,6 +128,11 @@ public interface DriverNames {
|
||||
* JDBC 驱动 南大通用
|
||||
*/
|
||||
String DRIVER_GBASE = "com.gbase.jdbc.Driver";
|
||||
/**
|
||||
* JDBC 驱动 南大通用8S<br>
|
||||
* 见:https://www.gbase.cn/community/post/4029
|
||||
*/
|
||||
String DRIVER_GBASE8S = "com.gbasedbt.jdbc.Driver";
|
||||
/**
|
||||
* JDBC 驱动 神州数据库
|
||||
*/
|
||||
|
||||
@@ -114,7 +114,7 @@ public class NamedSql extends BoundSql {
|
||||
}
|
||||
|
||||
// 收尾,如果SQL末尾存在变量,处理之
|
||||
if (name.length() > 0) {
|
||||
if (!name.isEmpty()) {
|
||||
replaceVar(nameStartChar, name, sqlBuilder, paramMap);
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ public class NamedSql extends BoundSql {
|
||||
* @param paramMap 变量map(非空)
|
||||
*/
|
||||
private void replaceVar(final Character nameStartChar, final StringBuilder name, final StringBuilder sqlBuilder, final Map<String, Object> paramMap) {
|
||||
if (name.length() == 0) {
|
||||
if (name.isEmpty()) {
|
||||
if (null != nameStartChar) {
|
||||
// 类似于:的情况,需要补上:
|
||||
sqlBuilder.append(nameStartChar);
|
||||
|
||||
@@ -25,6 +25,7 @@ import cn.hutool.v7.db.Entity;
|
||||
import cn.hutool.v7.db.dialect.DialectName;
|
||||
import cn.hutool.v7.db.dialect.impl.OracleDialect;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -39,6 +40,7 @@ import java.util.List;
|
||||
* @author Looly
|
||||
*/
|
||||
public class SqlBuilder implements Builder<String> {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// --------------------------------------------------------------- Static methods start
|
||||
@@ -191,7 +193,7 @@ public class SqlBuilder implements Builder<String> {
|
||||
|
||||
entity.forEach((field, value) -> {
|
||||
if (StrUtil.isNotBlank(field)) {
|
||||
if (fieldsPart.length() > 0) {
|
||||
if (!fieldsPart.isEmpty()) {
|
||||
// 非第一个参数,追加逗号
|
||||
fieldsPart.append(", ");
|
||||
placeHolder.append(", ");
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-extra</artifactId>
|
||||
@@ -70,6 +70,7 @@
|
||||
<kafka.version>4.0.0</kafka.version>
|
||||
<rabbitmq.version>5.25.0</rabbitmq.version>
|
||||
<rocketmq.version>5.3.3</rocketmq.version>
|
||||
<activemq.version>6.1.7</activemq.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -554,5 +555,11 @@
|
||||
<version>${rocketmq.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-client</artifactId>
|
||||
<version>${activemq.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -39,7 +39,6 @@ public interface Consumer extends Closeable {
|
||||
*
|
||||
* @param messageHandler 消息处理器
|
||||
*/
|
||||
@SuppressWarnings("InfiniteLoopStatement")
|
||||
default void listen(final MessageHandler messageHandler) {
|
||||
ThreadUtil.execAsync(() -> {
|
||||
for(;;) {
|
||||
|
||||
@@ -18,6 +18,7 @@ package cn.hutool.v7.extra.mq;
|
||||
|
||||
import cn.hutool.v7.extra.mq.engine.MQEngine;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Properties;
|
||||
|
||||
@@ -28,6 +29,7 @@ import java.util.Properties;
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class MQConfig implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,12 +18,15 @@ package cn.hutool.v7.extra.mq;
|
||||
|
||||
import cn.hutool.v7.core.exception.HutoolException;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 消息队列异常
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
public class MQException extends HutoolException {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package cn.hutool.v7.extra.mq.engine.activemq;
|
||||
|
||||
import cn.hutool.v7.core.lang.Assert;
|
||||
import cn.hutool.v7.extra.mq.MQConfig;
|
||||
import cn.hutool.v7.extra.mq.engine.jms.JmsEngine;
|
||||
import jakarta.jms.ConnectionFactory;
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
|
||||
/**
|
||||
* ActiveMQ引擎
|
||||
*
|
||||
* @author Looly
|
||||
* @since 7.0.0
|
||||
*/
|
||||
public class ActiveMQEngine extends JmsEngine {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public ActiveMQEngine() {
|
||||
// SPI方式加载时检查库是否引入
|
||||
Assert.notNull(org.apache.activemq.ActiveMQConnectionFactory.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConnectionFactory createConnectionFactory(final MQConfig config) {
|
||||
return new ActiveMQConnectionFactory(config.getBrokerUrl());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ActiveMQ消息队列引擎
|
||||
*
|
||||
* @author Looly
|
||||
* @since 7.0.0
|
||||
*/
|
||||
package cn.hutool.v7.extra.mq.engine.activemq;
|
||||
@@ -0,0 +1,85 @@
|
||||
package cn.hutool.v7.extra.mq.engine.jms;
|
||||
|
||||
import cn.hutool.v7.core.io.IoUtil;
|
||||
import cn.hutool.v7.core.util.ByteUtil;
|
||||
import cn.hutool.v7.extra.mq.Consumer;
|
||||
import cn.hutool.v7.extra.mq.MQException;
|
||||
import cn.hutool.v7.extra.mq.Message;
|
||||
import cn.hutool.v7.extra.mq.MessageHandler;
|
||||
import jakarta.jms.BytesMessage;
|
||||
import jakarta.jms.JMSException;
|
||||
import jakarta.jms.MessageConsumer;
|
||||
import jakarta.jms.TextMessage;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* JMS消息消费者
|
||||
*
|
||||
* @author Looly
|
||||
* @since 7.0.0
|
||||
*/
|
||||
public class JmsConsumer implements Consumer {
|
||||
|
||||
private String consumerGroup;
|
||||
private final MessageConsumer consumer;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param consumerGroup 消费者组
|
||||
* @param consumer 消费者
|
||||
*/
|
||||
public JmsConsumer(final String consumerGroup, final MessageConsumer consumer) {
|
||||
this.consumerGroup = consumerGroup;
|
||||
this.consumer = consumer;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置消费者组
|
||||
*
|
||||
* @param consumerGroup 消费者组
|
||||
* @return this
|
||||
*/
|
||||
public JmsConsumer setConsumerGroup(final String consumerGroup) {
|
||||
this.consumerGroup = consumerGroup;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(final MessageHandler messageHandler) {
|
||||
try {
|
||||
this.consumer.setMessageListener(message -> {
|
||||
messageHandler.handle(new Message() {
|
||||
@Override
|
||||
public String topic() {
|
||||
return consumerGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] content() {
|
||||
try {
|
||||
if (message instanceof TextMessage) {
|
||||
// TODO 考虑编码
|
||||
return ByteUtil.toUtf8Bytes(((TextMessage) message).getText());
|
||||
} else if (message instanceof BytesMessage) {
|
||||
return new byte[(int) ((BytesMessage) message).getBodyLength()];
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported message type: " + message.getClass().getName());
|
||||
}
|
||||
} catch (final JMSException e) {
|
||||
throw new MQException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (final JMSException e) {
|
||||
throw new MQException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
IoUtil.closeQuietly(this.consumer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package cn.hutool.v7.extra.mq.engine.jms;
|
||||
|
||||
import cn.hutool.v7.core.io.IoUtil;
|
||||
import cn.hutool.v7.extra.mq.Consumer;
|
||||
import cn.hutool.v7.extra.mq.MQConfig;
|
||||
import cn.hutool.v7.extra.mq.MQException;
|
||||
import cn.hutool.v7.extra.mq.Producer;
|
||||
import cn.hutool.v7.extra.mq.engine.MQEngine;
|
||||
import jakarta.jms.*;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* JMS(Java Message Service)引擎
|
||||
*
|
||||
* @author Looly
|
||||
* @since 7.0.0
|
||||
*/
|
||||
public abstract class JmsEngine implements MQEngine, Closeable {
|
||||
|
||||
private Connection connection;
|
||||
private Session session;
|
||||
private boolean isTopic;
|
||||
private String producerGroup = "hutool.queue";
|
||||
private String consumerGroup = "hutool.queue";
|
||||
|
||||
@Override
|
||||
public MQEngine init(final MQConfig config) {
|
||||
try {
|
||||
this.connection = createConnectionFactory(config).createConnection();
|
||||
this.session = this.connection.createSession();
|
||||
} catch (final JMSException e) {
|
||||
throw new MQException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建ConnectionFactory
|
||||
*
|
||||
* @param config 配置
|
||||
* @return ConnectionFactory
|
||||
*/
|
||||
protected abstract ConnectionFactory createConnectionFactory(final MQConfig config);
|
||||
|
||||
/**
|
||||
* 设置是否Topic
|
||||
*
|
||||
* @param isTopic 是否Topic
|
||||
* @return this
|
||||
*/
|
||||
public JmsEngine setTopic(final boolean isTopic) {
|
||||
this.isTopic = isTopic;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置生产者组
|
||||
*
|
||||
* @param producerGroup 生产者组
|
||||
* @return this
|
||||
*/
|
||||
public JmsEngine setProducerGroup(final String producerGroup) {
|
||||
this.producerGroup = producerGroup;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置消费者组
|
||||
*
|
||||
* @param consumerGroup 消费者组
|
||||
* @return this
|
||||
*/
|
||||
public JmsEngine setConsumerGroup(final String consumerGroup) {
|
||||
this.consumerGroup = consumerGroup;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Producer getProducer() {
|
||||
final MessageProducer messageProducer;
|
||||
try {
|
||||
messageProducer = this.session.createProducer(createDestination(producerGroup));
|
||||
} catch (final JMSException e) {
|
||||
throw new MQException(e);
|
||||
}
|
||||
|
||||
return new JmsProducer(this.session, messageProducer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer getConsumer() {
|
||||
final MessageConsumer messageConsumer;
|
||||
try {
|
||||
messageConsumer = this.session.createConsumer(createDestination(consumerGroup));
|
||||
} catch (final JMSException e) {
|
||||
throw new MQException(e);
|
||||
}
|
||||
|
||||
return new JmsConsumer(this.consumerGroup, messageConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
IoUtil.closeQuietly(this.session);
|
||||
IoUtil.closeQuietly(this.connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Destination
|
||||
*
|
||||
* @param group 组
|
||||
* @return Destination
|
||||
*/
|
||||
private Destination createDestination(final String group) {
|
||||
try {
|
||||
return isTopic ? this.session.createTopic(group) : this.session.createQueue(group);
|
||||
} catch (final JMSException e) {
|
||||
throw new MQException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package cn.hutool.v7.extra.mq.engine.jms;
|
||||
|
||||
import cn.hutool.v7.core.io.IoUtil;
|
||||
import cn.hutool.v7.extra.mq.MQException;
|
||||
import cn.hutool.v7.extra.mq.Message;
|
||||
import cn.hutool.v7.extra.mq.Producer;
|
||||
import jakarta.jms.BytesMessage;
|
||||
import jakarta.jms.JMSException;
|
||||
import jakarta.jms.MessageProducer;
|
||||
import jakarta.jms.Session;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* JMS消息生产者
|
||||
*
|
||||
* @author looly
|
||||
* @since 7.0.0
|
||||
*/
|
||||
public class JmsProducer implements Producer {
|
||||
|
||||
private final Session session;
|
||||
private final MessageProducer producer;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param session JMS会话
|
||||
* @param producer JMS消息生产者
|
||||
*/
|
||||
public JmsProducer(final Session session, final MessageProducer producer) {
|
||||
this.session = session;
|
||||
this.producer = producer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(final Message message) {
|
||||
final BytesMessage bytesMessage;
|
||||
try {
|
||||
bytesMessage = this.session.createBytesMessage();
|
||||
bytesMessage.writeBytes(message.content());
|
||||
this.producer.send(bytesMessage);
|
||||
} catch (final JMSException e) {
|
||||
throw new MQException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
IoUtil.closeQuietly(this.producer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JMS(Java Message Service)消息队列引擎
|
||||
*
|
||||
* @author Looly
|
||||
* @since 7.0.0
|
||||
*/
|
||||
package cn.hutool.v7.extra.mq.engine.jms;
|
||||
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-http</artifactId>
|
||||
|
||||
@@ -17,12 +17,20 @@
|
||||
package cn.hutool.v7.http;
|
||||
|
||||
import cn.hutool.v7.core.net.url.UrlBuilder;
|
||||
import cn.hutool.v7.core.text.CharUtil;
|
||||
import cn.hutool.v7.core.text.StrUtil;
|
||||
import cn.hutool.v7.core.text.split.SplitUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* HTTP URL工具类
|
||||
*
|
||||
* @author looly
|
||||
* @since 7.0.0
|
||||
*/
|
||||
public class HttpUrlUtil {
|
||||
|
||||
/**
|
||||
* 获取转发的新的URL
|
||||
*
|
||||
@@ -35,8 +43,11 @@ public class HttpUrlUtil {
|
||||
if (!HttpUtil.isHttp(location) && !HttpUtil.isHttps(location)) {
|
||||
// issue#I5TPSY
|
||||
// location可能为相对路径
|
||||
if (!location.startsWith("/")) {
|
||||
location = StrUtil.addSuffixIfNot(parentUrl.getPathStr(), "/") + location;
|
||||
if (!location.startsWith(StrUtil.SLASH)) {
|
||||
// issue#ICSG7D 如果当前路径以/结尾,直接拼接,否则去除最后一个节点
|
||||
String pathStr = parentUrl.getPathStr();
|
||||
pathStr = StrUtil.subBefore(pathStr, CharUtil.SLASH, true);
|
||||
location = pathStr + StrUtil.SLASH + location;
|
||||
}
|
||||
|
||||
// issue#3265, 相对路径中可能存在参数,单独处理参数
|
||||
|
||||
@@ -235,7 +235,7 @@ public class SunServerRequest extends SunServerExchangeBase implements ServerReq
|
||||
public String getClientIP(final String... otherHeaderNames) {
|
||||
String[] headers = {"X-Forwarded-For", "X-Real-IP", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"};
|
||||
if (ArrayUtil.isNotEmpty(otherHeaderNames)) {
|
||||
headers = ArrayUtil.addAll(headers, otherHeaderNames);
|
||||
headers = ArrayUtil.addAll(otherHeaderNames, headers);
|
||||
}
|
||||
|
||||
return getClientIPByHeader(headers);
|
||||
|
||||
@@ -211,7 +211,7 @@ public class ServletUtil {
|
||||
public static String getClientIP(final HttpServletRequest request, final String... otherHeaderNames) {
|
||||
String[] headers = {"X-Forwarded-For", "X-Real-IP", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"};
|
||||
if (ArrayUtil.isNotEmpty(otherHeaderNames)) {
|
||||
headers = ArrayUtil.addAll(headers, otherHeaderNames);
|
||||
headers = ArrayUtil.addAll(otherHeaderNames, headers);
|
||||
}
|
||||
|
||||
return getClientIPByHeader(request, headers);
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-json</artifactId>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-log</artifactId>
|
||||
|
||||
@@ -20,6 +20,11 @@ import cn.hutool.v7.log.level.Level;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 日志门面单元测试
|
||||
* @author Looly
|
||||
@@ -60,4 +65,45 @@ public class LogTest {
|
||||
void getLogByClassTest() {
|
||||
Log.get(LogTest.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterizedMessageEdgeCasesTest() {
|
||||
final Log log = Log.get();
|
||||
|
||||
// 测试不同数量的参数
|
||||
log.info("No parameters");
|
||||
log.info("One: {}", "param1");
|
||||
log.info("Two: {} and {}", "param1", "param2");
|
||||
log.info("Three: {}, {}, {}", "param1", "param2", "param3");
|
||||
log.info("Four: {}, {}, {}, {}", "param1", "param2", "param3", "param4");
|
||||
|
||||
// 测试参数不足的情况
|
||||
log.info("Missing param: {} and {}", "only_one");
|
||||
|
||||
// 测试参数过多的情况
|
||||
log.info("Extra param: {}", "param1", "extra_param");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void i18nMessageTest() {
|
||||
final Log log = Log.get();
|
||||
// 国际化消息测试
|
||||
log.info("中文消息测试");
|
||||
log.info("Message with unicode: {}", "特殊字符©®™✓✗★☆");
|
||||
log.info("多语言混排: 中文, English, 日本語, 한글");
|
||||
log.info("Emoji测试: 😀🚀🌏");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void complexObjectTest() {
|
||||
final Log log = Log.get();
|
||||
// 复杂对象参数测试
|
||||
final List<String> list = Arrays.asList("item1", "item2");
|
||||
final Map<String, Object> map = new HashMap<>();
|
||||
map.put("key", "value");
|
||||
|
||||
log.info("List: {}", list);
|
||||
log.info("Map: {}", map);
|
||||
log.info("Null object: {}", (Object)null);
|
||||
}
|
||||
}
|
||||
|
||||
BIN
hutool-poi/d:/test/comments.xlsx
Normal file
BIN
hutool-poi/d:/test/comments.xlsx
Normal file
Binary file not shown.
BIN
hutool-poi/d:/test/templateWriter/templateResult.xlsx
Normal file
BIN
hutool-poi/d:/test/templateWriter/templateResult.xlsx
Normal file
Binary file not shown.
Binary file not shown.
BIN
hutool-poi/d:/test/templateWriter/templateWithFooterResult.xlsx
Normal file
BIN
hutool-poi/d:/test/templateWriter/templateWithFooterResult.xlsx
Normal file
Binary file not shown.
Binary file not shown.
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-poi</artifactId>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-setting</artifactId>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-socket</artifactId>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-swing</artifactId>
|
||||
|
||||
8
pom.xml
8
pom.xml
@@ -24,7 +24,7 @@
|
||||
|
||||
<groupId>cn.hutool.v7</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>7.0.0-M1</version>
|
||||
<version>7.0.0-M2</version>
|
||||
<name>hutool</name>
|
||||
<description>
|
||||
Hutool是一个功能丰富且易用的Java工具库,通过诸多实用工具类的使用,旨在帮助开发者快速、便捷地完成各类开发任务。这些封装的工具涵盖了字符串、数字、集合、编码、日期、文件、IO、加密、数据库JDBC、JSON、HTTP客户端等一系列操作,可以满足各种不同的开发需求。
|
||||
@@ -290,11 +290,11 @@
|
||||
<version>0.8.0</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<publishingServerId>central6</publishingServerId>
|
||||
<publishingServerId>central</publishingServerId>
|
||||
<!-- 自动发布 -->
|
||||
<autoPublish>true</autoPublish>
|
||||
<autoPublish>false</autoPublish>
|
||||
<!-- 等待发布 -->
|
||||
<waitUntil>published</waitUntil>
|
||||
<!-- <waitUntil>published</waitUntil> -->
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
Reference in New Issue
Block a user