mirror of
https://gitee.com/dromara/hutool.git
synced 2026-02-09 09:16:26 +08:00
Compare commits
8 Commits
6c6d6f6ed2
...
a32fac8760
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a32fac8760 | ||
|
|
266cd0754c | ||
|
|
6fe9f31eaf | ||
|
|
fa79eee1ce | ||
|
|
12547f4d4c | ||
|
|
af48fa825c | ||
|
|
c12b87f8b7 | ||
|
|
915f7c429b |
@@ -1,10 +1,13 @@
|
|||||||
|
|
||||||
# 🚀Changelog
|
# 🚀Changelog
|
||||||
-------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------
|
||||||
# 5.8.44
|
# 5.8.44(2026-01-12)
|
||||||
### 🐣新特性
|
### 🐣新特性
|
||||||
|
* 【core 】 `NumberUtil.parseNumber`增加支持科学计数法(pr#4211@Github)
|
||||||
|
* 【captcha】 `AbstractCaptcha`增加`setStroke`方法支持线条粗细(issue#IDJQ15@Gitee)
|
||||||
|
|
||||||
### 🐞Bug修复
|
### 🐞Bug修复
|
||||||
|
* 【json 】 修复`JSONUtil.wrap`忽略错误问题(issue#4210@Github)
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------
|
||||||
# 5.8.43(2026-01-04)
|
# 5.8.43(2026-01-04)
|
||||||
|
|||||||
@@ -9,10 +9,7 @@ import cn.hutool.core.io.IORuntimeException;
|
|||||||
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.io.IoUtil;
|
||||||
import cn.hutool.core.util.URLUtil;
|
import cn.hutool.core.util.URLUtil;
|
||||||
|
|
||||||
import java.awt.AlphaComposite;
|
import java.awt.*;
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Font;
|
|
||||||
import java.awt.Image;
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -65,6 +62,7 @@ public abstract class AbstractCaptcha implements ICaptcha {
|
|||||||
* 文字透明度
|
* 文字透明度
|
||||||
*/
|
*/
|
||||||
protected AlphaComposite textAlpha;
|
protected AlphaComposite textAlpha;
|
||||||
|
protected Stroke stroke;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造,使用随机验证码生成器生成验证码
|
* 构造,使用随机验证码生成器生成验证码
|
||||||
@@ -271,4 +269,13 @@ public abstract class AbstractCaptcha implements ICaptcha {
|
|||||||
this.textAlpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, textAlpha);
|
this.textAlpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, textAlpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置画笔线条特征,如线条宽度等
|
||||||
|
*
|
||||||
|
* @param stroke 画笔
|
||||||
|
* @since 5.8.44
|
||||||
|
*/
|
||||||
|
public void setStroke(Stroke stroke) {
|
||||||
|
this.stroke = stroke;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,6 +118,11 @@ public class CircleCaptcha extends AbstractCaptcha {
|
|||||||
* @param g {@link Graphics2D}
|
* @param g {@link Graphics2D}
|
||||||
*/
|
*/
|
||||||
private void drawInterfere(Graphics2D g) {
|
private void drawInterfere(Graphics2D g) {
|
||||||
|
// issue#IDJQ15 自定义线条特征(粗细等)
|
||||||
|
if(null != this.stroke){
|
||||||
|
g.setStroke(this.stroke);
|
||||||
|
}
|
||||||
|
|
||||||
final ThreadLocalRandom random = RandomUtil.getRandom();
|
final ThreadLocalRandom random = RandomUtil.getRandom();
|
||||||
|
|
||||||
for (int i = 0; i < this.interfereCount; i++) {
|
for (int i = 0; i < this.interfereCount; i++) {
|
||||||
|
|||||||
@@ -110,6 +110,11 @@ public class LineCaptcha extends AbstractCaptcha {
|
|||||||
* @param g {@link Graphics2D}画笔
|
* @param g {@link Graphics2D}画笔
|
||||||
*/
|
*/
|
||||||
private void drawInterfere(Graphics2D g) {
|
private void drawInterfere(Graphics2D g) {
|
||||||
|
// issue#IDJQ15 自定义线条特征(粗细等)
|
||||||
|
if(null != this.stroke){
|
||||||
|
g.setStroke(this.stroke);
|
||||||
|
}
|
||||||
|
|
||||||
final ThreadLocalRandom random = RandomUtil.getRandom();
|
final ThreadLocalRandom random = RandomUtil.getRandom();
|
||||||
// 干扰线
|
// 干扰线
|
||||||
for (int i = 0; i < this.interfereCount; i++) {
|
for (int i = 0; i < this.interfereCount; i++) {
|
||||||
|
|||||||
@@ -193,7 +193,6 @@ public class ShearCaptcha extends AbstractCaptcha {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("SameParameterValue")
|
@SuppressWarnings("SameParameterValue")
|
||||||
private void drawInterfere(Graphics g, int x1, int y1, int x2, int y2, int thickness, Color c) {
|
private void drawInterfere(Graphics g, int x1, int y1, int x2, int y2, int thickness, Color c) {
|
||||||
|
|
||||||
// The thick line is in fact a filled polygon
|
// The thick line is in fact a filled polygon
|
||||||
g.setColor(c);
|
g.setColor(c);
|
||||||
int dX = x2 - x1;
|
int dX = x2 - x1;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import javax.net.ssl.TrustManager;
|
|||||||
public class SSLUtil {
|
public class SSLUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建{@link SSLContext},默认新人全部
|
* 创建{@link SSLContext},默认信任全部
|
||||||
*
|
*
|
||||||
* @param protocol SSL协议,例如TLS等
|
* @param protocol SSL协议,例如TLS等
|
||||||
* @return {@link SSLContext}
|
* @return {@link SSLContext}
|
||||||
|
|||||||
@@ -2783,6 +2783,16 @@ public class NumberUtil {
|
|||||||
// issue@4197@Github 转为半角
|
// issue@4197@Github 转为半角
|
||||||
numberStr = Convert.toDBC(numberStr);
|
numberStr = Convert.toDBC(numberStr);
|
||||||
|
|
||||||
|
// issue#IDJ1NS@Gitee 处理科学计数法E+格式
|
||||||
|
// NumberFormat对E+格式支持不佳,使用BigDecimal直接解析
|
||||||
|
if (StrUtil.containsIgnoreCase(numberStr, "e")) {
|
||||||
|
try {
|
||||||
|
return new BigDecimal(numberStr);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// BigDecimal解析失败,继续使用NumberFormat尝试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final NumberFormat format = NumberFormat.getInstance();
|
final NumberFormat format = NumberFormat.getInstance();
|
||||||
if (format instanceof DecimalFormat) {
|
if (format instanceof DecimalFormat) {
|
||||||
|
|||||||
@@ -388,6 +388,16 @@ public class NumberUtilTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void issueIDJ1NSTest(){
|
||||||
|
final String numberstr1 = "8.37095942E+9";
|
||||||
|
final BigDecimal result1 = (BigDecimal) NumberUtil.parseNumber(numberstr1);
|
||||||
|
final String numberstr2 = "8.37095942e+9";
|
||||||
|
final BigDecimal result2 = (BigDecimal) NumberUtil.parseNumber(numberstr2);
|
||||||
|
assertEquals(new BigDecimal("8370959420").toPlainString(), result1.toPlainString());
|
||||||
|
assertEquals(new BigDecimal("8370959420").toPlainString(), result2.toPlainString());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseHexNumberTest() {
|
public void parseHexNumberTest() {
|
||||||
// 千位分隔符去掉
|
// 千位分隔符去掉
|
||||||
|
|||||||
@@ -739,7 +739,7 @@ public class JSONUtil {
|
|||||||
* <li>map =》 JSONObject</li>
|
* <li>map =》 JSONObject</li>
|
||||||
* <li>standard property (Double, String, et al) =》 原对象</li>
|
* <li>standard property (Double, String, et al) =》 原对象</li>
|
||||||
* <li>来自于java包 =》 字符串</li>
|
* <li>来自于java包 =》 字符串</li>
|
||||||
* <li>其它 =》 尝试包装为JSONObject,否则返回{@code null}</li>
|
* <li>其它 =》 尝试包装为JSONObject,如果{@link JSONConfig#isIgnoreError()}为true时返回{@code null}, 否则抛出异常</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param object 被包装的对象
|
* @param object 被包装的对象
|
||||||
@@ -805,7 +805,11 @@ public class JSONUtil {
|
|||||||
// 默认按照JSONObject对待
|
// 默认按照JSONObject对待
|
||||||
return new JSONObject(object, jsonConfig);
|
return new JSONObject(object, jsonConfig);
|
||||||
} catch (final Exception exception) {
|
} catch (final Exception exception) {
|
||||||
return null;
|
// issue#4210 只有设置忽略错误时才返回null
|
||||||
|
if(jsonConfig.isIgnoreError()){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
throw exception;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
45
hutool-json/src/test/java/cn/hutool/json/Issue4210Test.java
Normal file
45
hutool-json/src/test/java/cn/hutool/json/Issue4210Test.java
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package cn.hutool.json;
|
||||||
|
|
||||||
|
import cn.hutool.core.exceptions.InvocationTargetRuntimeException;
|
||||||
|
import cn.hutool.core.lang.Console;
|
||||||
|
import cn.hutool.core.lang.ObjectId;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class Issue4210Test {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void setValueTest(){
|
||||||
|
final JSONObject jsonObject = new JSONObject();
|
||||||
|
|
||||||
|
final TestEntity entity = new TestEntity("张三", "社畜");
|
||||||
|
Assertions.assertThrows(InvocationTargetRuntimeException.class, () -> jsonObject.set("entity",entity));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class BaseEntity implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实体唯一标识符
|
||||||
|
*/
|
||||||
|
private String _id;
|
||||||
|
private ObjectId id;
|
||||||
|
|
||||||
|
public String get_id() {
|
||||||
|
return _id == null ? id.toString() : _id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class TestEntity extends BaseEntity{
|
||||||
|
private String name;
|
||||||
|
private String desc;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
hutool-json/src/test/java/cn/hutool/json/Issue4214Test.java
Normal file
32
hutool-json/src/test/java/cn/hutool/json/Issue4214Test.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package cn.hutool.json;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
public class Issue4214Test {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void toBeanTest(){
|
||||||
|
LicenseInfo licenseInfo = new LicenseInfo();
|
||||||
|
licenseInfo.setAuthTypeEnum(AuthTypeEnum.OFFICIAL);
|
||||||
|
|
||||||
|
String jsonStr = JSONUtil.toJsonStr(licenseInfo);
|
||||||
|
assertEquals("{\"authTypeEnum\":\"OFFICIAL\"}", jsonStr);
|
||||||
|
|
||||||
|
// 这里反序列化会报错
|
||||||
|
LicenseInfo bean = JSONUtil.toBean(jsonStr, LicenseInfo.class);
|
||||||
|
assertEquals(AuthTypeEnum.OFFICIAL, bean.getAuthTypeEnum());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
static class LicenseInfo{
|
||||||
|
private AuthTypeEnum authTypeEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AuthTypeEnum{
|
||||||
|
OFFICIAL,
|
||||||
|
SELF_BUILD
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user