Compare commits
44 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c10c144f64 | ||
![]() |
0b072015da | ||
![]() |
8d34a4d26e | ||
![]() |
c94e3baa28 | ||
![]() |
2046809264 | ||
![]() |
1c3e8634c8 | ||
![]() |
150f8930d0 | ||
![]() |
5b34544b8f | ||
![]() |
2c810d92bf | ||
![]() |
b2c0d74dd7 | ||
![]() |
fcf78229c4 | ||
![]() |
a74b2f8b0f | ||
![]() |
c41612d21d | ||
![]() |
b9425a3b2b | ||
![]() |
bb810d2d64 | ||
![]() |
4c6c3b057a | ||
![]() |
520b128f1c | ||
![]() |
732bea6d0b | ||
![]() |
10f02bb9bc | ||
![]() |
f697141cab | ||
![]() |
bd94c09e91 | ||
![]() |
1aec0973f8 | ||
![]() |
cb0abbbbd5 | ||
![]() |
dc038f2356 | ||
![]() |
22314d80f9 | ||
![]() |
220148d555 | ||
![]() |
1c0b6c3da1 | ||
![]() |
4ef8814c14 | ||
![]() |
05f16f051e | ||
![]() |
bfad067365 | ||
![]() |
72277a1a6a | ||
![]() |
63d5a6ead6 | ||
![]() |
41e52de401 | ||
![]() |
df4683378f | ||
![]() |
0154e72eaa | ||
![]() |
455a555f43 | ||
![]() |
cc5b8a290c | ||
![]() |
6e83e67a4a | ||
![]() |
f3c97bdc4d | ||
![]() |
7608e08c2e | ||
![]() |
35f0e368d2 | ||
![]() |
05e68b9683 | ||
![]() |
b0e1302332 | ||
![]() |
e6efa72cee |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@ -1,4 +1,4 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [looly]
|
||||
custom: ['https://gitee.com/dromara/hutool', 'https://dromara.gitee.io/donate.html']
|
||||
custom: ['https://gitee.com/chinabugotech/hutool']
|
||||
|
20
CHANGELOG.md
20
CHANGELOG.md
@ -1,6 +1,24 @@
|
||||
|
||||
# 🚀Changelog
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
# 5.8.37(2025-03-07)
|
||||
|
||||
### 🐣新特性
|
||||
* 【json 】 ObjectMapper删除重复trim(pr#3859@Github)
|
||||
* 【core 】 `FileWriter`增加方法,可选是否追加换行符(issue#3858@Github)
|
||||
* 【core 】 `IdcardUtil`验证10位身份证兼容中英文括号(issue#IBP6T1@Gitee)
|
||||
* 【extra 】 `PinyinUtil`增加重载可选是否返回声调(pr#3875@Github)
|
||||
* 【http 】 `HttpBase`增加重载可选是否返回声调(pr#3883@Github)
|
||||
* 【core 】 增加`VersionUtil`版本比较工具(pr#3876@Github)
|
||||
* 【db 】 增加GoldenDB识别(pr#3886@Github)
|
||||
|
||||
### 🐞Bug修复
|
||||
* 【setting】 修复`SettingLoader`load未抛出异常导致配置文件无法正常遍历的问题(pr#3868@Github)
|
||||
* 【cache 】 修复`ReentrantCache#getOrRemoveExpired`方法丢失onRemove触发问题(pr#1315@Gitee)
|
||||
* 【json 】 修复`JsonUtil.toBean`泛型数组类型丢失问题(pr#3876@Github)
|
||||
* 【http 】 修复`HttpUtil.normalizeParams`规则问题(issue#IBQIYQ@Gitee)
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
# 5.8.36(2025-02-18)
|
||||
|
||||
@ -1081,4 +1099,4 @@
|
||||
* 【core 】 修复农历转公历在闰月时错误(issue#I4ZSGJ@Gitee)
|
||||
|
||||
# 5.7.x 或更早版本
|
||||
* [https://gitee.com/dromara/hutool/blob/v5-master/CHANGELOG_5.0-5.7.md](https://gitee.com/dromara/hutool/blob/v5-master/CHANGELOG_5.0-5.7.md)
|
||||
* [https://gitee.com/chinabugotech/hutool/blob/v5-master/CHANGELOG_5.0-5.7.md](https://gitee.com/chinabugotech/hutool/blob/v5-master/CHANGELOG_5.0-5.7.md)
|
60
README-EN.md
60
README-EN.md
@ -18,26 +18,26 @@
|
||||
<a target="_blank" href="https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html">
|
||||
<img src="https://img.shields.io/badge/JDK-8+-green.svg" />
|
||||
</a>
|
||||
<a target="_blank" href="https://travis-ci.com/dromara/hutool">
|
||||
<img src="https://travis-ci.com/dromara/hutool.svg?branch=v5-master" />
|
||||
<a target="_blank" href="https://travis-ci.com/chinabugotech/hutool">
|
||||
<img src="https://travis-ci.com/chinabugotech/hutool.svg?branch=v5-master" />
|
||||
</a>
|
||||
<a href="https://www.codacy.com/gh/dromara/hutool/dashboard?utm_source=github.com&utm_medium=referral&utm_content=dromara/hutool&utm_campaign=Badge_Grade">
|
||||
<a href="https://www.codacy.com/gh/chinabugotech/hutool/dashboard?utm_source=github.com&utm_medium=referral&utm_content=chinabugotech/hutool&utm_campaign=Badge_Grade">
|
||||
<img src="https://app.codacy.com/project/badge/Grade/8a6897d9de7440dd9de8804c28d2871d"/>
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/dromara/hutool">
|
||||
<img src="https://codecov.io/gh/dromara/hutool/branch/v5-master/graph/badge.svg" />
|
||||
<a href="https://codecov.io/gh/chinabugotech/hutool">
|
||||
<img src="https://codecov.io/gh/chinabugotech/hutool/branch/v5-master/graph/badge.svg" />
|
||||
</a>
|
||||
<a target="_blank" href="https://gitter.im/hutool/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge">
|
||||
<img src="https://badges.gitter.im/hutool/Lobby.svg" />
|
||||
</a>
|
||||
<a target="_blank" href='https://gitee.com/dromara/hutool/stargazers'>
|
||||
<img src='https://gitee.com/dromara/hutool/badge/star.svg?theme=gvp' alt='star'/>
|
||||
<a target="_blank" href='https://gitee.com/chinabugotech/hutool/stargazers'>
|
||||
<img src='https://gitee.com/chinabugotech/hutool/badge/star.svg?theme=gvp' alt='star'/>
|
||||
</a>
|
||||
<a target="_blank" href='https://github.com/dromara/hutool'>
|
||||
<img src="https://img.shields.io/github/stars/dromara/hutool.svg?style=social" alt="github star"/>
|
||||
<a target="_blank" href='https://github.com/chinabugotech/hutool'>
|
||||
<img src="https://img.shields.io/github/stars/chinabugotech/hutool.svg?style=social" alt="github star"/>
|
||||
</a>
|
||||
<a target="_blank" href='https://gitcode.com/dromara/hutool'>
|
||||
<img src="https://gitcode.com/dromara/hutool/star/badge.svg" alt="gitcode star"/>
|
||||
<a target="_blank" href='https://gitcode.com/chinabugotech/hutool'>
|
||||
<img src="https://gitcode.com/chinabugotech/hutool/star/badge.svg" alt="gitcode star"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@ -49,11 +49,7 @@
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
<p align="center">
|
||||
<a href="#"><img style="width: 45%" alt="" src="https://plus.hutool.cn/images/zanzhu.jpg"/></a>
|
||||
</p>
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
[**🌎中文说明**](README.md)
|
||||
|
||||
@ -128,23 +124,7 @@ Each module can be introduced individually, or all modules can be introduced by
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 🪙Support Hutool
|
||||
|
||||
### 💳Donate
|
||||
|
||||
If you think Hutool is good, you can donate to buy the author a pack of chili~, thanks in advance ^_^.
|
||||
|
||||
[Gitee donate](https://gitee.com/dromara/hutool)
|
||||
|
||||
[Dromara donate](https://dromara.gitee.io/donate.html)
|
||||
|
||||
### 👕Shop about Hutool
|
||||
|
||||
We provide the T-Shirt and Sweater with Hutool Logo, please visit the shop:
|
||||
|
||||
👉 [Hutool Shop](https://market.m.taobao.com/apps/market/content/index.html?wh_weex=true&contentId=331724720170) 👈
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 📦Install
|
||||
|
||||
@ -153,18 +133,18 @@ We provide the T-Shirt and Sweater with Hutool Logo, please visit the shop:
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.36</version>
|
||||
<version>5.8.37</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### 🍐Gradle
|
||||
```
|
||||
implementation 'cn.hutool:hutool-all:5.8.36'
|
||||
implementation 'cn.hutool:hutool-all:5.8.37'
|
||||
```
|
||||
|
||||
## 📥Download
|
||||
|
||||
- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.36/)
|
||||
- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.37/)
|
||||
|
||||
> 🔔️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.
|
||||
@ -174,9 +154,9 @@ implementation 'cn.hutool:hutool-all:5.8.36'
|
||||
|
||||
Download the entire project source code
|
||||
|
||||
gitee:[https://gitee.com/dromara/hutool](https://gitee.com/dromara/hutool)
|
||||
gitee:[https://gitee.com/chinabugotech/hutool](https://gitee.com/chinabugotech/hutool)
|
||||
|
||||
github:[https://github.com/dromara/hutool](https://github.com/dromara/hutool)
|
||||
github:[https://github.com/chinabugotech/hutool](https://github.com/chinabugotech/hutool)
|
||||
|
||||
```sh
|
||||
cd ${hutool}
|
||||
@ -200,9 +180,9 @@ Hutool's source code is divided into two branches:
|
||||
|
||||
When submitting feedback, please indicate which JDK version, Hutool version, and related dependency library version you are using.
|
||||
|
||||
- [Gitee issue](https://gitee.com/dromara/hutool/issues)
|
||||
- [Github issue](https://github.com/dromara/hutool/issues)
|
||||
- [Gitcode issue](https://gitcode.com/dromara/hutool/issues)
|
||||
- [Gitee issue](https://gitee.com/chinabugotech/hutool/issues)
|
||||
- [Github issue](https://github.com/chinabugotech/hutool/issues)
|
||||
- [Gitcode issue](https://gitcode.com/chinabugotech/hutool/issues)
|
||||
|
||||
### 🧬Principles of PR(pull request)
|
||||
|
||||
@ -221,4 +201,4 @@ Hutool welcomes anyone to contribute code to Hutool, but the author suffers from
|
||||
|
||||
## ⭐Star Hutool
|
||||
|
||||
[](https://starchart.cc/dromara/hutool)
|
||||
[](https://starchart.cc/chinabugotech/hutool)
|
||||
|
63
README.md
63
README.md
@ -18,26 +18,23 @@
|
||||
<a target="_blank" href="https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html">
|
||||
<img src="https://img.shields.io/badge/JDK-8+-green.svg" />
|
||||
</a>
|
||||
<a target="_blank" href="https://travis-ci.com/dromara/hutool">
|
||||
<img src="https://travis-ci.com/dromara/hutool.svg?branch=v5-master" />
|
||||
<a target="_blank" href="https://travis-ci.com/chinabugotech/hutool">
|
||||
<img src="https://travis-ci.com/chinabugotech/hutool.svg?branch=v5-master" />
|
||||
</a>
|
||||
<a href="https://www.codacy.com/gh/dromara/hutool/dashboard?utm_source=github.com&utm_medium=referral&utm_content=dromara/hutool&utm_campaign=Badge_Grade">
|
||||
<a href="https://www.codacy.com/gh/chinabugotech/hutool/dashboard?utm_source=github.com&utm_medium=referral&utm_content=chinabugotech/hutool&utm_campaign=Badge_Grade">
|
||||
<img src="https://app.codacy.com/project/badge/Grade/8a6897d9de7440dd9de8804c28d2871d"/>
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/dromara/hutool">
|
||||
<img src="https://codecov.io/gh/dromara/hutool/branch/v5-master/graph/badge.svg" />
|
||||
<a href="https://codecov.io/gh/chinabugotech/hutool">
|
||||
<img src="https://codecov.io/gh/chinabugotech/hutool/branch/v5-master/graph/badge.svg" />
|
||||
</a>
|
||||
<a target="_blank" href="https://gitter.im/hutool/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge">
|
||||
<img src="https://badges.gitter.im/hutool/Lobby.svg" />
|
||||
<a target="_blank" href='https://gitee.com/chinabugotech/hutool/stargazers'>
|
||||
<img src='https://gitee.com/chinabugotech/hutool/badge/star.svg?theme=gvp' alt='star'/>
|
||||
</a>
|
||||
<a target="_blank" href='https://gitee.com/dromara/hutool/stargazers'>
|
||||
<img src='https://gitee.com/dromara/hutool/badge/star.svg?theme=gvp' alt='star'/>
|
||||
<a target="_blank" href='https://github.com/chinabugotech/hutool'>
|
||||
<img src="https://img.shields.io/github/stars/chinabugotech/hutool.svg?style=social" alt="github star"/>
|
||||
</a>
|
||||
<a target="_blank" href='https://github.com/dromara/hutool'>
|
||||
<img src="https://img.shields.io/github/stars/dromara/hutool.svg?style=social" alt="github star"/>
|
||||
</a>
|
||||
<a target="_blank" href='https://gitcode.com/dromara/hutool'>
|
||||
<img src="https://gitcode.com/dromara/hutool/star/badge.svg" alt="gitcode star"/>
|
||||
<a target="_blank" href='https://gitcode.com/chinabugotech/hutool'>
|
||||
<img src="https://gitcode.com/chinabugotech/hutool/star/badge.svg" alt="gitcode star"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@ -49,11 +46,7 @@
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
<p align="center">
|
||||
<a href="#"><img style="width: 45%" alt="" src="https://plus.hutool.cn/images/zanzhu.jpg"/></a>
|
||||
</p>
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
=======
|
||||
|
||||
[**🌎English Documentation**](README-EN.md)
|
||||
|
||||
@ -119,23 +112,7 @@ Hutool = Hu + tool,是原公司项目底层代码剥离后的开源库,“Hu
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 🪙支持Hutool
|
||||
|
||||
### 💳捐赠
|
||||
|
||||
如果你觉得Hutool不错,可以捐赠请维护者吃包辣条~,在此表示感谢^_^。
|
||||
|
||||
[Gitee上捐赠](https://gitee.com/dromara/hutool)
|
||||
|
||||
### 👕周边商店
|
||||
|
||||
你也可以通过购买Hutool的周边商品来支持Hutool维护哦!
|
||||
|
||||
我们提供了印有Hutool Logo的周边商品,欢迎点击购买支持:
|
||||
|
||||
👉 [Hutool 周边商店](https://market.m.taobao.com/apps/market/content/index.html?wh_weex=true&contentId=331724720170) 👈
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 📦安装
|
||||
|
||||
@ -146,20 +123,20 @@ Hutool = Hu + tool,是原公司项目底层代码剥离后的开源库,“Hu
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.36</version>
|
||||
<version>5.8.37</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### 🍐Gradle
|
||||
```
|
||||
implementation 'cn.hutool:hutool-all:5.8.36'
|
||||
implementation 'cn.hutool:hutool-all:5.8.37'
|
||||
```
|
||||
|
||||
### 📥下载jar
|
||||
|
||||
点击以下链接,下载`hutool-all-X.X.X.jar`即可:
|
||||
|
||||
- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.36/)
|
||||
- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.37/)
|
||||
|
||||
> 🔔️注意
|
||||
> Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。
|
||||
@ -167,7 +144,7 @@ implementation 'cn.hutool:hutool-all:5.8.36'
|
||||
|
||||
### 🚽编译安装
|
||||
|
||||
访问Hutool的Gitee主页:[https://gitee.com/dromara/hutool](https://gitee.com/dromara/hutool) 下载整个项目源码(v5-master或v5-dev分支都可)然后进入Hutool项目目录执行:
|
||||
访问Hutool的Gitee主页:[https://gitee.com/chinabugotech/hutool](https://gitee.com/chinabugotech/hutool) 下载整个项目源码(v5-master或v5-dev分支都可)然后进入Hutool项目目录执行:
|
||||
|
||||
```sh
|
||||
./hutool.sh install
|
||||
@ -192,9 +169,9 @@ Hutool的源码分为两个分支,功能如下:
|
||||
|
||||
提交问题反馈请说明正在使用的JDK版本呢、Hutool版本和相关依赖库版本。
|
||||
|
||||
- [Gitee issue](https://gitee.com/dromara/hutool/issues)
|
||||
- [Github issue](https://github.com/dromara/hutool/issues)
|
||||
- [Gitcode issue](https://gitcode.com/dromara/hutool/issues)
|
||||
- [Gitee issue](https://gitee.com/chinabugotech/hutool/issues)
|
||||
- [Github issue](https://github.com/chinabugotech/hutool/issues)
|
||||
- [Gitcode issue](https://gitcode.com/chinabugotech/hutool/issues)
|
||||
|
||||
|
||||
### 🧬贡献代码的步骤
|
||||
@ -224,4 +201,4 @@ Hutool欢迎任何人为Hutool添砖加瓦,贡献代码,不过维护者是
|
||||
|
||||
## ⭐Star Hutool
|
||||
|
||||
[](https://starchart.cc/dromara/hutool)
|
||||
[](https://starchart.cc/chinabugotech/hutool)
|
||||
|
@ -10,6 +10,6 @@
|
||||
|
||||
## Reporting a Vulnerability(报告漏洞)
|
||||
|
||||
如果你发现有安全问题或漏洞,请发送邮件到`loolly@aliyun.com`。
|
||||
如果你发现有安全问题或漏洞,请发送邮件到`bugo@bugotech.cn`。
|
||||
|
||||
To report any found security issues or vulnerabilities, please send a mail to `loolly@aliyun.com`.
|
||||
To report any found security issues or vulnerabilities, please send a mail to `bugo@bugotech.cn`.
|
@ -1 +1 @@
|
||||
5.8.36
|
||||
5.8.37
|
||||
|
@ -1 +1 @@
|
||||
var version = '5.8.36'
|
||||
var version = '5.8.37'
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.8.36</version>
|
||||
<version>5.8.37-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-all</artifactId>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.8.36</version>
|
||||
<version>5.8.37-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-aop</artifactId>
|
||||
|
@ -29,7 +29,7 @@ public class CglibProxyFactory extends ProxyFactory{
|
||||
|
||||
/**
|
||||
* 创建代理对象<br>
|
||||
* https://gitee.com/dromara/hutool/issues/I74EX7<br>
|
||||
* https://gitee.com/chinabugotech/hutool/issues/I74EX7<br>
|
||||
* 某些对象存在非空参数构造,则需遍历查找需要的构造完成代理对象构建。
|
||||
*
|
||||
* @param <T> 代理对象类型
|
||||
|
@ -29,7 +29,7 @@ public class SpringCglibProxyFactory extends ProxyFactory{
|
||||
|
||||
/**
|
||||
* 创建代理对象<br>
|
||||
* https://gitee.com/dromara/hutool/issues/I74EX7<br>
|
||||
* https://gitee.com/chinabugotech/hutool/issues/I74EX7<br>
|
||||
* 某些对象存在非空参数构造,则需遍历查找需要的构造完成代理对象构建。
|
||||
*
|
||||
* @param <T> 代理对象类型
|
||||
|
@ -30,7 +30,7 @@ public class IssueI74EX7Test {
|
||||
}
|
||||
|
||||
/**
|
||||
* https://gitee.com/dromara/hutool/issues/I74EX7<br>
|
||||
* https://gitee.com/chinabugotech/hutool/issues/I74EX7<br>
|
||||
* Enhancer.create()默认调用无参构造,有参构造或者多个构造没有很好的兼容。
|
||||
*
|
||||
*/
|
||||
@ -42,7 +42,7 @@ public class IssueI74EX7Test {
|
||||
}
|
||||
|
||||
/**
|
||||
* https://gitee.com/dromara/hutool/issues/I74EX7<br>
|
||||
* https://gitee.com/chinabugotech/hutool/issues/I74EX7<br>
|
||||
* Enhancer.create()默认调用无参构造,有参构造或者多个构造没有很好的兼容。
|
||||
*
|
||||
*/
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.8.36</version>
|
||||
<version>5.8.37-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-bloomFilter</artifactId>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.8.36</version>
|
||||
<version>5.8.37-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-bom</artifactId>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.8.36</version>
|
||||
<version>5.8.37-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-cache</artifactId>
|
||||
|
@ -112,6 +112,7 @@ public abstract class ReentrantCache<K, V> extends AbstractCache<K, V> {
|
||||
if(null != co && co.isExpired()){
|
||||
//过期移除
|
||||
removeWithoutLock(key);
|
||||
onRemove(co.key, co.obj);
|
||||
co = null;
|
||||
}
|
||||
} finally {
|
||||
|
@ -4,13 +4,17 @@ import cn.hutool.cache.impl.TimedCache;
|
||||
import cn.hutool.core.date.DateUnit;
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* 缓存测试用例
|
||||
* @author Looly
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
public class CacheTest {
|
||||
|
||||
@ -121,4 +125,27 @@ public class CacheTest {
|
||||
//取消定时清理
|
||||
timedCache.cancelPruneSchedule();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TimedCache的数据过期后不是每次都触发监听器onRemove,而是偶尔触发onRemove
|
||||
* https://gitee.com/chinabugotech/hutool/issues/IBP752
|
||||
*/
|
||||
@Test
|
||||
public void whenContainsKeyTimeout_shouldCallOnRemove() {
|
||||
int timeout = 50;
|
||||
final TimedCache<Integer, String> ALARM_CACHE = new TimedCache<>(timeout);
|
||||
|
||||
AtomicInteger counter = new AtomicInteger(0);
|
||||
ALARM_CACHE.setListener((key, value) -> {
|
||||
counter.incrementAndGet();
|
||||
});
|
||||
|
||||
ALARM_CACHE.put(1, "value1");
|
||||
|
||||
ThreadUtil.sleep(100);
|
||||
|
||||
assertFalse(ALARM_CACHE.containsKey(1));
|
||||
assertEquals(1, counter.get());
|
||||
}
|
||||
}
|
||||
|
@ -4,15 +4,16 @@ import cn.hutool.cache.impl.LRUCache;
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* 见:https://github.com/dromara/hutool/issues/1895<br>
|
||||
* 见:https://github.com/chinabugotech/hutool/issues/1895<br>
|
||||
* 并发问题测试,在5.7.15前,LRUCache存在并发问题,多线程get后,map结构变更,导致null的位置不确定,
|
||||
* 并可能引起死锁。
|
||||
*/
|
||||
@ -21,7 +22,7 @@ public class LRUCacheTest {
|
||||
@Test
|
||||
@Disabled
|
||||
public void putTest(){
|
||||
//https://github.com/dromara/hutool/issues/2227
|
||||
//https://github.com/chinabugotech/hutool/issues/2227
|
||||
final LRUCache<String, String> cache = CacheUtil.newLRUCache(100, 10);
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
//ThreadUtil.execute(()-> cache.put(RandomUtil.randomString(5), "1243", 10));
|
||||
|
@ -2,10 +2,11 @@ package cn.hutool.cache;
|
||||
|
||||
import cn.hutool.cache.impl.WeakCache;
|
||||
import cn.hutool.core.lang.Console;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class WeakCacheTest {
|
||||
|
||||
@Test
|
||||
@ -25,7 +26,7 @@ public class WeakCacheTest {
|
||||
@Test
|
||||
@Disabled
|
||||
public void removeByGcTest(){
|
||||
// https://gitee.com/dromara/hutool/issues/I51O7M
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I51O7M
|
||||
WeakCache<String, String> cache = new WeakCache<>(-1);
|
||||
cache.put("a", "1");
|
||||
cache.put("b", "2");
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.8.36</version>
|
||||
<version>5.8.37-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-captcha</artifactId>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.8.36</version>
|
||||
<version>5.8.37-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-core</artifactId>
|
||||
|
@ -2199,7 +2199,7 @@ public class CollUtil {
|
||||
iter = (Iterator) value;
|
||||
} else if (value instanceof Iterable) {
|
||||
if(value instanceof Map && BeanUtil.isBean(TypeUtil.getClass(elementType))){
|
||||
//https://github.com/dromara/hutool/issues/3139
|
||||
//https://github.com/chinabugotech/hutool/issues/3139
|
||||
// 如果值为Map,而目标为一个Bean,则Map应整体转换为Bean,而非拆分成Entry转换
|
||||
iter = new ArrayIter<>(new Object[]{value});
|
||||
}else{
|
||||
|
@ -36,7 +36,7 @@ public class NumberWithFormat extends Number implements TypeConverter {
|
||||
// 自定义日期格式
|
||||
if (null != this.format && targetType instanceof Class) {
|
||||
final Class<?> clazz = (Class<?>) targetType;
|
||||
// https://gitee.com/dromara/hutool/issues/I6IS5B
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I6IS5B
|
||||
if (Date.class.isAssignableFrom(clazz)) {
|
||||
return new DateConverter((Class<? extends Date>) clazz, format).convert(this.number, null);
|
||||
} else if (TemporalAccessor.class.isAssignableFrom(clazz)) {
|
||||
|
@ -206,7 +206,7 @@ public class TemporalAccessorConverter extends AbstractConverter<TemporalAccesso
|
||||
|
||||
final Instant instant;
|
||||
if (GlobalCustomFormat.FORMAT_SECONDS.equals(this.format)) {
|
||||
// https://gitee.com/dromara/hutool/issues/I6IS5B
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I6IS5B
|
||||
// Unix时间戳
|
||||
instant = Instant.ofEpochSecond(time);
|
||||
} else {
|
||||
|
@ -561,7 +561,8 @@ public class FileUtil extends PathUtil {
|
||||
|
||||
/**
|
||||
* 计算文件的总行数<br>
|
||||
* 参考:https://stackoverflow.com/questions/453018/number-of-lines-in-a-file-in-java
|
||||
* 参考:https://stackoverflow.com/questions/453018/number-of-lines-in-a-file-in-java<br>
|
||||
* 最后一行如果末尾带有换行符,则被当作为新行
|
||||
*
|
||||
* @param file 文件
|
||||
* @param bufferSize 缓存大小,小于1则使用默认的1024
|
||||
@ -569,6 +570,20 @@ public class FileUtil extends PathUtil {
|
||||
* @since 5.8.28
|
||||
*/
|
||||
public static int getTotalLines(File file, int bufferSize) {
|
||||
return getTotalLines(file, bufferSize, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算文件的总行数<br>
|
||||
* 参考:https://stackoverflow.com/questions/453018/number-of-lines-in-a-file-in-java
|
||||
*
|
||||
* @param file 文件
|
||||
* @param bufferSize 缓存大小,小于1则使用默认的1024
|
||||
* @param lastLineSeparatorAsNewLine 是否将最后一行分隔符作为新行,Linux下要求最后一行必须带有换行符,不算一行,此处用户选择
|
||||
* @return 该文件总行数
|
||||
* @since 5.8.37
|
||||
*/
|
||||
public static int getTotalLines(File file, int bufferSize, boolean lastLineSeparatorAsNewLine) {
|
||||
if (false == isFile(file)) {
|
||||
throw new IORuntimeException("Input must be a File");
|
||||
}
|
||||
@ -614,9 +629,16 @@ public class FileUtil extends PathUtil {
|
||||
readChars = is.read(chars);
|
||||
}
|
||||
|
||||
// 最后一个字符为换行符,则单独计数行
|
||||
if(c == CharUtil.CR){
|
||||
++count;
|
||||
if(lastLineSeparatorAsNewLine){
|
||||
// 最后一个字符为\r,则单独计数行
|
||||
if(c == CharUtil.CR){
|
||||
++count;
|
||||
}
|
||||
}else{
|
||||
// 最后一个字符为\n,则可选是否算作新行单独计数行
|
||||
if(c == CharUtil.LF){
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
@ -1033,7 +1055,7 @@ public class FileUtil extends PathUtil {
|
||||
int exceptionsCount = 0;
|
||||
while (true) {
|
||||
try {
|
||||
// https://github.com/dromara/hutool/issues/3103
|
||||
// https://github.com/chinabugotech/hutool/issues/3103
|
||||
//File file = File.createTempFile(prefix, suffix, mkdir(dir)).getCanonicalFile();
|
||||
final File file = PathUtil.createTempFile(prefix, suffix, null == dir ? null : dir.toPath()).toFile().getCanonicalFile();
|
||||
if (isReCreat) {
|
||||
@ -1329,11 +1351,11 @@ public class FileUtil extends PathUtil {
|
||||
if (null == classPath) {
|
||||
// throw new NullPointerException("ClassPath is null !");
|
||||
// 在jar运行模式中,ClassPath有可能获取不到,此时返回原始相对路径(此时获取的文件为相对工作目录)
|
||||
return path;
|
||||
return normalPath;
|
||||
}
|
||||
|
||||
// 资源不存在的情况下使用标准化路径有问题,使用原始路径拼接后标准化路径
|
||||
return normalize(classPath.concat(Objects.requireNonNull(path)));
|
||||
return normalize(classPath.concat(Objects.requireNonNull(normalPath)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,7 +159,7 @@ public class FileWriter extends FileWrapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将列表写入文件,覆盖模式
|
||||
* 将列表写入文件,覆盖模式,最后一行末尾不追加换行符
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param list 列表
|
||||
@ -171,7 +171,7 @@ public class FileWriter extends FileWrapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将列表写入文件,追加模式
|
||||
* 将列表写入文件,追加模式,最后一行末尾不追加换行符
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param list 列表
|
||||
@ -183,7 +183,7 @@ public class FileWriter extends FileWrapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将列表写入文件
|
||||
* 将列表写入文件,最后一行末尾不追加换行符
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param list 列表
|
||||
@ -196,7 +196,7 @@ public class FileWriter extends FileWrapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将列表写入文件
|
||||
* 将列表写入文件,最后一行末尾不追加换行符
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param list 列表
|
||||
@ -207,6 +207,22 @@ public class FileWriter extends FileWrapper {
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public <T> File writeLines(Iterable<T> list, LineSeparator lineSeparator, boolean isAppend) throws IORuntimeException {
|
||||
return writeLines(list, lineSeparator, isAppend, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将列表写入文件
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param list 列表
|
||||
* @param lineSeparator 换行符枚举(Windows、Mac或Linux换行符)
|
||||
* @param isAppend 是否追加
|
||||
* @param appendLineSeparator 是否在最后一行末尾追加换行符,Linux下要求最后一行必须带有换行符
|
||||
* @return 目标文件
|
||||
* @throws IORuntimeException IO异常
|
||||
* @since 5.8.37
|
||||
*/
|
||||
public <T> File writeLines(Iterable<T> list, LineSeparator lineSeparator, boolean isAppend, boolean appendLineSeparator) throws IORuntimeException {
|
||||
try (PrintWriter writer = getPrintWriter(isAppend)) {
|
||||
boolean isFirst = true;
|
||||
for (T t : list) {
|
||||
@ -221,10 +237,12 @@ public class FileWriter extends FileWrapper {
|
||||
printNewLine(writer, lineSeparator);
|
||||
}
|
||||
writer.print(t);
|
||||
|
||||
writer.flush();
|
||||
}
|
||||
}
|
||||
if(appendLineSeparator){
|
||||
printNewLine(writer, lineSeparator);
|
||||
}
|
||||
writer.flush();
|
||||
}
|
||||
return this.file;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* 复制jdk16中的Optional,以及自己进行了一点调整和新增,比jdk8中的Optional多了几个实用的函数<br>
|
||||
* 详细见:<a href="https://gitee.com/dromara/hutool/pulls/426">https://gitee.com/dromara/hutool/pulls/426</a>
|
||||
* 详细见:<a href="https://gitee.com/chinabugotech/hutool/pulls/426">https://gitee.com/chinabugotech/hutool/pulls/426</a>
|
||||
*
|
||||
* @param <T> 包裹里元素的类型
|
||||
* @author VampireAchao
|
||||
|
@ -146,9 +146,9 @@ public interface RegexPool {
|
||||
* 中国车牌号码(兼容新能源车牌)
|
||||
*/
|
||||
String PLATE_NUMBER =
|
||||
//https://gitee.com/dromara/hutool/issues/I1B77H?from=project-issue
|
||||
//https://gitee.com/chinabugotech/hutool/issues/I1B77H?from=project-issue
|
||||
"^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[ABCDEFGHJK])|([ABCDEFGHJK]([A-HJ-NP-Z0-9])[0-9]{4})))|" +
|
||||
//https://gitee.com/dromara/hutool/issues/I1BJHE?from=project-issue
|
||||
//https://gitee.com/chinabugotech/hutool/issues/I1BJHE?from=project-issue
|
||||
"([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领]\\d{3}\\d{1,3}[领])|" +
|
||||
"([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$";
|
||||
|
||||
|
@ -2,8 +2,10 @@ package cn.hutool.core.lang.reflect;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.map.WeakConcurrentMap;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.TypeUtil;
|
||||
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
@ -37,14 +39,14 @@ public class ActualTypeMapperPool {
|
||||
* @return 泛型对应关系Map
|
||||
* @since 5.7.16
|
||||
*/
|
||||
public static Map<String, Type> getStrKeyMap(Type type){
|
||||
public static Map<String, Type> getStrKeyMap(Type type) {
|
||||
return Convert.toMap(String.class, Type.class, get(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得泛型变量对应的泛型实际类型,如果此变量没有对应的实际类型,返回null
|
||||
*
|
||||
* @param type 类
|
||||
* @param type 类
|
||||
* @param typeVariable 泛型变量,例如T等
|
||||
* @return 实际类型,可能为Class等
|
||||
*/
|
||||
@ -57,11 +59,35 @@ public class ActualTypeMapperPool {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得泛型变量对应的泛型实际类型,如果此变量没有对应的实际类型,返回null
|
||||
*
|
||||
* @param type 类
|
||||
* @param genericArrayType 泛型数组类型
|
||||
* @return 实际类型,可能为Class等
|
||||
* @since 5.8.37
|
||||
*/
|
||||
public static Type getActualType(Type type, GenericArrayType genericArrayType) {
|
||||
final Map<Type, Type> typeTypeMap = get(type);
|
||||
Type actualType = typeTypeMap.get(genericArrayType);
|
||||
|
||||
if (actualType == null) {
|
||||
Type componentType = typeTypeMap.get(genericArrayType.getGenericComponentType());
|
||||
if (!(componentType instanceof Class<?>)) {
|
||||
return null;
|
||||
}
|
||||
actualType = ArrayUtil.getArrayType((Class<?>) componentType);
|
||||
typeTypeMap.put(genericArrayType, actualType);
|
||||
}
|
||||
|
||||
return actualType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定泛型变量对应的真实类型<br>
|
||||
* 由于子类中泛型参数实现和父类(接口)中泛型定义位置是一一对应的,因此可以通过对应关系找到泛型实现类型<br>
|
||||
*
|
||||
* @param type 真实类型所在类,此类中记录了泛型参数对应的实际类型
|
||||
* @param type 真实类型所在类,此类中记录了泛型参数对应的实际类型
|
||||
* @param typeVariables 泛型变量,需要的实际类型对应的泛型参数
|
||||
* @return 给定泛型参数对应的实际类型,如果无对应类型,对应位置返回null
|
||||
*/
|
||||
@ -70,8 +96,8 @@ public class ActualTypeMapperPool {
|
||||
final Type[] result = new Type[typeVariables.length];
|
||||
for (int i = 0; i < typeVariables.length; i++) {
|
||||
result[i] = (typeVariables[i] instanceof TypeVariable)
|
||||
? getActualType(type, (TypeVariable<?>) typeVariables[i])
|
||||
: typeVariables[i];
|
||||
? getActualType(type, (TypeVariable<?>) typeVariables[i])
|
||||
: typeVariables[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -94,7 +120,7 @@ public class ActualTypeMapperPool {
|
||||
// 如果传入的非Class,例如TypeReference,获取到泛型参数中实际的泛型对象类,继续按照类处理
|
||||
while (null != type) {
|
||||
final ParameterizedType parameterizedType = TypeUtil.toParameterizedType(type);
|
||||
if(null == parameterizedType){
|
||||
if (null == parameterizedType) {
|
||||
break;
|
||||
}
|
||||
final Type[] typeArguments = parameterizedType.getActualTypeArguments();
|
||||
@ -105,7 +131,7 @@ public class ActualTypeMapperPool {
|
||||
for (int i = 0; i < typeParameters.length; i++) {
|
||||
value = typeArguments[i];
|
||||
// 跳过泛型变量对应泛型变量的情况
|
||||
if(false == value instanceof TypeVariable){
|
||||
if (false == value instanceof TypeVariable) {
|
||||
typeMap.put(typeParameters[i], value);
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import java.util.Stack;
|
||||
|
||||
/**
|
||||
* 数学表达式计算工具类<br>
|
||||
* 见:https://github.com/dromara/hutool/issues/1090#issuecomment-693750140
|
||||
* 见:https://github.com/chinabugotech/hutool/issues/1090#issuecomment-693750140
|
||||
*
|
||||
* @author trainliang, looly
|
||||
* @since 5.4.3
|
||||
|
@ -11,7 +11,7 @@ import java.util.Currency;
|
||||
/**
|
||||
* 单币种货币类,处理货币算术、币种和取整。
|
||||
* <p>
|
||||
* 感谢提供此方法的用户:https://github.com/dromara/hutool/issues/605
|
||||
* 感谢提供此方法的用户:https://github.com/chinabugotech/hutool/issues/605
|
||||
*
|
||||
* <p>
|
||||
* 货币类中封装了货币金额和币种。目前金额在内部是long类型表示,
|
||||
|
@ -518,7 +518,7 @@ public class NetUtil {
|
||||
* <p>
|
||||
* 此方法不会抛出异常,获取失败将返回{@code null}<br>
|
||||
* <p>
|
||||
* 见:https://github.com/dromara/hutool/issues/428
|
||||
* 见:https://github.com/chinabugotech/hutool/issues/428
|
||||
*
|
||||
* @return 本机网卡IP地址,获取失败返回{@code null}
|
||||
* @since 3.0.1
|
||||
|
@ -363,7 +363,7 @@ public final class CsvWriter implements Closeable, Flushable, Serializable {
|
||||
@Override
|
||||
public void close() {
|
||||
if(this.config.endingLineBreak){
|
||||
//https://gitee.com/dromara/hutool/issues/I75K5G
|
||||
//https://gitee.com/chinabugotech/hutool/issues/I75K5G
|
||||
writeLine();
|
||||
}
|
||||
IoUtil.close(this.writer);
|
||||
|
@ -340,6 +340,11 @@ public class IdcardUtil {
|
||||
if (StrUtil.isBlank(idcard)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// issue#IBP6T1 中文空格替换为英文
|
||||
idcard = StrUtil.replace(idcard, "(", "(");
|
||||
idcard = StrUtil.replace(idcard, ")", ")");
|
||||
|
||||
String[] info = new String[3];
|
||||
String card = idcard.replaceAll("[()]", "");
|
||||
if (card.length() != 8 && card.length() != 9 && idcard.length() != 10) {
|
||||
|
@ -3,12 +3,7 @@ package cn.hutool.core.util;
|
||||
import cn.hutool.core.lang.ParameterizedTypeImpl;
|
||||
import cn.hutool.core.lang.reflect.ActualTypeMapperPool;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.lang.reflect.WildcardType;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -412,6 +407,13 @@ public class TypeUtil {
|
||||
if (typeVariable instanceof TypeVariable) {
|
||||
return ActualTypeMapperPool.getActualType(type, (TypeVariable<?>) typeVariable);
|
||||
}
|
||||
if (typeVariable instanceof GenericArrayType) {
|
||||
//return ActualTypeMapperPool.getActualType(type, (GenericArrayType) typeVariable);
|
||||
final Type actualType = ActualTypeMapperPool.getActualType(type, (GenericArrayType) typeVariable);
|
||||
if(null != actualType){
|
||||
return actualType;
|
||||
}
|
||||
}
|
||||
|
||||
// 没有需要替换的泛型变量,原样输出
|
||||
return typeVariable;
|
||||
|
196
hutool-core/src/main/java/cn/hutool/core/util/VersionUtil.java
Normal file
196
hutool-core/src/main/java/cn/hutool/core/util/VersionUtil.java
Normal file
@ -0,0 +1,196 @@
|
||||
package cn.hutool.core.util;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.exceptions.UtilException;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 版本对比工具
|
||||
* 对 {@link cn.hutool.core.comparator.VersionComparator} 的封装
|
||||
* 最主要功能包括:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* 1. 版本表达式匹配
|
||||
* 2. 单个版本匹配
|
||||
* </pre>
|
||||
*
|
||||
* @author winlans
|
||||
* @see cn.hutool.core.comparator.VersionComparator
|
||||
*/
|
||||
public class VersionUtil {
|
||||
|
||||
private static final Pattern COMPARE_REG = Pattern.compile("^[<>≥≤]=?");
|
||||
// 默认多版本分隔符
|
||||
private static final String defaultVersionsDelimiter = ";";
|
||||
|
||||
/**
|
||||
* 是否匹配任意一个版本
|
||||
*
|
||||
* @param currentVersion 当前版本
|
||||
* @param compareVersions 待匹配的版本列表
|
||||
* @return true 包含待匹配的版本
|
||||
*/
|
||||
public static boolean anyMatch(String currentVersion, Collection<String> compareVersions) {
|
||||
return matchEl(currentVersion, CollUtil.join(compareVersions, defaultVersionsDelimiter));
|
||||
}
|
||||
|
||||
public static boolean anyMatch(String currentVersion, String... compareVersions) {
|
||||
return matchEl(currentVersion, ArrayUtil.join(compareVersions, defaultVersionsDelimiter));
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前版本大于待比较版本
|
||||
*
|
||||
* @param currentVersion 当前本本
|
||||
* @param compareVersion 待比较版本
|
||||
* @return true 当前版本大于待比较版本
|
||||
*/
|
||||
public static boolean isGreaterThan(String currentVersion, String compareVersion) {
|
||||
return matchEl(currentVersion, ">" + compareVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前版本大于等于待比较版本
|
||||
*
|
||||
* @param currentVersion 当前本本
|
||||
* @param compareVersion 待比较版本
|
||||
* @return true 当前版本大于等于待比较版本
|
||||
*/
|
||||
public static boolean isGreaterThanOrEqual(String currentVersion, String compareVersion) {
|
||||
return matchEl(currentVersion, ">=" + compareVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前版本小于待比较版本
|
||||
*
|
||||
* @param currentVersion 当前本本
|
||||
* @param compareVersion 待比较版本
|
||||
* @return true 当前版本小于待比较版本
|
||||
*/
|
||||
public static boolean isLessThan(String currentVersion, String compareVersion) {
|
||||
return matchEl(currentVersion, "<" + compareVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前版本小于等于待比较版本
|
||||
*
|
||||
* @param currentVersion 当前本本
|
||||
* @param compareVersion 待比较版本
|
||||
* @return true 当前版本小于等于待比较版本
|
||||
*/
|
||||
public static boolean isLessThanOrEqual(String currentVersion, String compareVersion) {
|
||||
return matchEl(currentVersion, "<=" + compareVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前版本是否满足版本表达式
|
||||
* <pre>
|
||||
* matchEl("1.0.2", ">=1.0.2") == true
|
||||
* matchEl("1.0.2", "<1.0.1;1.0.2") == true
|
||||
* matchEl("1.0.2", "<1.0.2") == false
|
||||
* matchEl("1.0.2", "1.0.0-1.1.1") == true
|
||||
* matchEl("1.0.2", "1.0.0-1.1.1") == true
|
||||
* </pre>
|
||||
*
|
||||
* @param currentVersion 当前本本
|
||||
* @param versionEl 版本表达式
|
||||
* @return true 当前版本小于等于待比较版本
|
||||
*/
|
||||
public static boolean matchEl(String currentVersion, String versionEl) {
|
||||
return matchEl(currentVersion, versionEl, defaultVersionsDelimiter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前版本是否满足版本表达式
|
||||
* <pre>
|
||||
* matchEl("1.0.2", ">=1.0.2", ";") == true
|
||||
* matchEl("1.0.2", "<1.0.1,1.0.2", ",") == true
|
||||
* matchEl("1.0.2", "<1.0.2", ";") == false
|
||||
* matchEl("1.0.2", "1.0.0-1.1.1", ",") == true
|
||||
* matchEl("1.0.2", "1.0.1,1.0.2-1.1.1", ",") == true
|
||||
* </pre>
|
||||
*
|
||||
* @param currentVersion 当前本本
|
||||
* @param versionEl 版本表达式(可以匹配多个条件,使用指定的分隔符(默认;)分隔),
|
||||
* {@code '-'}表示范围包含左右版本,如果 {@code '-'}的左边没有,表示小于等于某个版本号, 右边表示大于等于某个版本号。
|
||||
* 支持比较符号{@code '>'},{@code '<'}, {@code '>='},{@code '<='},{@code '≤'},{@code '≥'}
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@code 1.0.1-1.2.4, 1.9.8} 表示版本号 大于等于{@code 1.0.1}且小于等于{@code 1.2.4} 或 版本{@code 1.9.8}</li>
|
||||
* <li>{@code >=2.0.0, 1.9.8} 表示版本号 大于等于{@code 2.0.0}或 版本{@code 1.9.8}</li>
|
||||
* </ul>
|
||||
* @param versionsDelimiter 多表达式分隔符
|
||||
* @return true 当前版本小于等于待比较版本
|
||||
*/
|
||||
public static boolean matchEl(String currentVersion, String versionEl, String versionsDelimiter) {
|
||||
if (StrUtil.isBlank(versionsDelimiter)
|
||||
|| StrUtil.equals("-", versionsDelimiter)
|
||||
|| ReUtil.isMatch(COMPARE_REG, versionsDelimiter)) {
|
||||
throw new UtilException("非法的版本分隔符:" + versionsDelimiter);
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(versionEl) || StrUtil.isBlank(currentVersion)) {
|
||||
return false;
|
||||
}
|
||||
String trimmedVersion = StrUtil.trim(currentVersion);
|
||||
|
||||
List<String> els = StrUtil.split(versionEl, versionsDelimiter, true, true);
|
||||
if (CollUtil.isEmpty(els)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (String el : els) {
|
||||
el = el.trim();
|
||||
Matcher matcher = COMPARE_REG.matcher(el);
|
||||
if (matcher.find()) {
|
||||
String op = matcher.group();
|
||||
String ver = StrUtil.removePrefix(el, op);
|
||||
switch (op) {
|
||||
case ">=":
|
||||
case "≥":
|
||||
if (StrUtil.compareVersion(trimmedVersion, ver) >= 0) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case "<=":
|
||||
case "≤":
|
||||
if (StrUtil.compareVersion(trimmedVersion, ver) <= 0) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case "<":
|
||||
if (StrUtil.compareVersion(trimmedVersion, ver) < 0) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case ">":
|
||||
if (StrUtil.compareVersion(trimmedVersion, ver) > 0) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else if (StrUtil.contains(el, "-")) {
|
||||
String[] pair = el.split("-");
|
||||
String left = StrUtil.blankToDefault(StrUtil.trim(pair[0]), "");
|
||||
String right = StrUtil.blankToDefault(StrUtil.trim(pair[1]), "");
|
||||
|
||||
boolean leftMatch = StrUtil.isBlank(left) || StrUtil.compareVersion(left, trimmedVersion) <= 0;
|
||||
boolean rightMatch = StrUtil.isBlank(right) || StrUtil.compareVersion(right, trimmedVersion) >= 0;
|
||||
if (leftMatch && rightMatch) {
|
||||
return true;
|
||||
}
|
||||
} else if (Objects.equals(trimmedVersion, el)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test;
|
||||
public class BeanCopyMappingTest {
|
||||
|
||||
/**
|
||||
* https://gitee.com/dromara/hutool/issues/I4C48U <br>
|
||||
* https://gitee.com/chinabugotech/hutool/issues/I4C48U <br>
|
||||
* 传递复制不要用注解别名,应该用动态映射
|
||||
*/
|
||||
@Test
|
||||
|
@ -253,7 +253,7 @@ public class BeanUtilTest {
|
||||
final SubPersonWithAlias subPersonWithAlias = BeanUtil.toBean(map, SubPersonWithAlias.class);
|
||||
assertEquals("sub名字", subPersonWithAlias.getSubName());
|
||||
|
||||
//https://gitee.com/dromara/hutool/issues/I6H0XF
|
||||
//https://gitee.com/chinabugotech/hutool/issues/I6H0XF
|
||||
assertFalse(subPersonWithAlias.isBooleana());
|
||||
assertNull(subPersonWithAlias.getBooleanb());
|
||||
}
|
||||
@ -520,7 +520,7 @@ public class BeanUtilTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* <a href="https://github.com/dromara/hutool/issues/1173">#1173</a>
|
||||
* <a href="https://github.com/chinabugotech/hutool/issues/1173">#1173</a>
|
||||
*/
|
||||
@Test
|
||||
public void beanToBeanOverlayFieldTest() {
|
||||
@ -597,7 +597,7 @@ public class BeanUtilTest {
|
||||
|
||||
@Test
|
||||
public void copyBeanPropertiesFunctionFilterTest() {
|
||||
//https://gitee.com/dromara/hutool/pulls/590
|
||||
//https://gitee.com/chinabugotech/hutool/pulls/590
|
||||
final Person o = new Person();
|
||||
o.setName("asd");
|
||||
o.setAge(123);
|
||||
@ -858,7 +858,7 @@ public class BeanUtilTest {
|
||||
|
||||
@Test
|
||||
public void valueProviderToBeanTest() {
|
||||
// https://gitee.com/dromara/hutool/issues/I5B4R7
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I5B4R7
|
||||
final CopyOptions copyOptions = CopyOptions.create();
|
||||
final Map<String, String> filedMap = new HashMap<>();
|
||||
filedMap.put("name", "sourceId");
|
||||
@ -931,7 +931,7 @@ public class BeanUtilTest {
|
||||
|
||||
@Test
|
||||
public void hasGetterTest() {
|
||||
// https://gitee.com/dromara/hutool/issues/I6M7Z7
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I6M7Z7
|
||||
final boolean b = BeanUtil.hasGetter(Object.class);
|
||||
assertFalse(b);
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* https://github.com/dromara/hutool/issues/1687
|
||||
* https://github.com/chinabugotech/hutool/issues/1687
|
||||
*/
|
||||
public class Issue1687Test {
|
||||
|
||||
|
@ -4,7 +4,7 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* https://github.com/dromara/hutool/issues/2009
|
||||
* https://github.com/chinabugotech/hutool/issues/2009
|
||||
*/
|
||||
public class Issue2009Test {
|
||||
|
||||
|
@ -5,7 +5,7 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* https://github.com/dromara/hutool/issues/2082<br>
|
||||
* https://github.com/chinabugotech/hutool/issues/2082<br>
|
||||
* 当setXXX有重载方法的时候,BeanDesc中会匹配到重载方法,增加类型检查来规避之
|
||||
*/
|
||||
public class Issue2082Test {
|
||||
|
@ -12,7 +12,7 @@ import java.util.Map;
|
||||
public class Issue2202Test {
|
||||
|
||||
/**
|
||||
* https://github.com/dromara/hutool/issues/2202
|
||||
* https://github.com/chinabugotech/hutool/issues/2202
|
||||
*/
|
||||
@Test
|
||||
public void mapToBeanWithFieldNameEditorTest(){
|
||||
|
@ -8,7 +8,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* https://github.com/dromara/hutool/issues/2697
|
||||
* https://github.com/chinabugotech/hutool/issues/2697
|
||||
*/
|
||||
public class Issue2697Test {
|
||||
|
||||
|
@ -854,7 +854,7 @@ public class CollUtilTest {
|
||||
|
||||
@Test
|
||||
public void setValueByMapTest() {
|
||||
// https://gitee.com/dromara/hutool/pulls/482
|
||||
// https://gitee.com/chinabugotech/hutool/pulls/482
|
||||
final List<Person> people = Arrays.asList(
|
||||
new Person("aa", 12, "man", 1),
|
||||
new Person("bb", 13, "woman", 2),
|
||||
|
@ -12,7 +12,7 @@ public class IssueI5DRU0Test {
|
||||
@Test
|
||||
@Disabled
|
||||
public void appendTest(){
|
||||
// https://gitee.com/dromara/hutool/issues/I5DRU0
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I5DRU0
|
||||
// 向zip中添加文件的时候,如果添加的文件的父目录已经存在,会报错。实际中目录存在忽略即可。
|
||||
ZipUtil.append(Paths.get("d:/test/zipTest.zip"), Paths.get("d:/test/zipTest"), StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import org.junit.jupiter.api.Test;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* https://gitee.com/dromara/hutool/issues/IAGYDG
|
||||
* https://gitee.com/chinabugotech/hutool/issues/IAGYDG
|
||||
*/
|
||||
public class IssueIAGYDGTest {
|
||||
@Test
|
||||
|
@ -351,7 +351,7 @@ public class ConvertTest {
|
||||
|
||||
@Test
|
||||
public void toBigDecimalTest() {
|
||||
// https://github.com/dromara/hutool/issues/1818
|
||||
// https://github.com/chinabugotech/hutool/issues/1818
|
||||
final String str = "33020000210909112800000124";
|
||||
final BigDecimal bigDecimal = Convert.toBigDecimal(str);
|
||||
assertEquals(str, bigDecimal.toPlainString());
|
||||
@ -359,7 +359,7 @@ public class ConvertTest {
|
||||
|
||||
@Test
|
||||
public void toFloatTest() {
|
||||
// https://gitee.com/dromara/hutool/issues/I4M0E4
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I4M0E4
|
||||
final String hex2 = "CD0CCB43";
|
||||
final byte[] value = HexUtil.decodeHex(hex2);
|
||||
final float f = Convert.toFloat(value);
|
||||
|
@ -25,7 +25,7 @@ public class CalendarUtilTest {
|
||||
final Calendar calendar = CalendarUtil.parse("2021-09-27 00:00:112323", false,
|
||||
DatePattern.NORM_DATETIME_FORMAT);
|
||||
|
||||
// https://github.com/dromara/hutool/issues/1849
|
||||
// https://github.com/chinabugotech/hutool/issues/1849
|
||||
// 在使用严格模式时,秒不正确,抛出异常
|
||||
DateUtil.date(calendar);
|
||||
});
|
||||
|
@ -117,7 +117,7 @@ public class ChineseDateTest {
|
||||
|
||||
@Test
|
||||
public void getChineseMonthTest2(){
|
||||
//https://github.com/dromara/hutool/issues/2112
|
||||
//https://github.com/chinabugotech/hutool/issues/2112
|
||||
ChineseDate springFestival = new ChineseDate(DateUtil.parseDate("2022-02-01"));
|
||||
final String chineseMonth = springFestival.getChineseMonth();
|
||||
assertEquals("一月", chineseMonth);
|
||||
@ -125,7 +125,7 @@ public class ChineseDateTest {
|
||||
|
||||
@Test
|
||||
public void day19700101Test(){
|
||||
// https://gitee.com/dromara/hutool/issues/I4UTPK
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I4UTPK
|
||||
Date date = DateUtil.parse("1970-01-01");
|
||||
//noinspection ConstantConditions
|
||||
ChineseDate chineseDate = new ChineseDate(date);
|
||||
@ -153,7 +153,7 @@ public class ChineseDateTest {
|
||||
|
||||
@Test
|
||||
public void getGregorianDateTest(){
|
||||
// https://gitee.com/dromara/hutool/issues/I4ZSGJ
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I4ZSGJ
|
||||
ChineseDate chineseDate = new ChineseDate(1998, 5, 1);
|
||||
assertEquals("1998-06-24 00:00:00", chineseDate.getGregorianDate().toString());
|
||||
|
||||
|
@ -1002,7 +1002,7 @@ public class DateUtilTest {
|
||||
|
||||
@Test
|
||||
public void parseNotFitTest() {
|
||||
//https://github.com/dromara/hutool/issues/1332
|
||||
//https://github.com/chinabugotech/hutool/issues/1332
|
||||
assertThrows(DateException.class, () -> {
|
||||
// 在日期格式不匹配的时候,测试是否正常报错
|
||||
DateUtil.parse("2020-12-23", DatePattern.PURE_DATE_PATTERN);
|
||||
|
@ -5,7 +5,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
public class Issue2981Test {
|
||||
/**
|
||||
* https://github.com/dromara/hutool/issues/2981<br>
|
||||
* https://github.com/chinabugotech/hutool/issues/2981<br>
|
||||
* 按照ISO8601规范,以Z结尾表示UTC时间,否则为当地时间
|
||||
*/
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
|
@ -8,7 +8,7 @@ import java.util.Calendar;
|
||||
public class Issue3011Test {
|
||||
@Test
|
||||
public void isSameMonthTest() {
|
||||
// https://github.com/dromara/hutool/issues/3011
|
||||
// https://github.com/chinabugotech/hutool/issues/3011
|
||||
// 判断是否同一个月,还需考虑公元前和公元后的的情况
|
||||
// 此处公元前2020年和公元2021年返回年都是2021
|
||||
final Calendar calendar1 = Calendar.getInstance();
|
||||
|
@ -52,7 +52,7 @@ public class FileCopierTest {
|
||||
@Test
|
||||
@Disabled
|
||||
public void copyFileByRelativePath(){
|
||||
// https://github.com/dromara/hutool/pull/2188
|
||||
// https://github.com/chinabugotech/hutool/pull/2188
|
||||
// 当复制的目标文件位置是相对路径的时候可以通过
|
||||
FileCopier copier = FileCopier.create(new File("pom.xml"),new File("aaa.txt"));
|
||||
copier.copy();
|
||||
|
@ -76,7 +76,7 @@ public class FileTypeUtilTest {
|
||||
@Test
|
||||
@Disabled
|
||||
public void webpTest(){
|
||||
// https://gitee.com/dromara/hutool/issues/I5BGTF
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I5BGTF
|
||||
final File file = FileUtil.file("d:/test/a.webp");
|
||||
final BufferedInputStream inputStream = FileUtil.getInputStream(file);
|
||||
final String type = FileTypeUtil.getType(inputStream);
|
||||
|
@ -4,6 +4,7 @@ import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.io.file.LineSeparator;
|
||||
import cn.hutool.core.lang.Console;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -538,22 +539,31 @@ public class FileUtilTest {
|
||||
@Test
|
||||
public void getTotalLinesTest() {
|
||||
// 此文件最后一行有换行符,则最后的空行算作一行
|
||||
final int totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines.csv"));
|
||||
int totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines.csv"));
|
||||
assertEquals(8, totalLines);
|
||||
|
||||
totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines.csv"), -1, false);
|
||||
Assertions.assertEquals(7, totalLines);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTotalLinesCrTest() {
|
||||
// 此文件最后一行有换行符,则最后的空行算作一行
|
||||
final int totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines_cr.csv"));
|
||||
int totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines_cr.csv"));
|
||||
assertEquals(8, totalLines);
|
||||
|
||||
totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines_cr.csv"), -1, false);
|
||||
Assertions.assertEquals(7, totalLines);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTotalLinesCrlfTest() {
|
||||
// 此文件最后一行有换行符,则最后的空行算作一行
|
||||
final int totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines_crlf.csv"));
|
||||
int totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines_crlf.csv"));
|
||||
assertEquals(8, totalLines);
|
||||
|
||||
totalLines = FileUtil.getTotalLines(FileUtil.file("test_lines_crlf.csv"), -1, false);
|
||||
Assertions.assertEquals(7, totalLines);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -0,0 +1,24 @@
|
||||
package cn.hutool.core.io.file;
|
||||
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class FileWriterTest {
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
void writeLinesAppendLineSeparatorTest() {
|
||||
final FileWriter writer = FileWriter.create(FileUtil.file("d:/test/lines_append_line_separator.txt"));
|
||||
writer.writeLines(ListUtil.of("aaa", "bbb", "ccc"), null, false, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
void writeLinesTest() {
|
||||
final FileWriter writer = FileWriter.create(FileUtil.file("d:/test/lines.txt"));
|
||||
writer.writeLines(ListUtil.of("aaa", "bbb", "ccc"), null, false);
|
||||
}
|
||||
|
||||
}
|
@ -8,7 +8,7 @@ import java.io.File;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* https://gitee.com/dromara/hutool/issues/IAB65V
|
||||
* https://gitee.com/chinabugotech/hutool/issues/IAB65V
|
||||
*/
|
||||
public class IssueIAB65VTest {
|
||||
@Test
|
||||
|
@ -10,7 +10,7 @@ import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* https://gitee.com/dromara/hutool/pulls/532
|
||||
* https://gitee.com/chinabugotech/hutool/pulls/532
|
||||
*/
|
||||
public class MetroHashTest {
|
||||
|
||||
|
@ -7,7 +7,7 @@ import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 见:https://gitee.com/dromara/hutool/pulls/447/files
|
||||
* 见:https://gitee.com/chinabugotech/hutool/pulls/447/files
|
||||
*
|
||||
* TODO 同时继承泛型和实现泛型接口需要解析,此处为F
|
||||
*/
|
||||
|
@ -28,7 +28,7 @@ public class CaseInsensitiveMapTest {
|
||||
|
||||
@Test
|
||||
public void mergeTest(){
|
||||
//https://github.com/dromara/hutool/issues/2086
|
||||
//https://github.com/chinabugotech/hutool/issues/2086
|
||||
Pair<String, String> b = new Pair<>("a", "value");
|
||||
Pair<String, String> a = new Pair<>("A", "value");
|
||||
final CaseInsensitiveMap<Object, Object> map = new CaseInsensitiveMap<>();
|
||||
|
@ -32,7 +32,7 @@ public class CalculatorTest {
|
||||
|
||||
@Test
|
||||
public void conversationTest5(){
|
||||
// https://github.com/dromara/hutool/issues/1984
|
||||
// https://github.com/chinabugotech/hutool/issues/1984
|
||||
final double conversion = Calculator.conversion("((1/1) / (1/1) -1) * 100");
|
||||
assertEquals(0, conversion, 0);
|
||||
}
|
||||
@ -45,14 +45,14 @@ public class CalculatorTest {
|
||||
|
||||
@Test
|
||||
public void conversationTest7() {
|
||||
//https://gitee.com/dromara/hutool/issues/I4KONB
|
||||
//https://gitee.com/chinabugotech/hutool/issues/I4KONB
|
||||
final double conversion = Calculator.conversion("((-2395+0) * 0.3+140.24+35+90)/30");
|
||||
assertEquals(-15.11, conversion, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void issue2964Test() {
|
||||
// https://github.com/dromara/hutool/issues/2964
|
||||
// https://github.com/chinabugotech/hutool/issues/2964
|
||||
final double calcValue = Calculator.conversion("(11+2)12");
|
||||
assertEquals(156D, calcValue, 0.001);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ public class UrlBuilderTest {
|
||||
|
||||
@Test
|
||||
public void buildWithoutSlashTest() {
|
||||
// https://github.com/dromara/hutool/issues/2459
|
||||
// https://github.com/chinabugotech/hutool/issues/2459
|
||||
String buildUrl = UrlBuilder.of().setScheme("http").setHost("192.168.1.1").setPort(8080).setWithEndTag(false).build();
|
||||
assertEquals("http://192.168.1.1:8080", buildUrl);
|
||||
|
||||
@ -279,7 +279,7 @@ public class UrlBuilderTest {
|
||||
|
||||
@Test
|
||||
public void encodePathTest2() {
|
||||
// https://gitee.com/dromara/hutool/issues/I4RA42
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I4RA42
|
||||
// Path中`:`在第一个segment需要转义,之后的不需要
|
||||
final String urlStr = "https://hutool.cn/aa/bb/Pre-K,Kindergarten,First,Second,Third,Fourth,Fifth/Page:3";
|
||||
final UrlBuilder urlBuilder = UrlBuilder.ofHttp(urlStr, CharsetUtil.CHARSET_UTF_8);
|
||||
@ -298,7 +298,7 @@ public class UrlBuilderTest {
|
||||
|
||||
@Test
|
||||
public void fragmentEncodeTest() {
|
||||
// https://gitee.com/dromara/hutool/issues/I49KAL
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I49KAL
|
||||
// 见:https://stackoverflow.com/questions/26088849/url-fragment-allowed-characters
|
||||
final String url = "https://hutool.cn/docs/#/?id=简介";
|
||||
UrlBuilder urlBuilder = UrlBuilder.ofHttp(url);
|
||||
@ -310,7 +310,7 @@ public class UrlBuilderTest {
|
||||
|
||||
@Test
|
||||
public void slashEncodeTest() {
|
||||
// https://github.com/dromara/hutool/issues/1904
|
||||
// https://github.com/chinabugotech/hutool/issues/1904
|
||||
// 在query中,"/"是不可转义字符
|
||||
// 见:https://www.rfc-editor.org/rfc/rfc3986.html#section-3.4
|
||||
final String url = "https://invoice.maycur.com/2b27a802-8423-4d41-86f5-63a6b259f61e.xlsx?download/2b27a802-8423-4d41-86f5-63a6b259f61e.xlsx&e=1630491088";
|
||||
@ -333,7 +333,7 @@ public class UrlBuilderTest {
|
||||
|
||||
@Test
|
||||
public void addPathEncodeTest2() {
|
||||
// https://github.com/dromara/hutool/issues/1912
|
||||
// https://github.com/chinabugotech/hutool/issues/1912
|
||||
final String url = UrlBuilder.of()
|
||||
.setScheme("https")
|
||||
.setHost("domain.cn")
|
||||
@ -359,7 +359,7 @@ public class UrlBuilderTest {
|
||||
|
||||
@Test
|
||||
public void fragmentTest() {
|
||||
// https://gitee.com/dromara/hutool/issues/I49KAL#note_8060874
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I49KAL#note_8060874
|
||||
final String url = "https://www.hutool.cn/#/a/b?timestamp=1640391380204";
|
||||
final UrlBuilder builder = UrlBuilder.ofHttp(url);
|
||||
|
||||
@ -368,7 +368,7 @@ public class UrlBuilderTest {
|
||||
|
||||
@Test
|
||||
public void fragmentAppendParamTest() {
|
||||
// https://gitee.com/dromara/hutool/issues/I49KAL#note_8060874
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I49KAL#note_8060874
|
||||
final String url = "https://www.hutool.cn/#/a/b";
|
||||
final UrlBuilder builder = UrlBuilder.ofHttp(url);
|
||||
builder.setFragment(builder.getFragment() + "?timestamp=1640391380204");
|
||||
@ -437,7 +437,7 @@ public class UrlBuilderTest {
|
||||
|
||||
@Test
|
||||
public void issue2243Test() {
|
||||
// https://github.com/dromara/hutool/issues/2243
|
||||
// https://github.com/chinabugotech/hutool/issues/2243
|
||||
// 如果用户已经做了%编码,不应该重复编码
|
||||
final String url = "https://hutool.cn/v1.0?privateNum=%2B8616512884988";
|
||||
final String s = UrlBuilder.of(url, null).setCharset(CharsetUtil.CHARSET_UTF_8).toString();
|
||||
@ -471,7 +471,7 @@ public class UrlBuilderTest {
|
||||
|
||||
@Test
|
||||
public void addPathTest() {
|
||||
//https://gitee.com/dromara/hutool/issues/I5O4ML
|
||||
//https://gitee.com/chinabugotech/hutool/issues/I5O4ML
|
||||
UrlBuilder.of().addPath("");
|
||||
UrlBuilder.of().addPath("/");
|
||||
UrlBuilder.of().addPath("//");
|
||||
|
@ -22,7 +22,7 @@ public class UrlDecoderTest {
|
||||
|
||||
@Test
|
||||
public void issue3063Test() throws UnsupportedEncodingException {
|
||||
// https://github.com/dromara/hutool/issues/3063
|
||||
// https://github.com/chinabugotech/hutool/issues/3063
|
||||
|
||||
final String s = "测试";
|
||||
final String expectedDecode = "%FE%FF%6D%4B%8B%D5";
|
||||
|
@ -52,7 +52,7 @@ public class UrlQueryTest {
|
||||
|
||||
@Test
|
||||
public void parseTest4(){
|
||||
// https://github.com/dromara/hutool/issues/1989
|
||||
// https://github.com/chinabugotech/hutool/issues/1989
|
||||
String queryStr = "imageMogr2/thumbnail/x800/format/jpg";
|
||||
final UrlQuery query = UrlQuery.of(queryStr, CharsetUtil.CHARSET_UTF_8);
|
||||
assertEquals(queryStr, query.toString());
|
||||
|
@ -17,7 +17,7 @@ public class CharSequenceUtilTest {
|
||||
|
||||
@Test
|
||||
public void replaceTest2() {
|
||||
// https://gitee.com/dromara/hutool/issues/I4M16G
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I4M16G
|
||||
String replace = "#{A}";
|
||||
String result = CharSequenceUtil.replace(replace, "#{AAAAAAA}", "1");
|
||||
assertEquals(replace, result);
|
||||
@ -49,7 +49,7 @@ public class CharSequenceUtilTest {
|
||||
result = CharSequenceUtil.addSuffixIfNot(str, " is Good");
|
||||
assertEquals(str + " is Good", result);
|
||||
|
||||
// https://gitee.com/dromara/hutool/issues/I4NS0F
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I4NS0F
|
||||
result = CharSequenceUtil.addSuffixIfNot("", "/");
|
||||
assertEquals("/", result);
|
||||
}
|
||||
@ -89,7 +89,7 @@ public class CharSequenceUtilTest {
|
||||
|
||||
@Test
|
||||
public void subPreGbkTest() {
|
||||
// https://gitee.com/dromara/hutool/issues/I4JO2E
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I4JO2E
|
||||
String s = "华硕K42Intel酷睿i31代2G以下独立显卡不含机械硬盘固态硬盘120GB-192GB4GB-6GB";
|
||||
|
||||
String v = CharSequenceUtil.subPreGbk(s, 40, false);
|
||||
@ -101,7 +101,7 @@ public class CharSequenceUtilTest {
|
||||
|
||||
@Test
|
||||
public void startWithTest() {
|
||||
// https://gitee.com/dromara/hutool/issues/I4MV7Q
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I4MV7Q
|
||||
assertFalse(CharSequenceUtil.startWith("123", "123", false, true));
|
||||
assertFalse(CharSequenceUtil.startWith(null, null, false, true));
|
||||
assertFalse(CharSequenceUtil.startWith("abc", "abc", true, true));
|
||||
|
@ -35,9 +35,9 @@ public class NamingCaseTest {
|
||||
.set("H#case", "H#case")
|
||||
.set("PNLabel", "PN_label")
|
||||
.set("wPRunOZTime", "w_P_run_OZ_time")
|
||||
// https://github.com/dromara/hutool/issues/2070
|
||||
// https://github.com/chinabugotech/hutool/issues/2070
|
||||
.set("customerNickV2", "customer_nick_v2")
|
||||
// https://gitee.com/dromara/hutool/issues/I4X9TT
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I4X9TT
|
||||
.set("DEPT_NAME","DEPT_NAME")
|
||||
.forEach((key, value) -> assertEquals(value, NamingCase.toUnderlineCase(key)));
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import java.util.List;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* https://gitee.com/dromara/hutool/issues/IA8WE0
|
||||
* https://gitee.com/chinabugotech/hutool/issues/IA8WE0
|
||||
*/
|
||||
public class IssueIA8WE0Test {
|
||||
@Test
|
||||
|
@ -74,7 +74,7 @@ public class StrSplitterTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* https://github.com/dromara/hutool/issues/2099
|
||||
* https://github.com/chinabugotech/hutool/issues/2099
|
||||
*/
|
||||
@Test
|
||||
public void splitByRegexTest(){
|
||||
|
@ -11,7 +11,7 @@ public class ExecutorBuilderTest {
|
||||
@Test
|
||||
@Disabled
|
||||
public void CallerRunsPolicyTest(){
|
||||
// https://gitee.com/dromara/hutool/pulls/660
|
||||
// https://gitee.com/chinabugotech/hutool/pulls/660
|
||||
final ThreadPoolExecutor executor = ExecutorBuilder.create().setCorePoolSize(1).setMaxPoolSize(1).setHandler(RejectPolicy.BLOCK.getValue()).build();
|
||||
executor.execute(()-> Console.log("### 1"));
|
||||
executor.execute(()-> Console.log("### 2"));
|
||||
|
@ -21,7 +21,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class SyncFinisherTest {
|
||||
/**
|
||||
* https://gitee.com/dromara/hutool/issues/I716SX
|
||||
* https://gitee.com/chinabugotech/hutool/issues/I716SX
|
||||
* 设置ExceptionHandler捕获异常
|
||||
*/
|
||||
@Test
|
||||
@ -44,7 +44,7 @@ public class SyncFinisherTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* https://gitee.com/dromara/hutool/issues/I716SX
|
||||
* https://gitee.com/chinabugotech/hutool/issues/I716SX
|
||||
* 默认情况下吞掉异常
|
||||
*/
|
||||
@Test
|
||||
|
@ -39,7 +39,7 @@ public class EscapeUtilTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* https://gitee.com/dromara/hutool/issues/I49JU8
|
||||
* https://gitee.com/chinabugotech/hutool/issues/I49JU8
|
||||
*/
|
||||
@Test
|
||||
public void escapeAllTest2(){
|
||||
|
@ -45,7 +45,7 @@ public class HexUtilTest {
|
||||
String a = "0x3544534F444";
|
||||
assertTrue(HexUtil.isHexNumber(a));
|
||||
|
||||
// https://gitee.com/dromara/hutool/issues/I62H7K
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I62H7K
|
||||
a = "0x0000000000000001158e460913d00000";
|
||||
assertTrue(HexUtil.isHexNumber(a));
|
||||
|
||||
@ -53,7 +53,7 @@ public class HexUtilTest {
|
||||
a = "0x0000001000T00001158e460913d00000";
|
||||
assertFalse(HexUtil.isHexNumber(a));
|
||||
|
||||
// 错误的,https://github.com/dromara/hutool/issues/2857
|
||||
// 错误的,https://github.com/chinabugotech/hutool/issues/2857
|
||||
a = "-1";
|
||||
assertFalse(HexUtil.isHexNumber(a));
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* https://github.com/dromara/hutool/issues/3136
|
||||
* https://github.com/chinabugotech/hutool/issues/3136
|
||||
*/
|
||||
public class Issue3136Test {
|
||||
|
||||
|
@ -0,0 +1,13 @@
|
||||
package cn.hutool.core.util;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class IssueIBP6T1Test {
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
@Test
|
||||
void isValidCard10Test(){
|
||||
Assertions.assertEquals("true", IdcardUtil.isValidCard10("1608214(1)")[2]);
|
||||
Assertions.assertEquals("true", IdcardUtil.isValidCard10("1608214(1)")[2]);
|
||||
}
|
||||
}
|
@ -416,7 +416,7 @@ public class StrUtilTest {
|
||||
containsAny = StrUtil.containsAny("aaabbbccc", "d", "c");
|
||||
assertTrue(containsAny);
|
||||
|
||||
// https://gitee.com/dromara/hutool/issues/I7WSYD
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I7WSYD
|
||||
containsAny = StrUtil.containsAny("你好啊", "嗯", null);
|
||||
assertFalse(containsAny);
|
||||
}
|
||||
@ -651,7 +651,7 @@ public class StrUtilTest {
|
||||
|
||||
@Test
|
||||
public void issueI6KKFUTest() {
|
||||
// https://gitee.com/dromara/hutool/issues/I6KKFU
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I6KKFU
|
||||
final String template = "I''m {0} years old.";
|
||||
final String result = StrUtil.indexedFormat(template, 10);
|
||||
assertEquals("I'm 10 years old.", result);
|
||||
|
@ -4,8 +4,12 @@ import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import cn.hutool.core.lang.TypeReference;
|
||||
import lombok.Data;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class TypeUtilTest {
|
||||
@ -97,4 +101,29 @@ public class TypeUtilTest {
|
||||
private T level;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* fix github:issue#3873
|
||||
*/
|
||||
@Test
|
||||
public void getActualTypeForGenericArrayTest() {
|
||||
TypeReference<GenericArray<GenericArrayEle>> typeReference = new TypeReference<GenericArray<GenericArrayEle>>() {
|
||||
|
||||
};
|
||||
|
||||
Type levelType = TypeUtil.getFieldType(GenericArray.class, "level");
|
||||
Type actualType = TypeUtil.getActualType(typeReference.getType(), levelType);
|
||||
assertEquals(ArrayUtil.getArrayType(GenericArrayEle.class), actualType);
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class GenericArray<T> {
|
||||
private T[] level;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class GenericArrayEle {
|
||||
private Long uid;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,79 @@
|
||||
package cn.hutool.core.util;
|
||||
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.exceptions.UtilException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class VersionUtilTest {
|
||||
|
||||
@Test
|
||||
void isGreaterThan() {
|
||||
String currentVersion = " 1.0.2";
|
||||
assertTrue(VersionUtil.isGreaterThan(currentVersion, "1.0.1"));
|
||||
assertTrue(VersionUtil.isGreaterThan(currentVersion, "1"));
|
||||
assertFalse(VersionUtil.isGreaterThan(currentVersion, "1.1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isGreaterThanOrEqual() {
|
||||
String currentVersion = "1.0.2 ";
|
||||
assertTrue(VersionUtil.isGreaterThanOrEqual(currentVersion, "1.0.1"));
|
||||
assertTrue(VersionUtil.isGreaterThanOrEqual(currentVersion, "1.0.2"));
|
||||
assertFalse(VersionUtil.isGreaterThanOrEqual(currentVersion, "1.1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isLessThan() {
|
||||
String currentVersion = "1.0.2";
|
||||
assertTrue(VersionUtil.isLessThan(currentVersion, "1.0.3"));
|
||||
assertFalse(VersionUtil.isLessThan(currentVersion, "1"));
|
||||
assertTrue(VersionUtil.isLessThan(currentVersion, "1.1"));
|
||||
assertFalse(VersionUtil.isLessThan(currentVersion, "1.0.2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isLessThanOrEqual() {
|
||||
String currentVersion = "1.0.2";
|
||||
assertTrue(VersionUtil.isLessThanOrEqual(currentVersion, "1.0.2"));
|
||||
assertFalse(VersionUtil.isLessThanOrEqual(currentVersion, "1.0.1"));
|
||||
assertTrue(VersionUtil.isLessThanOrEqual(currentVersion, "1.1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchEl() {
|
||||
String currentVersion = "1.0.2";
|
||||
assertTrue(VersionUtil.matchEl(currentVersion, "1.0.1;1.0.2"));
|
||||
assertFalse(VersionUtil.matchEl(currentVersion, "1.0.1;1.0.3"));
|
||||
assertTrue(VersionUtil.matchEl(currentVersion, "1.0.9;1.0.1-1.0.2"));
|
||||
assertTrue(VersionUtil.matchEl(currentVersion, "1.0.9;1.0.1-1.0.3"));
|
||||
|
||||
assertTrue(VersionUtil.matchEl(currentVersion, "1.0.9,1.0.1-1.0.3", ","));
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchEl_Exception_whenVersionDelimiterIllegal() {
|
||||
List<String> illegalDelimiters = ListUtil.of("-", ">", ">=", "<", "<=", "≥", "≤", null, "", " ");
|
||||
|
||||
for (String illegalDelimiter : illegalDelimiters) {
|
||||
assertThrows(UtilException.class, () -> {
|
||||
String currentVersion = "1.0.2";
|
||||
VersionUtil.matchEl(currentVersion, "1.0.1;1.0.2", illegalDelimiter);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void anyMatch() {
|
||||
String currentVersion = "1.0.2";
|
||||
assertTrue(VersionUtil.anyMatch(currentVersion, ListUtil.of("1.0.1", "1.0.3", "1.0.2")));
|
||||
assertTrue(VersionUtil.anyMatch(currentVersion, "1.0.1", "1.0.2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMatchEl() {
|
||||
}
|
||||
}
|
@ -149,7 +149,7 @@ public class ZipUtilTest {
|
||||
@Test
|
||||
@Disabled
|
||||
public void zipStreamTest(){
|
||||
//https://github.com/dromara/hutool/issues/944
|
||||
//https://github.com/chinabugotech/hutool/issues/944
|
||||
final String dir = "d:/test";
|
||||
final String zip = "d:/test.zip";
|
||||
//noinspection IOStreamConstructor
|
||||
@ -164,7 +164,7 @@ public class ZipUtilTest {
|
||||
@Test
|
||||
@Disabled
|
||||
public void zipStreamTest2(){
|
||||
// https://github.com/dromara/hutool/issues/944
|
||||
// https://github.com/chinabugotech/hutool/issues/944
|
||||
final String file1 = "d:/test/a.txt";
|
||||
final String file2 = "d:/test/a.txt";
|
||||
final String file3 = "d:/test/asn1.key";
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.8.36</version>
|
||||
<version>5.8.37-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-cron</artifactId>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.8.36</version>
|
||||
<version>5.8.37-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-crypto</artifactId>
|
||||
|
@ -61,7 +61,7 @@ public class KeyUtilTest {
|
||||
|
||||
@Test
|
||||
public void generateSm4KeyTest(){
|
||||
// https://github.com/dromara/hutool/issues/2150
|
||||
// https://github.com/chinabugotech/hutool/issues/2150
|
||||
assertEquals(16, KeyUtil.generateKey("sm4").getEncoded().length);
|
||||
assertEquals(32, KeyUtil.generateKey("sm4", 256).getEncoded().length);
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ public class PemUtilTest {
|
||||
@Test
|
||||
@Disabled
|
||||
public void readECPrivateKeyTest2() {
|
||||
// https://gitee.com/dromara/hutool/issues/I37Z75
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I37Z75
|
||||
final byte[] d = PemUtil.readPem(FileUtil.getInputStream("d:/test/keys/priv.key"));
|
||||
final byte[] publicKey = PemUtil.readPem(FileUtil.getInputStream("d:/test/keys/pub.key"));
|
||||
|
||||
|
@ -6,14 +6,15 @@ import cn.hutool.crypto.digest.mac.SM4MacEngine;
|
||||
import org.bouncycastle.crypto.CipherParameters;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.bouncycastle.crypto.params.ParametersWithIV;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class CBCBlockCipherMacEngineTest {
|
||||
|
||||
@Test
|
||||
public void SM4CMACTest(){
|
||||
// https://github.com/dromara/hutool/issues/2206
|
||||
// https://github.com/chinabugotech/hutool/issues/2206
|
||||
final byte[] key = new byte[16];
|
||||
final CipherParameters parameter = new KeyParameter(KeyUtil.generateKey("SM4", key).getEncoded());
|
||||
Mac mac = new Mac(new SM4MacEngine(parameter));
|
||||
@ -27,7 +28,7 @@ public class CBCBlockCipherMacEngineTest {
|
||||
|
||||
@Test
|
||||
public void SM4CMACWithIVTest(){
|
||||
// https://github.com/dromara/hutool/issues/2206
|
||||
// https://github.com/chinabugotech/hutool/issues/2206
|
||||
final byte[] key = new byte[16];
|
||||
final byte[] iv = new byte[16];
|
||||
CipherParameters parameter = new KeyParameter(KeyUtil.generateKey("SM4", key).getEncoded());
|
||||
|
@ -5,11 +5,12 @@ import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.crypto.KeyUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.symmetric.ZUC;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* Hmac单元测试
|
||||
* @author Looly
|
||||
@ -84,7 +85,7 @@ public class HmacTest {
|
||||
|
||||
@Test
|
||||
public void sm4CMACTest(){
|
||||
// https://github.com/dromara/hutool/issues/2206
|
||||
// https://github.com/chinabugotech/hutool/issues/2206
|
||||
final byte[] key = new byte[16];
|
||||
HMac mac = new HMac(HmacAlgorithm.SM4CMAC,
|
||||
KeyUtil.generateKey("SM4", key));
|
||||
|
@ -10,7 +10,7 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* https://gitee.com/dromara/hutool/issues/I4EMST
|
||||
* https://gitee.com/chinabugotech/hutool/issues/I4EMST
|
||||
*/
|
||||
public class Sm4StreamTest {
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.8.36</version>
|
||||
<version>5.8.37-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-db</artifactId>
|
||||
|
@ -148,7 +148,7 @@ public interface Dialect extends Serializable {
|
||||
* @since 5.7.2
|
||||
*/
|
||||
default PreparedStatement psForCount(Connection conn, SqlBuilder sqlBuilder) throws SQLException {
|
||||
// https://gitee.com/dromara/hutool/issues/I713XQ
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I713XQ
|
||||
// 为了兼容informix等数据库,此处使用count(*)而非count(1)
|
||||
sqlBuilder = sqlBuilder
|
||||
.insertPreFragment("SELECT count(*) from(")
|
||||
|
@ -45,7 +45,8 @@ public class DialectFactory implements DriverNamePool {
|
||||
*/
|
||||
private static Dialect internalNewDialect(String driverName) {
|
||||
if (StrUtil.isNotBlank(driverName)) {
|
||||
if (DRIVER_MYSQL.equalsIgnoreCase(driverName) || DRIVER_MYSQL_V6.equalsIgnoreCase(driverName)) {
|
||||
if (DRIVER_MYSQL.equalsIgnoreCase(driverName) || DRIVER_MYSQL_V6.equalsIgnoreCase(driverName)
|
||||
|| DRIVER_GOLDENDB.equalsIgnoreCase(driverName)) {
|
||||
return new MysqlDialect();
|
||||
} else if (DRIVER_ORACLE.equalsIgnoreCase(driverName) || DRIVER_ORACLE_OLD.equalsIgnoreCase(driverName)) {
|
||||
return new OracleDialect();
|
||||
@ -164,6 +165,9 @@ public class DialectFactory implements DriverNamePool {
|
||||
} else if (nameContainsProductInfo.contains("opengauss")) {
|
||||
// OpenGauss
|
||||
driver = DRIVER_OPENGAUSS;
|
||||
} else if (nameContainsProductInfo.contains("goldendb")) {
|
||||
// GoldenDB
|
||||
driver = DRIVER_GOLDENDB;
|
||||
}
|
||||
|
||||
return driver;
|
||||
|
@ -116,4 +116,8 @@ public interface DriverNamePool {
|
||||
* JDBC 驱动 OpenGauss
|
||||
*/
|
||||
String DRIVER_OPENGAUSS = "org.opengauss.Driver";
|
||||
/**
|
||||
* JDBC 驱动 GoldenDB
|
||||
*/
|
||||
String DRIVER_GOLDENDB = "com.goldendb.jdbc.Driver";
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ public class DbTest {
|
||||
@Test
|
||||
@Disabled
|
||||
public void queryFetchTest() throws SQLException {
|
||||
// https://gitee.com/dromara/hutool/issues/I4JXWN
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I4JXWN
|
||||
Db.use().query((conn->{
|
||||
PreparedStatement ps = conn.prepareStatement("select * from table",
|
||||
ResultSet.TYPE_FORWARD_ONLY,
|
||||
|
@ -91,7 +91,7 @@ public class DsTest {
|
||||
|
||||
@Test
|
||||
public void c3p0DsUserAndPassTest() {
|
||||
// https://gitee.com/dromara/hutool/issues/I4T7XZ
|
||||
// https://gitee.com/chinabugotech/hutool/issues/I4T7XZ
|
||||
DSFactory.setCurrentDSFactory(new C3p0DSFactory());
|
||||
ComboPooledDataSource ds = (ComboPooledDataSource) ((DataSourceWrapper) DSFactory.get("mysql")).getRaw();
|
||||
assertEquals("root", ds.getUser());
|
||||
|
10
hutool-db/src/test/java/cn/hutool/db/GlobalDbConfigTest.java
Normal file
10
hutool-db/src/test/java/cn/hutool/db/GlobalDbConfigTest.java
Normal file
@ -0,0 +1,10 @@
|
||||
package cn.hutool.db;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class GlobalDbConfigTest {
|
||||
@Test
|
||||
void createDbSettingTest(){
|
||||
GlobalDbConfig.createDbSetting();
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@ import org.junit.jupiter.api.Test;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* https://gitee.com/dromara/hutool/issues/I73770
|
||||
* https://gitee.com/chinabugotech/hutool/issues/I73770
|
||||
*/
|
||||
public class IssueI73770Test {
|
||||
@Test
|
||||
|
@ -42,6 +42,7 @@ public class DialectFactoryTest {
|
||||
map.put("oscar",DRIVER_OSCAR);
|
||||
map.put("sybase",DRIVER_SYBASE);
|
||||
map.put("mariadb",DRIVER_MARIADB);
|
||||
map.put("goldendb",DRIVER_GOLDENDB);
|
||||
|
||||
|
||||
map.forEach((k,v) -> assertEquals(v,
|
||||
|
@ -51,4 +51,4 @@ idleConnectionTestPeriod = 0
|
||||
# c3p0全局的PreparedStatements缓存的大小。如果maxStatements与maxStatementsPerConnection均为0,则缓存不生效,只要有一个不为0,则语句的缓存就能生效。如果默认值: 0
|
||||
maxStatements = 0
|
||||
# maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。默认值: 0
|
||||
maxStatementsPerConnection = 0
|
||||
maxStatementsPerConnection = 0
|
||||
|
@ -48,4 +48,4 @@ testOnBorrow = false
|
||||
# (boolean) 指明是否在归还到池中前进行检验 注意: 设置为true 后如果要生效,validationQuery 参数必须设置为非空字符串
|
||||
testOnReturn = false
|
||||
# (boolean) 指明连接是否被空闲连接回收器( 如果有) 进行检验。 如果检测失败, 则连接将被从池中去除。注意: 设置为true 后如果要生效,validationQuery 参数必须设置为非空字符串
|
||||
testWhileIdle = false
|
||||
testWhileIdle = false
|
||||
|
@ -52,4 +52,4 @@ connectionInitSqls = SELECT 1
|
||||
# 属性类型是字符串,通过别名的方式配置扩展插件, 常用的插件有: 监控统计用的filter:stat 日志用的filter:log4j 防御sql注入的filter:wall
|
||||
filters = stat
|
||||
# 类型是List<com.alibaba.druid.filter.Filter>, 如果同时配置了filters和proxyFilters, 是组合关系,并非替换关系
|
||||
proxyFilters =
|
||||
proxyFilters =
|
||||
|
@ -40,4 +40,4 @@ minimumIdle = 10
|
||||
# 连接池中允许的最大连接数。缺省值:10;推荐的公式:((core_count * 2) + effective_spindle_count)
|
||||
maximumPoolSize = 10
|
||||
# 连接只读数据库时配置为true, 保证安全
|
||||
readOnly = false
|
||||
readOnly = false
|
||||
|
@ -48,4 +48,4 @@ testOnBorrow = false
|
||||
# (boolean) 指明是否在归还到池中前进行检验 注意: 设置为true 后如果要生效,validationQuery 参数必须设置为非空字符串
|
||||
testOnReturn = false
|
||||
# (boolean) 指明连接是否被空闲连接回收器( 如果有) 进行检验。 如果检测失败, 则连接将被从池中去除。注意: 设置为true 后如果要生效,validationQuery 参数必须设置为非空字符串
|
||||
testWhileIdle = false
|
||||
testWhileIdle = false
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.8.36</version>
|
||||
<version>5.8.37-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-dfa</artifactId>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user