Prepare release

This commit is contained in:
Looly 2019-12-02 18:25:37 +08:00
commit af4f37a054
73 changed files with 1133 additions and 869 deletions

View File

@ -3,6 +3,29 @@
-------------------------------------------------------------------------------------------------------------
## 5.0.7
### 新特性
* 【core 】 解决NumberUtil导致的ambiguous问题issue#630@Github
* 【core 】 BeanUtil.isEmpty()忽略字段支持增加isNotEmptyissue#629@Github
* 【extra】 邮件发送后获取message-idissue#I15FKR@Gitee
* 【core 】 CaseInsensitiveMap/CamelCaseMap增加toStringissue#636@Github
* 【core 】 XmlUtil多节点改进issue#I15I0R@Gitee
* 【core 】 Thread.excAsync修正为execAsyncissue#642@Github
* 【core 】 FileUtil.getAbsolutePath修正正则issue#648@Github
* 【core 】 NetUtil增加getNetworkInterface方法issue#I15WEL@Gitee
* 【core 】 增加ReflectUtil.getFieldMap方法issue#I15WJ7@Gitee
### Bug修复
* 【extra】 修复SFTP.upload上传失败的问题issue#I15O40@Gitee
* 【db】 修复findLike匹配错误问题
* 【core 】 修复scale方法透明无效问题issue#I15L5S@Gitee
* 【extra】 修复exec返回无效issue#I15L5S@Gitee
* 【cron】 修复CronPattern注释pr#646@Github
* 【json】 修复LocalDateTime等JDK8时间对象不被支持的问题issue#644@Github
-------------------------------------------------------------------------------------------------------------
## 5.0.6
### 新特性

View File

@ -116,21 +116,21 @@ Hutool的存在就是为了减少代码搜索成本避免网络上参差不
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</dependency>
```
### Gradle
```
compile 'cn.hutool:hutool-all:5.0.6'
compile 'cn.hutool:hutool-all:5.0.7'
```
### 非Maven项目
点击以下任一链接,下载`hutool-all-X.X.X.jar`即可:
- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.0.6/)
- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.0.6/)
- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.0.7/)
- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.0.7/)
> 注意
> Hutool 5.x支持JDK8+对Android平台没有测试不能保证所有工具类获工具方法可用。

View File

@ -1 +1 @@
5.0.6
5.0.7

View File

@ -1 +1 @@
var version = '5.0.6'
var version = '5.0.7'

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-all</artifactId>

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-aop</artifactId>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-bloomFilter</artifactId>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-bom</artifactId>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-cache</artifactId>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-captcha</artifactId>

View File

@ -93,7 +93,6 @@ public class CaptchaTest {
@Test
@Ignore
public void ShearCaptchaWithMathTest() {
// 定义图形验证码的长和宽
ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(200, 45, 4, 4);
captcha.setGenerator(new MathGenerator());

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-core</artifactId>

View File

@ -117,32 +117,6 @@ public class BeanUtil {
return PropertyEditorManager.findEditor(type);
}
/**
* 判断Bean中是否有值为null的字段
*
* @param bean Bean
* @return 是否有值为null的字段
* @deprecated 请使用{@link #hasNullField(Object)}
*/
@Deprecated
public static boolean hasNull(Object bean) {
final Field[] fields = ClassUtil.getDeclaredFields(bean.getClass());
Object fieldValue = null;
for (Field field : fields) {
field.setAccessible(true);
try {
fieldValue = field.get(bean);
} catch (Exception e) {
//ignore
}
if (null == fieldValue) {
return true;
}
}
return false;
}
/**
* 获取{@link BeanDesc} Bean描述信息
*
@ -292,7 +266,7 @@ public class BeanUtil {
/**
* 解析Bean中的属性值
*
* @param <T> 属性值类型
* @param <T> 属性值类型
* @param bean Bean对象支持MapListCollectionArray
* @param expression 表达式例如person.friend[5].name
* @return Bean属性值
@ -676,17 +650,31 @@ public class BeanUtil {
return bean;
}
/**
* 判断Bean是否为非空对象非空对象表示本身不为<code>null</code>或者含有非<code>null</code>属性的对象
*
* @param bean Bean对象
* @param ignoreFiledNames 忽略检查的字段名
* @return 是否为空<code>true</code> - / <code>false</code> - 非空
* @since 5.0.7
*/
public static boolean isNotEmpty(Object bean, String... ignoreFiledNames) {
return false == isEmpty(bean, ignoreFiledNames);
}
/**
* 判断Bean是否为空对象空对象表示本身为<code>null</code>或者所有属性都为<code>null</code>
*
* @param bean Bean对象
* @param bean Bean对象
* @param ignoreFiledNames 忽略检查的字段名
* @return 是否为空<code>true</code> - / <code>false</code> - 非空
* @since 4.1.10
*/
public static boolean isEmpty(Object bean) {
public static boolean isEmpty(Object bean, String... ignoreFiledNames) {
if (null != bean) {
for (Field field : ReflectUtil.getFields(bean.getClass())) {
if (null != ReflectUtil.getFieldValue(bean, field)) {
if ((false == ArrayUtil.contains(ignoreFiledNames, field.getName()))
&& null != ReflectUtil.getFieldValue(bean, field)) {
return false;
}
}
@ -698,16 +686,18 @@ public class BeanUtil {
* 判断Bean是否包含值为<code>null</code>的属性<br>
* 对象本身为<code>null</code>也返回true
*
* @param bean Bean对象
* @param bean Bean对象
* @param ignoreFiledNames 忽略检查的字段名
* @return 是否包含值为<code>null</code>的属性<code>true</code> - 包含 / <code>false</code> - 不包含
* @since 4.1.10
*/
public static boolean hasNullField(Object bean) {
public static boolean hasNullField(Object bean, String... ignoreFiledNames) {
if (null == bean) {
return true;
}
for (Field field : ReflectUtil.getFields(bean.getClass())) {
if (null == ReflectUtil.getFieldValue(bean, field)) {
if ((false == ArrayUtil.contains(ignoreFiledNames, field.getName()))//
&& null == ReflectUtil.getFieldValue(bean, field)) {
return true;
}
}

View File

@ -4,6 +4,8 @@ import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
@ -444,7 +446,35 @@ public class Convert {
public static Date toDate(Object value, Date defaultValue) {
return convertQuietly(Date.class, value, defaultValue);
}
/**
* LocalDateTime<br>
* 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
* @since 5.0.7
*/
public static Date toLocalDateTime(Object value, Date defaultValue) {
return convertQuietly(LocalDateTime.class, value, defaultValue);
}
/**
* Instant<br>
* 如果给定的值为空或者转换失败返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
* @since 5.0.7
*/
public static Date toInstant(Object value, Date defaultValue) {
return convertQuietly(Instant.class, value, defaultValue);
}
/**
* 转换为Date<br>
* 如果给定的值为空或者转换失败返回<code>null</code><br>

View File

@ -1,41 +1,46 @@
package cn.hutool.core.convert.impl;
import cn.hutool.core.convert.AbstractConverter;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import java.time.temporal.TemporalAccessor;
import java.util.Calendar;
import java.util.Date;
/**
* 原始类型转换器<br>
* 支持类型为<br>
* <ul>
* <li><code>byte</code></li>
* <li><code>short</code></li>
* <li><code>int</code></li>
* <li><code>long</code></li>
* <li><code>int</code></li>
* <li><code>long</code></li>
* <li><code>float</code></li>
* <li><code>double</code></li>
* <li><code>char</code></li>
* <li><code>boolean</code></li>
* </ul>
*
* @author Looly
*
* @author Looly
*/
public class PrimitiveConverter extends AbstractConverter<Object> {
private static final long serialVersionUID = 1L;
private Class<?> targetType;
/**
* 构造<br>
*
* @param clazz 需要转换的原始
* @throws IllegalArgumentException 传入的转换类型非原始类型时抛出
*/
public PrimitiveConverter(Class<?> clazz) {
if(null == clazz){
if (null == clazz) {
throw new NullPointerException("PrimitiveConverter not allow null target type!");
}else if(false == clazz.isPrimitive()){
} else if (false == clazz.isPrimitive()) {
throw new IllegalArgumentException("[" + clazz + "] is not a primitive class!");
}
this.targetType = clazz;
@ -47,80 +52,95 @@ public class PrimitiveConverter extends AbstractConverter<Object> {
if (byte.class == this.targetType) {
if (value instanceof Number) {
return ((Number) value).byteValue();
} else if(value instanceof Boolean) {
return BooleanUtil.toByte((Boolean)value);
} else if (value instanceof Boolean) {
return BooleanUtil.toByte((Boolean) value);
}
final String valueStr = convertToStr(value);
if (StrUtil.isBlank(valueStr)) {
return 0;
}
return Byte.parseByte(valueStr);
} else if (short.class == this.targetType) {
if (value instanceof Number) {
return ((Number) value).shortValue();
} else if(value instanceof Boolean) {
return BooleanUtil.toShort((Boolean)value);
} else if (value instanceof Boolean) {
return BooleanUtil.toShort((Boolean) value);
}
final String valueStr = convertToStr(value);
if (StrUtil.isBlank(valueStr)) {
return 0;
}
return Short.parseShort(valueStr);
} else if (int.class == this.targetType) {
if (value instanceof Number) {
return ((Number) value).intValue();
} else if(value instanceof Boolean) {
return BooleanUtil.toInt((Boolean)value);
} else if (value instanceof Boolean) {
return BooleanUtil.toInt((Boolean) value);
} else if (value instanceof Date) {
return ((Date) value).getTime();
} else if (value instanceof Calendar) {
return ((Calendar) value).getTimeInMillis();
} else if (value instanceof TemporalAccessor) {
return DateUtil.toInstant((TemporalAccessor) value).toEpochMilli();
}
final String valueStr = convertToStr(value);
if (StrUtil.isBlank(valueStr)) {
return 0;
}
return NumberUtil.parseInt(valueStr);
} else if (long.class == this.targetType) {
if (value instanceof Number) {
return ((Number) value).longValue();
} else if(value instanceof Boolean) {
return BooleanUtil.toLong((Boolean)value);
} else if (value instanceof Boolean) {
return BooleanUtil.toLong((Boolean) value);
} else if (value instanceof Date) {
return ((Date) value).getTime();
} else if (value instanceof Calendar) {
return ((Calendar) value).getTimeInMillis();
} else if (value instanceof TemporalAccessor) {
return DateUtil.toInstant((TemporalAccessor) value).toEpochMilli();
}
final String valueStr = convertToStr(value);
if (StrUtil.isBlank(valueStr)) {
return 0;
}
return NumberUtil.parseLong(valueStr);
} else if (float.class == this.targetType) {
if (value instanceof Number) {
return ((Number) value).floatValue();
} else if(value instanceof Boolean) {
return BooleanUtil.toFloat((Boolean)value);
} else if (value instanceof Boolean) {
return BooleanUtil.toFloat((Boolean) value);
}
final String valueStr = convertToStr(value);
if (StrUtil.isBlank(valueStr)) {
return 0;
}
return Float.parseFloat(valueStr);
} else if (double.class == this.targetType) {
if (value instanceof Number) {
return ((Number) value).doubleValue();
} else if(value instanceof Boolean) {
return BooleanUtil.toDouble((Boolean)value);
} else if (value instanceof Boolean) {
return BooleanUtil.toDouble((Boolean) value);
}
final String valueStr = convertToStr(value);
if (StrUtil.isBlank(valueStr)) {
return 0;
}
return Double.parseDouble(valueStr);
} else if (char.class == this.targetType) {
if(value instanceof Character){
return ((Character)value).charValue();
} else if(value instanceof Boolean) {
return BooleanUtil.toChar((Boolean)value);
if (value instanceof Character) {
//noinspection UnnecessaryUnboxing
return ((Character) value).charValue();
} else if (value instanceof Boolean) {
return BooleanUtil.toChar((Boolean) value);
}
final String valueStr = convertToStr(value);
if (StrUtil.isBlank(valueStr)) {
@ -128,8 +148,9 @@ public class PrimitiveConverter extends AbstractConverter<Object> {
}
return valueStr.charAt(0);
} else if (boolean.class == this.targetType) {
if(value instanceof Boolean){
return ((Boolean)value).booleanValue();
if (value instanceof Boolean) {
//noinspection UnnecessaryUnboxing
return ((Boolean) value).booleanValue();
}
String valueStr = convertToStr(value);
return BooleanUtil.toBoolean(valueStr);
@ -139,12 +160,12 @@ public class PrimitiveConverter extends AbstractConverter<Object> {
}
return 0;
}
@Override
protected String convertToStr(Object value) {
return StrUtil.trim(super.convertToStr(value));
}
@Override
@SuppressWarnings("unchecked")
public Class<Object> getTargetType() {

View File

@ -10,21 +10,20 @@ import cn.hutool.core.convert.Convert;
* 基本类型的getter接口抽象实现所有类型的值获取都是通过将getObj获得的值转换而来<br>
* 用户只需实现getObj方法即可其他类型将会从Object结果中转换
* 在不提供默认值的情况下 如果值不存在或获取错误返回null<br>
*
* @author Looly
*/
public abstract class OptNullBasicTypeFromObjectGetter<K> extends OptNullBasicTypeGetter<K>{
public interface OptNullBasicTypeFromObjectGetter<K> extends OptNullBasicTypeGetter<K>{
@Override
public String getStr(K key, String defaultValue) {
default String getStr(K key, String defaultValue) {
final Object obj = getObj(key);
if(null == obj) {
return defaultValue;
}
return Convert.toStr(obj, defaultValue);
}
@Override
public Integer getInt(K key, Integer defaultValue) {
default Integer getInt(K key, Integer defaultValue) {
final Object obj = getObj(key);
if(null == obj) {
return defaultValue;
@ -32,8 +31,7 @@ public abstract class OptNullBasicTypeFromObjectGetter<K> extends OptNullBasicTy
return Convert.toInt(obj, defaultValue);
}
@Override
public Short getShort(K key, Short defaultValue) {
default Short getShort(K key, Short defaultValue) {
final Object obj = getObj(key);
if(null == obj) {
return defaultValue;
@ -41,8 +39,7 @@ public abstract class OptNullBasicTypeFromObjectGetter<K> extends OptNullBasicTy
return Convert.toShort(obj, defaultValue);
}
@Override
public Boolean getBool(K key, Boolean defaultValue) {
default Boolean getBool(K key, Boolean defaultValue) {
final Object obj = getObj(key);
if(null == obj) {
return defaultValue;
@ -50,8 +47,7 @@ public abstract class OptNullBasicTypeFromObjectGetter<K> extends OptNullBasicTy
return Convert.toBool(obj, defaultValue);
}
@Override
public Long getLong(K key, Long defaultValue) {
default Long getLong(K key, Long defaultValue) {
final Object obj = getObj(key);
if(null == obj) {
return defaultValue;
@ -59,17 +55,15 @@ public abstract class OptNullBasicTypeFromObjectGetter<K> extends OptNullBasicTy
return Convert.toLong(obj, defaultValue);
}
@Override
public Character getChar(K key, Character defaultValue) {
default Character getChar(K key, Character defaultValue) {
final Object obj = getObj(key);
if(null == obj) {
return defaultValue;
}
return Convert.toChar(obj, defaultValue);
}
@Override
public Float getFloat(K key, Float defaultValue) {
default Float getFloat(K key, Float defaultValue) {
final Object obj = getObj(key);
if(null == obj) {
return defaultValue;
@ -77,8 +71,7 @@ public abstract class OptNullBasicTypeFromObjectGetter<K> extends OptNullBasicTy
return Convert.toFloat(obj, defaultValue);
}
@Override
public Double getDouble(K key, Double defaultValue) {
default Double getDouble(K key, Double defaultValue) {
final Object obj = getObj(key);
if(null == obj) {
return defaultValue;
@ -86,8 +79,7 @@ public abstract class OptNullBasicTypeFromObjectGetter<K> extends OptNullBasicTy
return Convert.toDouble(obj, defaultValue);
}
@Override
public Byte getByte(K key, Byte defaultValue) {
default Byte getByte(K key, Byte defaultValue) {
final Object obj = getObj(key);
if(null == obj) {
return defaultValue;
@ -95,8 +87,7 @@ public abstract class OptNullBasicTypeFromObjectGetter<K> extends OptNullBasicTy
return Convert.toByte(obj, defaultValue);
}
@Override
public BigDecimal getBigDecimal(K key, BigDecimal defaultValue) {
default BigDecimal getBigDecimal(K key, BigDecimal defaultValue) {
final Object obj = getObj(key);
if(null == obj) {
return defaultValue;
@ -104,26 +95,23 @@ public abstract class OptNullBasicTypeFromObjectGetter<K> extends OptNullBasicTy
return Convert.toBigDecimal(obj, defaultValue);
}
@Override
public BigInteger getBigInteger(K key, BigInteger defaultValue) {
default BigInteger getBigInteger(K key, BigInteger defaultValue) {
final Object obj = getObj(key);
if(null == obj) {
return defaultValue;
}
return Convert.toBigInteger(obj, defaultValue);
}
@Override
public <E extends Enum<E>> E getEnum(Class<E> clazz, K key, E defaultValue) {
default <E extends Enum<E>> E getEnum(Class<E> clazz, K key, E defaultValue) {
final Object obj = getObj(key);
if(null == obj) {
return defaultValue;
}
return Convert.toEnum(clazz, obj, defaultValue);
}
@Override
public Date getDate(K key, Date defaultValue) {
default Date getDate(K key, Date defaultValue) {
final Object obj = getObj(key);
if(null == obj) {
return defaultValue;

View File

@ -12,70 +12,57 @@ import cn.hutool.core.convert.Convert;
*
* @author Looly
*/
public abstract class OptNullBasicTypeFromStringGetter<K> extends OptNullBasicTypeGetter<K> {
public interface OptNullBasicTypeFromStringGetter<K> extends OptNullBasicTypeGetter<K> {
@Override
public Object getObj(K key, Object defaultValue) {
default Object getObj(K key, Object defaultValue) {
return getStr(key, null == defaultValue ? null : defaultValue.toString());
}
@Override
public Integer getInt(K key, Integer defaultValue) {
default Integer getInt(K key, Integer defaultValue) {
return Convert.toInt(getStr(key), defaultValue);
}
@Override
public Short getShort(K key, Short defaultValue) {
default Short getShort(K key, Short defaultValue) {
return Convert.toShort(getStr(key), defaultValue);
}
@Override
public Boolean getBool(K key, Boolean defaultValue) {
default Boolean getBool(K key, Boolean defaultValue) {
return Convert.toBool(getStr(key), defaultValue);
}
@Override
public Long getLong(K key, Long defaultValue) {
default Long getLong(K key, Long defaultValue) {
return Convert.toLong(getStr(key), defaultValue);
}
@Override
public Character getChar(K key, Character defaultValue) {
default Character getChar(K key, Character defaultValue) {
return Convert.toChar(getStr(key), defaultValue);
}
@Override
public Float getFloat(K key, Float defaultValue) {
default Float getFloat(K key, Float defaultValue) {
return Convert.toFloat(getStr(key), defaultValue);
}
@Override
public Double getDouble(K key, Double defaultValue) {
default Double getDouble(K key, Double defaultValue) {
return Convert.toDouble(getStr(key), defaultValue);
}
@Override
public Byte getByte(K key, Byte defaultValue) {
default Byte getByte(K key, Byte defaultValue) {
return Convert.toByte(getStr(key), defaultValue);
}
@Override
public BigDecimal getBigDecimal(K key, BigDecimal defaultValue) {
default BigDecimal getBigDecimal(K key, BigDecimal defaultValue) {
return Convert.toBigDecimal(getStr(key), defaultValue);
}
@Override
public BigInteger getBigInteger(K key, BigInteger defaultValue) {
default BigInteger getBigInteger(K key, BigInteger defaultValue) {
return Convert.toBigInteger(getStr(key), defaultValue);
}
@Override
public <E extends Enum<E>> E getEnum(Class<E> clazz, K key, E defaultValue) {
default <E extends Enum<E>> E getEnum(Class<E> clazz, K key, E defaultValue) {
return Convert.toEnum(clazz, getStr(key), defaultValue);
}
@Override
public Date getDate(K key, Date defaultValue) {
default Date getDate(K key, Date defaultValue) {
return Convert.toDate(getStr(key), defaultValue);
}
}

View File

@ -8,13 +8,12 @@ import java.util.Date;
* 基本类型的getter接口抽象实现<br>
* 提供一个统一的接口定义返回不同类型的值基本类型<br>
* 在不提供默认值的情况下 如果值不存在或获取错误返回null<br>
* 用户只需实现{@code com.xiaoleilu.hutool.getter.OptBasicTypeGetter}接口即可
* 用户只需实现{@link OptBasicTypeGetter}接口即可
* @author Looly
*/
public abstract class OptNullBasicTypeGetter<K> implements BasicTypeGetter<K>, OptBasicTypeGetter<K>{
public interface OptNullBasicTypeGetter<K> extends BasicTypeGetter<K>, OptBasicTypeGetter<K>{
@Override
public Object getObj(K key) {
default Object getObj(K key) {
return getObj(key, null);
}
@ -25,8 +24,7 @@ public abstract class OptNullBasicTypeGetter<K> implements BasicTypeGetter<K>, O
* @param key 属性名
* @return 属性值
*/
@Override
public String getStr(K key){
default String getStr(K key){
return this.getStr(key, null);
}
@ -37,8 +35,7 @@ public abstract class OptNullBasicTypeGetter<K> implements BasicTypeGetter<K>, O
* @param key 属性名
* @return 属性值
*/
@Override
public Integer getInt(K key) {
default Integer getInt(K key) {
return this.getInt(key, null);
}
@ -49,8 +46,7 @@ public abstract class OptNullBasicTypeGetter<K> implements BasicTypeGetter<K>, O
* @param key 属性名
* @return 属性值
*/
@Override
public Short getShort(K key){
default Short getShort(K key){
return this.getShort(key, null);
}
@ -61,8 +57,7 @@ public abstract class OptNullBasicTypeGetter<K> implements BasicTypeGetter<K>, O
* @param key 属性名
* @return 属性值
*/
@Override
public Boolean getBool(K key){
default Boolean getBool(K key){
return this.getBool(key, null);
}
@ -73,8 +68,7 @@ public abstract class OptNullBasicTypeGetter<K> implements BasicTypeGetter<K>, O
* @param key 属性名
* @return 属性值
*/
@Override
public Long getLong(K key){
default Long getLong(K key){
return this.getLong(key, null);
}
@ -85,8 +79,7 @@ public abstract class OptNullBasicTypeGetter<K> implements BasicTypeGetter<K>, O
* @param key 属性名
* @return 属性值
*/
@Override
public Character getChar(K key){
default Character getChar(K key){
return this.getChar(key, null);
}
@ -97,8 +90,7 @@ public abstract class OptNullBasicTypeGetter<K> implements BasicTypeGetter<K>, O
* @param key 属性名
* @return 属性值
*/
@Override
public Float getFloat(K key){
default Float getFloat(K key){
return this.getFloat(key, null);
}
@ -109,11 +101,10 @@ public abstract class OptNullBasicTypeGetter<K> implements BasicTypeGetter<K>, O
* @param key 属性名
* @return 属性值
*/
@Override
public Double getDouble(K key){
default Double getDouble(K key){
return this.getDouble(key, null);
}
/**
* 获取byte型属性值<br>
* 无值或获取错误返回null
@ -121,8 +112,7 @@ public abstract class OptNullBasicTypeGetter<K> implements BasicTypeGetter<K>, O
* @param key 属性名
* @return 属性值
*/
@Override
public Byte getByte(K key){
default Byte getByte(K key){
return this.getByte(key, null);
}
@ -133,8 +123,7 @@ public abstract class OptNullBasicTypeGetter<K> implements BasicTypeGetter<K>, O
* @param key 属性名
* @return 属性值
*/
@Override
public BigDecimal getBigDecimal(K key){
default BigDecimal getBigDecimal(K key){
return this.getBigDecimal(key, null);
}
@ -145,8 +134,7 @@ public abstract class OptNullBasicTypeGetter<K> implements BasicTypeGetter<K>, O
* @param key 属性名
* @return 属性值
*/
@Override
public BigInteger getBigInteger(K key){
default BigInteger getBigInteger(K key){
return this.getBigInteger(key, null);
}
@ -158,8 +146,7 @@ public abstract class OptNullBasicTypeGetter<K> implements BasicTypeGetter<K>, O
* @param key 属性名
* @return 属性值
*/
@Override
public <E extends Enum<E>> E getEnum(Class<E> clazz, K key) {
default <E extends Enum<E>> E getEnum(Class<E> clazz, K key) {
return this.getEnum(clazz, key, null);
}
@ -170,8 +157,7 @@ public abstract class OptNullBasicTypeGetter<K> implements BasicTypeGetter<K>, O
* @param key 属性名
* @return 属性值
*/
@Override
public Date getDate(K key) {
default Date getDate(K key) {
return this.getDate(key, null);
}
}

View File

@ -53,7 +53,7 @@ public class Img implements Serializable {
/**
* 目标图片文件格式用于写出
*/
private String targetImageType = ImgUtil.IMAGE_TYPE_JPG;
private String targetImageType;
/**
* 计算x,y坐标的时候是否从中心做为原始坐标开始计算
*/
@ -140,7 +140,22 @@ public class Img implements Serializable {
* @param srcImage 来源图片
*/
public Img(BufferedImage srcImage) {
this(srcImage, null);
}
/**
* 构造
*
* @param srcImage 来源图片
* @param targetImageType 目标图片类型
* @since 5.0.7
*/
public Img(BufferedImage srcImage, String targetImageType) {
this.srcImage = srcImage;
if(null == targetImageType){
targetImageType = ImgUtil.IMAGE_TYPE_JPG;
}
this.targetImageType = targetImageType;
}
/**
@ -294,15 +309,14 @@ public class Img implements Serializable {
srcHeight = srcImage.getHeight(null);
srcWidth = srcImage.getWidth(null);
if (null == fixedColor) {// 补白
fixedColor = Color.WHITE;
}
final BufferedImage image = new BufferedImage(width, height, getTypeInt());
Graphics2D g = image.createGraphics();
// 设置背景
g.setBackground(fixedColor);
g.clearRect(0, 0, width, height);
if(null != fixedColor){
g.setBackground(fixedColor);
g.clearRect(0, 0, width, height);
}
// 在中间贴图
g.drawImage(srcImage, (width - srcWidth) / 2, (height - srcHeight) / 2, srcWidth, srcHeight, fixedColor, null);
@ -586,6 +600,7 @@ public class Img implements Serializable {
}
if (targetFile.exists()) {
//noinspection ResultOfMethodCallIgnored
targetFile.delete();
}
@ -624,6 +639,7 @@ public class Img implements Serializable {
* @see BufferedImage#TYPE_INT_RGB
*/
private int getTypeInt() {
//noinspection SwitchStatementWithTooFewBranches
switch (this.targetImageType) {
case ImgUtil.IMAGE_TYPE_PNG:
return BufferedImage.TYPE_INT_ARGB;
@ -678,6 +694,7 @@ public class Img implements Serializable {
if (degree >= 90) {
if (degree / 90 % 2 == 1) {
int temp = height;
//noinspection SuspiciousNameCombination
height = width;
width = temp;
}

View File

@ -171,17 +171,20 @@ public class ImgUtil {
/**
* 缩放图像按高度和宽度缩放<br>
* 缩放后默认为jpeg格式
* 缩放后默认格式与源图片相同无法识别原图片默认JPG
*
* @param srcImageFile 源图像文件地址
* @param destImageFile 缩放后的图像地址
* @param width 缩放后的宽度
* @param height 缩放后的高度
* @param fixedColor 比例不对时补充的颜色不补充为<code>null</code>
* @param fixedColor 补充的颜色不补充为<code>null</code>
* @throws IORuntimeException IO异常
*/
public static void scale(File srcImageFile, File destImageFile, int width, int height, Color fixedColor) throws IORuntimeException {
write(scale(read(srcImageFile), width, height, fixedColor), destImageFile);
Img.from(srcImageFile)//
.setTargetImageType(FileUtil.extName(destImageFile))//
.scale(width, height, fixedColor)//
.write(destImageFile);
}
/**
@ -397,12 +400,12 @@ public class ImgUtil {
if (srcWidth % destWidth == 0) {
cols = srcWidth / destWidth;
} else {
cols = (int) Math.floor(srcWidth / destWidth) + 1;
cols = (int) Math.floor((double)srcWidth / destWidth) + 1;
}
if (srcHeight % destHeight == 0) {
rows = srcHeight / destHeight;
} else {
rows = (int) Math.floor(srcHeight / destHeight) + 1;
rows = (int) Math.floor((double)srcHeight / destHeight) + 1;
}
// 循环建立切片
Image tag;

View File

@ -1,23 +1,65 @@
package cn.hutool.core.io;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.file.FileCopier;
import cn.hutool.core.io.file.FileMode;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.io.file.*;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.io.file.FileReader.ReaderHandler;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.io.file.LineSeparator;
import cn.hutool.core.io.file.Tailer;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.*;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.core.util.ZipUtil;
import java.io.*;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.io.Reader;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.nio.file.*;
import java.nio.file.CopyOption;
import java.nio.file.DirectoryStream;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.DecimalFormat;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.jar.JarFile;
import java.util.regex.Pattern;
import java.util.zip.CRC32;
@ -562,8 +604,8 @@ public class FileUtil {
if (ArrayUtil.isEmpty(subFiles)) {
return 0L;// empty directory
}
for (int i = 0; i < subFiles.length; i++) {
size += size(subFiles[i]);
for (File subFile : subFiles) {
size += size(subFile);
}
return size;
} else {
@ -629,6 +671,7 @@ public class FileUtil {
if (false == file.exists()) {
mkParentDirs(file);
try {
//noinspection ResultOfMethodCallIgnored
file.createNewFile();
} catch (Exception e) {
throw new IORuntimeException(e);
@ -672,6 +715,7 @@ public class FileUtil {
public static File mkParentDirs(File file) {
final File parentFile = file.getParentFile();
if (null != parentFile && false == parentFile.exists()) {
//noinspection ResultOfMethodCallIgnored
parentFile.mkdirs();
}
return parentFile;
@ -835,6 +879,7 @@ public class FileUtil {
final File[] files = directory.listFiles();
if (ArrayUtil.isEmpty(files)) {
// 空文件夹则删除之
//noinspection ResultOfMethodCallIgnored
directory.delete();
} else {
for (File childFile : files) {
@ -871,6 +916,7 @@ public class FileUtil {
return null;
}
if (false == dir.exists()) {
//noinspection ResultOfMethodCallIgnored
dir.mkdirs();
}
return dir;
@ -918,7 +964,9 @@ public class FileUtil {
try {
File file = File.createTempFile(prefix, suffix, dir).getCanonicalFile();
if (isReCreat) {
//noinspection ResultOfMethodCallIgnored
file.delete();
//noinspection ResultOfMethodCallIgnored
file.createNewFile();
}
return file;
@ -1083,6 +1131,7 @@ public class FileUtil {
}
if (isOverride && dest.isFile()) {// 只有目标为文件的情况下覆盖之
//noinspection ResultOfMethodCallIgnored
dest.delete();
}
@ -1238,7 +1287,7 @@ public class FileUtil {
}
// 给定的路径已经是绝对路径了
return StrUtil.C_SLASH == path.charAt(0) || path.matches("^[a-zA-Z]:[/\\\\].*");
return StrUtil.C_SLASH == path.charAt(0) || path.matches("^[a-zA-Z]:([/\\\\].*)?");
}
/**

View File

@ -60,7 +60,7 @@ public class CamelCaseLinkedMap<K, V> extends CamelCaseMap<K, V> {
* @param loadFactor 加载因子
*/
public CamelCaseLinkedMap(int initialCapacity, float loadFactor) {
super(new HashMap<K, V>(initialCapacity, loadFactor));
super(new HashMap<>(initialCapacity, loadFactor));
}
// ------------------------------------------------------------------------- Constructor end
}

View File

@ -62,7 +62,7 @@ public class CamelCaseMap<K, V> extends CustomKeyMap<K, V> {
* @param loadFactor 加载因子
*/
public CamelCaseMap(int initialCapacity, float loadFactor) {
super(new HashMap<K, V>(initialCapacity, loadFactor));
super(new HashMap<>(initialCapacity, loadFactor));
}
// ------------------------------------------------------------------------- Constructor end
@ -74,7 +74,7 @@ public class CamelCaseMap<K, V> extends CustomKeyMap<K, V> {
*/
@Override
protected Object customKey(Object key) {
if (null != key && key instanceof CharSequence) {
if (key instanceof CharSequence) {
key = StrUtil.toCamelCase(key.toString());
}
return key;

View File

@ -61,7 +61,7 @@ public class CaseInsensitiveLinkedMap<K, V> extends CaseInsensitiveMap<K, V> {
* @param loadFactor 加载因子
*/
public CaseInsensitiveLinkedMap(int initialCapacity, float loadFactor) {
super(new LinkedHashMap<K, V>(initialCapacity, loadFactor));
super(new LinkedHashMap<>(initialCapacity, loadFactor));
}
// ------------------------------------------------------------------------- Constructor end
}

View File

@ -21,7 +21,7 @@ import cn.hutool.core.util.StrUtil;
* @author looly
* @since 3.2.0
*/
public class MapProxy extends OptNullBasicTypeFromObjectGetter<Object> implements Map<Object, Object>, InvocationHandler, Serializable {
public class MapProxy implements Map<Object, Object>, OptNullBasicTypeFromObjectGetter<Object>, InvocationHandler, Serializable {
private static final long serialVersionUID = 1L;
@SuppressWarnings("rawtypes")
@ -89,7 +89,7 @@ public class MapProxy extends OptNullBasicTypeFromObjectGetter<Object> implement
return map.remove(key);
}
@SuppressWarnings("unchecked")
@SuppressWarnings({"unchecked", "NullableProblems"})
@Override
public void putAll(Map<?, ?> m) {
map.putAll(m);
@ -100,19 +100,19 @@ public class MapProxy extends OptNullBasicTypeFromObjectGetter<Object> implement
map.clear();
}
@SuppressWarnings("unchecked")
@SuppressWarnings({"unchecked", "NullableProblems"})
@Override
public Set<Object> keySet() {
return map.keySet();
}
@SuppressWarnings("unchecked")
@SuppressWarnings({"unchecked", "NullableProblems"})
@Override
public Collection<Object> values() {
return map.values();
}
@SuppressWarnings("unchecked")
@SuppressWarnings({"unchecked", "NullableProblems"})
@Override
public Set<Entry<Object, Object>> entrySet() {
return map.entrySet();

View File

@ -79,6 +79,7 @@ public class MapWrapper<K, V> implements Map<K, V>, Iterable<Map.Entry<K, V>>, S
}
@Override
@SuppressWarnings("NullableProblems")
public void putAll(Map<? extends K, ? extends V> m) {
raw.putAll(m);
}
@ -89,23 +90,31 @@ public class MapWrapper<K, V> implements Map<K, V>, Iterable<Map.Entry<K, V>>, S
}
@Override
public Set<K> keySet() {
return raw.keySet();
}
@Override
@SuppressWarnings("NullableProblems")
public Collection<V> values() {
return raw.values();
}
@Override
@SuppressWarnings("NullableProblems")
public Set<K> keySet() {
return raw.keySet();
}
@Override
@SuppressWarnings("NullableProblems")
public Set<Entry<K, V>> entrySet() {
return raw.entrySet();
}
@Override
@SuppressWarnings("NullableProblems")
public Iterator<Entry<K, V>> iterator() {
return this.entrySet().iterator();
}
@Override
public String toString() {
return raw.toString();
}
}

View File

@ -298,6 +298,32 @@ public class NetUtil {
}
}
/**
* 获取指定名称的网卡信息
*
* @param name 网络接口名例如Linux下默认是eth0
* @return 网卡未找到返回<code>null</code>
* @since 5.0.7
*/
public static NetworkInterface getNetworkInterface(String name) {
Enumeration<NetworkInterface> networkInterfaces;
try {
networkInterfaces = NetworkInterface.getNetworkInterfaces();
} catch (SocketException e) {
return null;
}
NetworkInterface netInterface;
while(networkInterfaces.hasMoreElements()){
netInterface = networkInterfaces.nextElement();
if(null != netInterface && name.equals(netInterface.getName())){
return netInterface;
}
}
return null;
}
/**
* 获取本机所有网卡
*

View File

@ -101,7 +101,7 @@ public class ThreadUtil {
* @param isDaemon 是否守护线程守护线程会在主线程结束后自动结束
* @return 执行的方法体
*/
public static Runnable excAsync(final Runnable runnable, boolean isDaemon) {
public static Runnable execAsync(final Runnable runnable, boolean isDaemon) {
Thread thread = new Thread(runnable);
thread.setDaemon(isDaemon);
thread.start();
@ -432,6 +432,7 @@ public class ThreadUtil {
* @param obj 对象所在线程
* @since 4.5.6
*/
@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
public static void sync(Object obj) {
synchronized (obj) {
try {

View File

@ -477,7 +477,7 @@ public class ArrayUtil {
* @return 新数组
* @since 4.0.8
*/
@SuppressWarnings("unchecked")
@SuppressWarnings({"unchecked", "SuspiciousSystemArraycopy"})
public static <T> Object insert(Object array, int index, T... newElements) {
if (isEmpty(newElements)) {
return array;
@ -541,6 +541,7 @@ public class ArrayUtil {
final int length = length(array);
final Object newArray = Array.newInstance(array.getClass().getComponentType(), newSize);
if (newSize > 0 && isNotEmpty(array)) {
//noinspection SuspiciousSystemArraycopy
System.arraycopy(array, 0, newArray, 0, Math.min(length, newSize));
}
return newArray;
@ -656,6 +657,7 @@ public class ArrayUtil {
* @since 3.0.6
*/
public static Object copy(Object src, int srcPos, Object dest, int destPos, int length) {
//noinspection SuspiciousSystemArraycopy
System.arraycopy(src, srcPos, dest, destPos, length);
return dest;
}
@ -671,6 +673,7 @@ public class ArrayUtil {
* @since 3.0.6
*/
public static Object copy(Object src, Object dest, int length) {
//noinspection SuspiciousSystemArraycopy
System.arraycopy(src, 0, dest, 0, length);
return dest;
}
@ -1477,7 +1480,7 @@ public class ArrayUtil {
final Integer[] array = new Integer[length];
for (int i = 0; i < length; i++) {
array[i] = Integer.valueOf(values[i]);
array[i] = values[i];
}
return array;
}
@ -1499,7 +1502,7 @@ public class ArrayUtil {
final int[] array = new int[length];
for (int i = 0; i < length; i++) {
array[i] = values[i].intValue();
array[i] = values[i];
}
return array;
}
@ -1521,7 +1524,7 @@ public class ArrayUtil {
final Long[] array = new Long[length];
for (int i = 0; i < length; i++) {
array[i] = Long.valueOf(values[i]);
array[i] = values[i];
}
return array;
}
@ -1543,7 +1546,7 @@ public class ArrayUtil {
final long[] array = new long[length];
for (int i = 0; i < length; i++) {
array[i] = values[i].longValue();
array[i] = values[i];
}
return array;
}
@ -1565,7 +1568,7 @@ public class ArrayUtil {
final Character[] array = new Character[length];
for (int i = 0; i < length; i++) {
array[i] = Character.valueOf(values[i]);
array[i] = values[i];
}
return array;
}
@ -1587,7 +1590,7 @@ public class ArrayUtil {
char[] array = new char[length];
for (int i = 0; i < length; i++) {
array[i] = values[i].charValue();
array[i] = values[i];
}
return array;
}
@ -1609,7 +1612,7 @@ public class ArrayUtil {
final Byte[] array = new Byte[length];
for (int i = 0; i < length; i++) {
array[i] = Byte.valueOf(values[i]);
array[i] = values[i];
}
return array;
}
@ -1631,7 +1634,7 @@ public class ArrayUtil {
final byte[] array = new byte[length];
for (int i = 0; i < length; i++) {
array[i] = values[i].byteValue();
array[i] = ObjectUtil.defaultIfNull(values[i], (byte)0);
}
return array;
}
@ -1653,7 +1656,7 @@ public class ArrayUtil {
final Short[] array = new Short[length];
for (int i = 0; i < length; i++) {
array[i] = Short.valueOf(values[i]);
array[i] = values[i];
}
return array;
}
@ -1675,7 +1678,7 @@ public class ArrayUtil {
final short[] array = new short[length];
for (int i = 0; i < length; i++) {
array[i] = values[i].shortValue();
array[i] = ObjectUtil.defaultIfNull(values[i], (short)0);
}
return array;
}
@ -1697,7 +1700,7 @@ public class ArrayUtil {
final Float[] array = new Float[length];
for (int i = 0; i < length; i++) {
array[i] = Float.valueOf(values[i]);
array[i] = values[i];
}
return array;
}
@ -1719,7 +1722,7 @@ public class ArrayUtil {
final float[] array = new float[length];
for (int i = 0; i < length; i++) {
array[i] = values[i].floatValue();
array[i] = ObjectUtil.defaultIfNull(values[i], 0F);
}
return array;
}
@ -1741,7 +1744,7 @@ public class ArrayUtil {
final Double[] array = new Double[length];
for (int i = 0; i < length; i++) {
array[i] = Double.valueOf(values[i]);
array[i] = values[i];
}
return array;
}
@ -1763,7 +1766,7 @@ public class ArrayUtil {
final double[] array = new double[length];
for (int i = 0; i < length; i++) {
array[i] = values[i].doubleValue();
array[i] = ObjectUtil.defaultIfNull(values[i], 0D);
}
return array;
}
@ -1785,7 +1788,7 @@ public class ArrayUtil {
final Boolean[] array = new Boolean[length];
for (int i = 0; i < length; i++) {
array[i] = Boolean.valueOf(values[i]);
array[i] = values[i];
}
return array;
}
@ -1807,7 +1810,7 @@ public class ArrayUtil {
final boolean[] array = new boolean[length];
for (int i = 0; i < length; i++) {
array[i] = values[i].booleanValue();
array[i] = ObjectUtil.defaultIfNull(values[i], false);
}
return array;
}
@ -2841,6 +2844,7 @@ public class ArrayUtil {
* @throws IllegalArgumentException 参数对象不为数组对象
* @since 3.0.8
*/
@SuppressWarnings("SuspiciousSystemArraycopy")
public static Object remove(Object array, int index) throws IllegalArgumentException {
if (null == array) {
return null;
@ -3339,9 +3343,9 @@ public class ArrayUtil {
throw new IllegalArgumentException("Number array must not empty !");
}
T min = numberArray[0];
for (int i = 0; i < numberArray.length; i++) {
if (ObjectUtil.compare(min, numberArray[i]) > 0) {
min = numberArray[i];
for (T t : numberArray) {
if (ObjectUtil.compare(min, t) > 0) {
min = t;
}
}
return min;
@ -3359,7 +3363,7 @@ public class ArrayUtil {
throw new IllegalArgumentException("Number array must not empty !");
}
long min = numberArray[0];
for (int i = 0; i < numberArray.length; i++) {
for (int i = 1; i < numberArray.length; i++) {
if (min > numberArray[i]) {
min = numberArray[i];
}
@ -3379,7 +3383,7 @@ public class ArrayUtil {
throw new IllegalArgumentException("Number array must not empty !");
}
int min = numberArray[0];
for (int i = 0; i < numberArray.length; i++) {
for (int i = 1; i < numberArray.length; i++) {
if (min > numberArray[i]) {
min = numberArray[i];
}
@ -3399,7 +3403,7 @@ public class ArrayUtil {
throw new IllegalArgumentException("Number array must not empty !");
}
short min = numberArray[0];
for (int i = 0; i < numberArray.length; i++) {
for (int i = 1; i < numberArray.length; i++) {
if (min > numberArray[i]) {
min = numberArray[i];
}
@ -3419,7 +3423,7 @@ public class ArrayUtil {
throw new IllegalArgumentException("Number array must not empty !");
}
char min = numberArray[0];
for (int i = 0; i < numberArray.length; i++) {
for (int i = 1; i < numberArray.length; i++) {
if (min > numberArray[i]) {
min = numberArray[i];
}
@ -3439,7 +3443,7 @@ public class ArrayUtil {
throw new IllegalArgumentException("Number array must not empty !");
}
byte min = numberArray[0];
for (int i = 0; i < numberArray.length; i++) {
for (int i = 1; i < numberArray.length; i++) {
if (min > numberArray[i]) {
min = numberArray[i];
}
@ -3459,7 +3463,7 @@ public class ArrayUtil {
throw new IllegalArgumentException("Number array must not empty !");
}
double min = numberArray[0];
for (int i = 0; i < numberArray.length; i++) {
for (int i = 1; i < numberArray.length; i++) {
if (min > numberArray[i]) {
min = numberArray[i];
}
@ -3479,7 +3483,7 @@ public class ArrayUtil {
throw new IllegalArgumentException("Number array must not empty !");
}
float min = numberArray[0];
for (int i = 0; i < numberArray.length; i++) {
for (int i = 1; i < numberArray.length; i++) {
if (min > numberArray[i]) {
min = numberArray[i];
}
@ -3500,7 +3504,7 @@ public class ArrayUtil {
throw new IllegalArgumentException("Number array must not empty !");
}
T max = numberArray[0];
for (int i = 0; i < numberArray.length; i++) {
for (int i = 1; i < numberArray.length; i++) {
if (ObjectUtil.compare(max, numberArray[i]) < 0) {
max = numberArray[i];
}
@ -3520,7 +3524,7 @@ public class ArrayUtil {
throw new IllegalArgumentException("Number array must not empty !");
}
long max = numberArray[0];
for (int i = 0; i < numberArray.length; i++) {
for (int i = 1; i < numberArray.length; i++) {
if (max < numberArray[i]) {
max = numberArray[i];
}
@ -3540,7 +3544,7 @@ public class ArrayUtil {
throw new IllegalArgumentException("Number array must not empty !");
}
int max = numberArray[0];
for (int i = 0; i < numberArray.length; i++) {
for (int i = 1; i < numberArray.length; i++) {
if (max < numberArray[i]) {
max = numberArray[i];
}
@ -3560,7 +3564,7 @@ public class ArrayUtil {
throw new IllegalArgumentException("Number array must not empty !");
}
short max = numberArray[0];
for (int i = 0; i < numberArray.length; i++) {
for (int i = 1; i < numberArray.length; i++) {
if (max < numberArray[i]) {
max = numberArray[i];
}
@ -3580,7 +3584,7 @@ public class ArrayUtil {
throw new IllegalArgumentException("Number array must not empty !");
}
char max = numberArray[0];
for (int i = 0; i < numberArray.length; i++) {
for (int i = 1; i < numberArray.length; i++) {
if (max < numberArray[i]) {
max = numberArray[i];
}
@ -3600,7 +3604,7 @@ public class ArrayUtil {
throw new IllegalArgumentException("Number array must not empty !");
}
byte max = numberArray[0];
for (int i = 0; i < numberArray.length; i++) {
for (int i = 1; i < numberArray.length; i++) {
if (max < numberArray[i]) {
max = numberArray[i];
}
@ -3620,7 +3624,7 @@ public class ArrayUtil {
throw new IllegalArgumentException("Number array must not empty !");
}
double max = numberArray[0];
for (int i = 0; i < numberArray.length; i++) {
for (int i = 1; i < numberArray.length; i++) {
if (max < numberArray[i]) {
max = numberArray[i];
}
@ -3640,7 +3644,7 @@ public class ArrayUtil {
throw new IllegalArgumentException("Number array must not empty !");
}
float max = numberArray[0];
for (int i = 0; i < numberArray.length; i++) {
for (int i = 1; i < numberArray.length; i++) {
if (max < numberArray[i]) {
max = numberArray[i];
}

View File

@ -10,6 +10,7 @@ import cn.hutool.core.lang.Validator;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* 身份证相关工具类<br>
@ -323,10 +324,10 @@ public class IdcardUtil {
final char[] chars = mid.toCharArray();
int iflag = 8;
for (char c : chars) {
sum += Integer.valueOf(String.valueOf(c)) * iflag;
sum += Integer.parseInt(String.valueOf(c)) * iflag;
iflag--;
}
return (sum % 10 == 0 ? 0 : (10 - sum % 10)) == Integer.valueOf(end);
return (sum % 10 == 0 ? 0 : (10 - sum % 10)) == Integer.parseInt(end);
}
/**
@ -360,7 +361,7 @@ public class IdcardUtil {
char[] chars = mid.toCharArray();
int iflag = 7;
for (char c : chars) {
sum = sum + Integer.valueOf(String.valueOf(c)) * iflag;
sum = sum + Integer.parseInt(String.valueOf(c)) * iflag;
iflag--;
}
if ("A".equals(end.toUpperCase())) {
@ -389,13 +390,15 @@ public class IdcardUtil {
* @return 生日(yyyyMMdd)
*/
public static String getBirth(String idCard) {
Assert.notBlank(idCard, "id card must be not blank!");
final int len = idCard.length();
if (len < CHINA_ID_MIN_LENGTH) {
return null;
} else if (len == CHINA_ID_MIN_LENGTH) {
idCard = convert15To18(idCard);
}
return idCard.substring(6, 14);
return Objects.requireNonNull(idCard).substring(6, 14);
}
/**
@ -444,7 +447,7 @@ public class IdcardUtil {
} else if (len == CHINA_ID_MIN_LENGTH) {
idCard = convert15To18(idCard);
}
return Short.valueOf(idCard.substring(6, 10));
return Short.valueOf(Objects.requireNonNull(idCard).substring(6, 10));
}
/**
@ -460,7 +463,7 @@ public class IdcardUtil {
} else if (len == CHINA_ID_MIN_LENGTH) {
idCard = convert15To18(idCard);
}
return Short.valueOf(idCard.substring(10, 12));
return Short.valueOf(Objects.requireNonNull(idCard).substring(10, 12));
}
/**
@ -476,7 +479,7 @@ public class IdcardUtil {
} else if (len == CHINA_ID_MIN_LENGTH) {
idCard = convert15To18(idCard);
}
return Short.valueOf(idCard.substring(12, 14));
return Short.valueOf(Objects.requireNonNull(idCard).substring(12, 14));
}
/**
@ -495,7 +498,7 @@ public class IdcardUtil {
if (len == CHINA_ID_MIN_LENGTH) {
idCard = convert15To18(idCard);
}
char sCardChar = idCard.charAt(16);
char sCardChar = Objects.requireNonNull(idCard).charAt(16);
return (sCardChar % 2 != 0) ? 1 : 0;
}
@ -586,7 +589,7 @@ public class IdcardUtil {
int iSum = 0;
if (power.length == iArr.length) {
for (int i = 0; i < iArr.length; i++) {
iSum += Integer.valueOf(String.valueOf(iArr[i])) * power[i];
iSum += Integer.parseInt(String.valueOf(iArr[i])) * power[i];
}
}
return iSum;

File diff suppressed because it is too large Load Diff

View File

@ -184,6 +184,7 @@ public class ObjectUtil {
* @return 是否为null
*/
public static boolean isNull(Object obj) {
//noinspection ConstantConditions
return null == obj || obj.equals(null);
}
@ -194,6 +195,7 @@ public class ObjectUtil {
* @return 是否为null
*/
public static boolean isNotNull(Object obj) {
//noinspection ConstantConditions
return null != obj && false == obj.equals(null);
}

View File

@ -6,14 +6,17 @@ import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Filter;
import cn.hutool.core.lang.SimpleCache;
import cn.hutool.core.map.MapUtil;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
@ -133,6 +136,22 @@ public class ReflectUtil {
return null;
}
/**
* 获取指定类中字段名和字段对应的Map包括其父类中的字段
*
* @param beanClass
* @return 字段名和字段对应的Map
* @since 5.0.7
*/
public static Map<String, Field> getFieldMap(Class<?> beanClass){
final Field[] fields = getFields(beanClass);
final HashMap<String, Field> map = MapUtil.newHashMap(fields.length);
for (Field field : fields) {
map.put(field.getName(), field);
}
return map;
}
/**
* 获得一个类中所有字段列表包括其父类中的字段
*
@ -350,12 +369,7 @@ public class ReflectUtil {
*/
public static List<Method> getPublicMethods(Class<?> clazz, Method... excludeMethods) {
final HashSet<Method> excludeMethodSet = CollectionUtil.newHashSet(excludeMethods);
return getPublicMethods(clazz, new Filter<Method>() {
@Override
public boolean accept(Method method) {
return false == excludeMethodSet.contains(method);
}
});
return getPublicMethods(clazz, method -> false == excludeMethodSet.contains(method));
}
/**
@ -367,12 +381,7 @@ public class ReflectUtil {
*/
public static List<Method> getPublicMethods(Class<?> clazz, String... excludeMethodNames) {
final HashSet<String> excludeMethodNameSet = CollectionUtil.newHashSet(excludeMethodNames);
return getPublicMethods(clazz, new Filter<Method>() {
@Override
public boolean accept(Method method) {
return false == excludeMethodNameSet.contains(method.getName());
}
});
return getPublicMethods(clazz, method -> false == excludeMethodNameSet.contains(method.getName()));
}
/**
@ -770,7 +779,7 @@ public class ReflectUtil {
*/
public static <T> T invokeWithCheck(Object obj, Method method, Object... args) throws UtilException {
final Class<?>[] types = method.getParameterTypes();
if (null != types && null != args) {
if (null != args) {
Assert.isTrue(args.length == types.length, "Params length [{}] is not fit for param length [{}] of method !", args.length, types.length);
Class<?> type;
for (int i = 0; i < args.length; i++) {

View File

@ -2401,7 +2401,7 @@ public class StrUtil {
Byte dataByte;
for (int i = 0; i < data.length; i++) {
dataByte = data[i];
bytes[i] = (null == dataByte) ? -1 : dataByte.byteValue();
bytes[i] = (null == dataByte) ? -1 : dataByte;
}
return str(bytes, charset);
@ -4018,8 +4018,8 @@ public class StrUtil {
*/
public static int totalLength(CharSequence... strs) {
int totalLength = 0;
for (int i = 0; i < strs.length; i++) {
totalLength += (null == strs[i] ? 0 : strs[i].length());
for (CharSequence str : strs) {
totalLength += (null == str ? 0 : str.length());
}
return totalLength;
}

View File

@ -33,6 +33,7 @@ import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import cn.hutool.core.collection.CollUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@ -756,7 +757,12 @@ public class XmlUtil {
childNode = nodeList.item(i);
if (isElement(childNode)) {
childEle = (Element) childNode;
result.put(childEle.getNodeName(), childEle.getTextContent());
final Object value = result.get(childEle.getNodeName());
if(null != value){
result.put(childEle.getNodeName(), CollUtil.newArrayList(value, childEle.getTextContent()));
} else{
result.put(childEle.getNodeName(), childEle.getTextContent());
}
}
}
return result;

View File

@ -38,12 +38,12 @@ public class FileUtilTest {
String absolutePath2 = FileUtil.getAbsolutePath(absolutePath);
Assert.assertNotNull(absolutePath2);
Assert.assertEquals(absolutePath, absolutePath2);
}
@Test
public void getAbsolutePathTest2() {
String path = FileUtil.getAbsolutePath("中文.xml");
Assert.assertTrue(path.contains("中文.xml"));
path = FileUtil.getAbsolutePath("d:");
Assert.assertEquals("d:", path);
}
@Test
@ -134,6 +134,7 @@ public class FileUtilTest {
Assert.assertEquals("C:/bar", FileUtil.normalize("C:\\..\\bar"));
Assert.assertEquals("bar", FileUtil.normalize("../../bar"));
Assert.assertEquals("C:/bar", FileUtil.normalize("/C:/bar"));
Assert.assertEquals("C:", FileUtil.normalize("C:"));
Assert.assertEquals("\\/192.168.1.1/Share/", FileUtil.normalize("\\\\192.168.1.1\\Share\\"));
}

View File

@ -191,13 +191,13 @@ public class NumberUtilTest {
@Test
public void maxTest() {
int max = NumberUtil.max(new int[]{5,4,3,6,1});
int max = NumberUtil.max(5,4,3,6,1);
Assert.assertEquals(6, max);
}
@Test
public void minTest() {
int min = NumberUtil.min(new int[]{5,4,3,6,1});
int min = NumberUtil.min(5,4,3,6,1);
Assert.assertEquals(1, min);
}
@ -215,6 +215,9 @@ public class NumberUtilTest {
Assert.assertEquals(10, v5);
int v6 = NumberUtil.parseInt("22.4D");
Assert.assertEquals(22, v6);
int v7 = NumberUtil.parseInt("0");
Assert.assertEquals(0, v7);
}
@Test

View File

@ -1,17 +1,16 @@
package cn.hutool.core.util;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.xml.xpath.XPathConstants;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapBuilder;
import cn.hutool.core.map.MapUtil;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.w3c.dom.Document;
import cn.hutool.core.map.MapBuilder;
import cn.hutool.core.map.MapUtil;
import javax.xml.xpath.XPathConstants;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* {@link XmlUtil} 工具类
@ -86,6 +85,15 @@ public class XmlUtilTest {
Assert.assertEquals("1", map.get("successCounts"));
}
@Test
public void xmlToMapTest2() {
String xml = "<root><name>张三</name><name>李四</name></root>";
Map<String, Object> map = XmlUtil.xmlToMap(xml);
Assert.assertEquals(1, map.size());
Assert.assertEquals(CollUtil.newArrayList("张三", "李四"), map.get("name"));
}
@Test
public void mapToXmlTest() {
Map<String, Object> map = MapBuilder.create(new LinkedHashMap<String, Object>())//

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-cron</artifactId>

View File

@ -71,7 +71,7 @@ import cn.hutool.cron.pattern.parser.YearValueParser;
* <ul>
* <li><strong>5 * * * *</strong>每个点钟的5分执行00:05,01:05</li>
* <li><strong>* * * * *</strong>每分钟执行</li>
* <li><strong>*&#47;2 * * * *</strong>每两小时执行</li>
* <li><strong>*&#47;2 * * * *</strong>每两分钟执行</li>
* <li><strong>* 12 * * *</strong>12点的每分钟执行</li>
* <li><strong>59 11 * * 1,2</strong>每周一和周二的11:59执行</li>
* <li><strong>3-18&#47;5 * * * *</strong>3~18分每5分钟执行一次即0:03, 0:08, 0:13, 0:18, 1:03, 1:08</li>

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-crypto</artifactId>

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-db</artifactId>

View File

@ -111,10 +111,10 @@ public class SqlUtil {
StringBuilder likeValue = StrUtil.builder(withLikeKeyword ? "LIKE " : "");
switch (likeType) {
case StartWith:
likeValue.append('%').append(value);
likeValue.append(value).append('%');
break;
case EndWith:
likeValue.append(value).append('%');
likeValue.append('%').append(value);
break;
case Contains:
likeValue.append('%').append(value).append('%');

View File

@ -1,15 +1,13 @@
package cn.hutool.db;
import java.sql.SQLException;
import java.util.List;
import cn.hutool.db.sql.Condition;
import cn.hutool.log.StaticLog;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import cn.hutool.core.lang.func.VoidFunc1;
import cn.hutool.db.sql.Condition;
import cn.hutool.log.StaticLog;
import java.sql.SQLException;
import java.util.List;
/**
* Db对象单元测试
@ -29,7 +27,22 @@ public class DbTest {
List<Entity> find = Db.use().find(Entity.create("user").set("age", 18));
Assert.assertEquals("王五", find.get(0).get("name"));
}
@Test
public void findLikeTest() throws SQLException {
// 方式1
List<Entity> find = Db.use().find(Entity.create("user").set("name", "like 王%"));
Assert.assertEquals("王五", find.get(0).get("name"));
// 方式2
find = Db.use().findLike("user", "name", "", Condition.LikeType.StartWith);
Assert.assertEquals("王五", find.get(0).get("name"));
// 方式3
find = Db.use().query("select * from user where name like ?", "王%");
Assert.assertEquals("王五", find.get(0).get("name"));
}
@Test
public void findByTest() throws SQLException {
List<Entity> find = Db.use().findBy("user",
@ -45,14 +58,10 @@ public class DbTest {
@Test
@Ignore
public void txTest() throws SQLException {
Db.use().tx(new VoidFunc1<Db>() {
@Override
public void call(Db db) throws SQLException {
db.insert(Entity.create("user").set("name", "unitTestUser2"));
db.update(Entity.create().set("age", 79), Entity.create("user").set("name", "unitTestUser2"));
db.del("user", "name", "unitTestUser2");
}
Db.use().tx(db -> {
db.insert(Entity.create("user").set("name", "unitTestUser2"));
db.update(Entity.create().set("age", 79), Entity.create("user").set("name", "unitTestUser2"));
db.del("user", "name", "unitTestUser2");
});
}
}

View File

@ -1,12 +1,10 @@
package cn.hutool.db;
import java.sql.SQLException;
import cn.hutool.core.lang.Console;
import org.junit.Ignore;
import org.junit.Test;
import cn.hutool.core.lang.Console;
import cn.hutool.core.lang.func.VoidFunc1;
import java.sql.SQLException;
/**
* MySQL操作单元测试

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-dfa</artifactId>

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-extra</artifactId>

View File

@ -133,13 +133,14 @@ public abstract class AbstractFtp implements Closeable {
}
/**
* 将本地文件上传到目标服务器目标文件名为destPath若destPath为目录则目标文件名将与srcFilePath文件名相同覆盖模式
* 将本地文件上传到目标服务器目标文件名为destPath若destPath为目录则目标文件名将与file文件名相同
* 覆盖模式
*
* @param srcFilePath 本地文件路径
* @param destFile 目标文件
* @param destPath 服务端路径可以为{@code null} 或者相对路径或绝对路径
* @param file 需要上传的文件
* @return 是否成功
*/
public abstract boolean upload(String srcFilePath, File destFile);
public abstract boolean upload(String destPath, File file);
/**
* 下载文件

View File

@ -364,14 +364,14 @@ public class Ftp extends AbstractFtp {
* 3. path为绝对路径则上传到此路径
* </pre>
*
* @param path 服务端路径可以为{@code null} 或者相对路径或绝对路径
* @param destPath 服务端路径可以为{@code null} 或者相对路径或绝对路径
* @param file 文件
* @return 是否上传成功
*/
@Override
public boolean upload(String path, File file) {
public boolean upload(String destPath, File file) {
Assert.notNull(file, "file to upload is null !");
return upload(path, file.getName(), file);
return upload(destPath, file.getName(), file);
}
/**

View File

@ -349,10 +349,10 @@ public class Mail {
/**
* 发送
*
* @return this
* @return message-id
* @throws MailException 邮件发送异常
*/
public Mail send() throws MailException {
public String send() throws MailException {
try {
return doSend();
} catch (MessagingException e) {
@ -365,12 +365,13 @@ public class Mail {
/**
* 执行发送
*
* @return this
* @return message-id
* @throws MessagingException 发送异常
*/
private Mail doSend() throws MessagingException {
Transport.send(buildMsg());
return this;
private String doSend() throws MessagingException {
final MimeMessage mimeMessage = buildMsg();
Transport.send(mimeMessage);
return mimeMessage.getMessageID();
}
/**

View File

@ -14,7 +14,7 @@ import cn.hutool.core.util.StrUtil;
/**
* 邮件工具类基于javax.mail封装
*
*
* @author looly
* @since 3.1.2
*/
@ -23,325 +23,349 @@ public class MailUtil {
* 使用配置文件中设置的账户发送文本邮件发送给单个或多个收件人<br>
* 多个收件人可以使用逗号,分隔也可以通过分号;分隔
*
* @param to 收件人
* @param to 收件人
* @param subject 标题
* @param content 正文
* @param files 附件列表
* @param files 附件列表
* @return message-id
* @since 3.2.0
*/
public static void sendText(String to, String subject, String content, File... files) {
send(to, subject, content, false, files);
public static String sendText(String to, String subject, String content, File... files) {
return send(to, subject, content, false, files);
}
/**
* 使用配置文件中设置的账户发送HTML邮件发送给单个或多个收件人<br>
* 多个收件人可以使用逗号,分隔也可以通过分号;分隔
*
* @param to 收件人
* @param to 收件人
* @param subject 标题
* @param content 正文
* @param files 附件列表
* @param files 附件列表
* @return message-id
* @since 3.2.0
*/
public static void sendHtml(String to, String subject, String content, File... files) {
send(to, subject, content, true, files);
public static String sendHtml(String to, String subject, String content, File... files) {
return send(to, subject, content, true, files);
}
/**
* 使用配置文件中设置的账户发送邮件发送单个或多个收件人<br>
* 多个收件人可以使用逗号,分隔也可以通过分号;分隔
*
* @param to 收件人
* @param to 收件人
* @param subject 标题
* @param content 正文
* @param isHtml 是否为HTML
* @param files 附件列表
* @param isHtml 是否为HTML
* @param files 附件列表
* @return message-id
*/
public static void send(String to, String subject, String content, boolean isHtml, File... files) {
send(splitAddress(to), subject, content, isHtml, files);
public static String send(String to, String subject, String content, boolean isHtml, File... files) {
return send(splitAddress(to), subject, content, isHtml, files);
}
/**
* 使用配置文件中设置的账户发送邮件发送单个或多个收件人<br>
* 多个收件人抄送人密送人可以使用逗号,分隔也可以通过分号;分隔
*
* @param to 收件人可以使用逗号,分隔也可以通过分号;分隔
* @param cc 抄送人可以使用逗号,分隔也可以通过分号;分隔
* @param bcc 密送人可以使用逗号,分隔也可以通过分号;分隔
* @param to 收件人可以使用逗号,分隔也可以通过分号;分隔
* @param cc 抄送人可以使用逗号,分隔也可以通过分号;分隔
* @param bcc 密送人可以使用逗号,分隔也可以通过分号;分隔
* @param subject 标题
* @param content 正文
* @param isHtml 是否为HTML
* @param files 附件列表
* @param isHtml 是否为HTML
* @param files 附件列表
* @return message-id
* @since 4.0.3
*/
public static void send(String to, String cc, String bcc, String subject, String content, boolean isHtml, File... files) {
send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, isHtml, files);
public static String send(String to, String cc, String bcc, String subject, String content, boolean isHtml, File... files) {
return send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, isHtml, files);
}
/**
* 使用配置文件中设置的账户发送文本邮件发送给多人
*
* @param tos 收件人列表
* @param tos 收件人列表
* @param subject 标题
* @param content 正文
* @param files 附件列表
* @param files 附件列表
* @return message-id
*/
public static void sendText(Collection<String> tos, String subject, String content, File... files) {
send(tos, subject, content, false, files);
public static String sendText(Collection<String> tos, String subject, String content, File... files) {
return send(tos, subject, content, false, files);
}
/**
* 使用配置文件中设置的账户发送HTML邮件发送给多人
*
* @param tos 收件人列表
* @param tos 收件人列表
* @param subject 标题
* @param content 正文
* @param files 附件列表
* @param files 附件列表
* @return message-id
* @since 3.2.0
*/
public static void sendHtml(Collection<String> tos, String subject, String content, File... files) {
send(tos, subject, content, true, files);
public static String sendHtml(Collection<String> tos, String subject, String content, File... files) {
return send(tos, subject, content, true, files);
}
/**
* 使用配置文件中设置的账户发送邮件发送给多人
*
* @param tos 收件人列表
* @param tos 收件人列表
* @param subject 标题
* @param content 正文
* @param isHtml 是否为HTML
* @param files 附件列表
* @param isHtml 是否为HTML
* @param files 附件列表
* @return message-id
*/
public static void send(Collection<String> tos, String subject, String content, boolean isHtml, File... files) {
send(tos, null, null, subject, content, isHtml, files);
public static String send(Collection<String> tos, String subject, String content, boolean isHtml, File... files) {
return send(tos, null, null, subject, content, isHtml, files);
}
/**
* 使用配置文件中设置的账户发送邮件发送给多人
*
* @param tos 收件人列表
* @param ccs 抄送人列表可以为null或空
* @param bccs 密送人列表可以为null或空
* @param tos 收件人列表
* @param ccs 抄送人列表可以为null或空
* @param bccs 密送人列表可以为null或空
* @param subject 标题
* @param content 正文
* @param isHtml 是否为HTML
* @param files 附件列表
* @param isHtml 是否为HTML
* @param files 附件列表
* @return message-id
* @since 4.0.3
*/
public static void send(Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, boolean isHtml, File... files) {
send(GlobalMailAccount.INSTANCE.getAccount(), true, tos, ccs, bccs, subject, content, null, isHtml, files);
public static String send(Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, boolean isHtml, File... files) {
return send(GlobalMailAccount.INSTANCE.getAccount(), true, tos, ccs, bccs, subject, content, null, isHtml, files);
}
// ------------------------------------------------------------------------------------------------------------------------------- Custom MailAccount
/**
* 发送邮件给多人
*
* @param mailAccount 邮件认证对象
* @param to 收件人多个收件人逗号或者分号隔开
* @param subject 标题
* @param content 正文
* @param isHtml 是否为HTML格式
* @param files 附件列表
* @param to 收件人多个收件人逗号或者分号隔开
* @param subject 标题
* @param content 正文
* @param isHtml 是否为HTML格式
* @param files 附件列表
* @return message-id
* @since 3.2.0
*/
public static void send(MailAccount mailAccount, String to, String subject, String content, boolean isHtml, File... files) {
send(mailAccount, splitAddress(to), subject, content, isHtml, files);
public static String send(MailAccount mailAccount, String to, String subject, String content, boolean isHtml, File... files) {
return send(mailAccount, splitAddress(to), subject, content, isHtml, files);
}
/**
* 发送邮件给多人
*
* @param mailAccount 邮件帐户信息
* @param tos 收件人列表
* @param subject 标题
* @param content 正文
* @param isHtml 是否为HTML格式
* @param files 附件列表
* @param tos 收件人列表
* @param subject 标题
* @param content 正文
* @param isHtml 是否为HTML格式
* @param files 附件列表
* @return message-id
*/
public static void send(MailAccount mailAccount, Collection<String> tos, String subject, String content, boolean isHtml, File... files) {
send(mailAccount, tos, null, null, subject, content, isHtml, files);
public static String send(MailAccount mailAccount, Collection<String> tos, String subject, String content, boolean isHtml, File... files) {
return send(mailAccount, tos, null, null, subject, content, isHtml, files);
}
/**
* 发送邮件给多人
*
* @param mailAccount 邮件帐户信息
* @param tos 收件人列表
* @param ccs 抄送人列表可以为null或空
* @param bccs 密送人列表可以为null或空
* @param subject 标题
* @param content 正文
* @param isHtml 是否为HTML格式
* @param files 附件列表
* @param tos 收件人列表
* @param ccs 抄送人列表可以为null或空
* @param bccs 密送人列表可以为null或空
* @param subject 标题
* @param content 正文
* @param isHtml 是否为HTML格式
* @param files 附件列表
* @return message-id
* @since 4.0.3
*/
public static void send(MailAccount mailAccount, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, boolean isHtml, File... files) {
send(mailAccount, false, tos, ccs, bccs, subject, content, null, isHtml, files);
public static String send(MailAccount mailAccount, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, boolean isHtml, File... files) {
return send(mailAccount, false, tos, ccs, bccs, subject, content, null, isHtml, files);
}
/**
* 使用配置文件中设置的账户发送HTML邮件发送给单个或多个收件人<br>
* 多个收件人可以使用逗号,分隔也可以通过分号;分隔
*
* @param to 收件人
* @param subject 标题
* @param content 正文
* @param files 附件列表
*
* @param to 收件人
* @param subject 标题
* @param content 正文
* @param imageMap 图片与占位符占位符格式为cid:$IMAGE_PLACEHOLDER
* @param files 附件列表
* @return message-id
* @since 3.2.0
*/
public static void sendHtml(String to, String subject, String content, Map<String, InputStream> imageMap, File... files) {
send(to, subject, content, imageMap, true, files);
public static String sendHtml(String to, String subject, String content, Map<String, InputStream> imageMap, File... files) {
return send(to, subject, content, imageMap, true, files);
}
/**
* 使用配置文件中设置的账户发送邮件发送单个或多个收件人<br>
* 多个收件人可以使用逗号,分隔也可以通过分号;分隔
*
* @param to 收件人
* @param subject 标题
* @param content 正文
*
* @param to 收件人
* @param subject 标题
* @param content 正文
* @param imageMap 图片与占位符占位符格式为cid:$IMAGE_PLACEHOLDER
* @param isHtml 是否为HTML
* @param files 附件列表
* @param isHtml 是否为HTML
* @param files 附件列表
* @return message-id
*/
public static void send(String to, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
send(splitAddress(to), subject, content, imageMap, isHtml, files);
public static String send(String to, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
return send(splitAddress(to), subject, content, imageMap, isHtml, files);
}
/**
* 使用配置文件中设置的账户发送邮件发送单个或多个收件人<br>
* 多个收件人抄送人密送人可以使用逗号,分隔也可以通过分号;分隔
*
* @param to 收件人可以使用逗号,分隔也可以通过分号;分隔
* @param cc 抄送人可以使用逗号,分隔也可以通过分号;分隔
* @param bcc 密送人可以使用逗号,分隔也可以通过分号;分隔
* @param subject 标题
* @param content 正文
*
* @param to 收件人可以使用逗号,分隔也可以通过分号;分隔
* @param cc 抄送人可以使用逗号,分隔也可以通过分号;分隔
* @param bcc 密送人可以使用逗号,分隔也可以通过分号;分隔
* @param subject 标题
* @param content 正文
* @param imageMap 图片与占位符占位符格式为cid:$IMAGE_PLACEHOLDER
* @param isHtml 是否为HTML
* @param files 附件列表
* @param isHtml 是否为HTML
* @param files 附件列表
* @return message-id
* @since 4.0.3
*/
public static void send(String to, String cc, String bcc, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, imageMap, isHtml, files);
public static String send(String to, String cc, String bcc, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
return send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, imageMap, isHtml, files);
}
/**
* 使用配置文件中设置的账户发送HTML邮件发送给多人
*
* @param tos 收件人列表
* @param subject 标题
* @param content 正文
*
* @param tos 收件人列表
* @param subject 标题
* @param content 正文
* @param imageMap 图片与占位符占位符格式为cid:$IMAGE_PLACEHOLDER
* @param files 附件列表
* @param files 附件列表
* @return message-id
* @since 3.2.0
*/
public static void sendHtml(Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, File... files) {
send(tos, subject, content, imageMap, true, files);
public static String sendHtml(Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, File... files) {
return send(tos, subject, content, imageMap, true, files);
}
/**
* 使用配置文件中设置的账户发送邮件发送给多人
*
* @param tos 收件人列表
* @param subject 标题
* @param content 正文
*
* @param tos 收件人列表
* @param subject 标题
* @param content 正文
* @param imageMap 图片与占位符占位符格式为cid:$IMAGE_PLACEHOLDER
* @param isHtml 是否为HTML
* @param files 附件列表
* @param isHtml 是否为HTML
* @param files 附件列表
* @return message-id
*/
public static void send(Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
send(tos, null, null, subject, content, imageMap, isHtml, files);
public static String send(Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
return send(tos, null, null, subject, content, imageMap, isHtml, files);
}
/**
* 使用配置文件中设置的账户发送邮件发送给多人
*
* @param tos 收件人列表
* @param ccs 抄送人列表可以为null或空
* @param bccs 密送人列表可以为null或空
* @param subject 标题
* @param content 正文
*
* @param tos 收件人列表
* @param ccs 抄送人列表可以为null或空
* @param bccs 密送人列表可以为null或空
* @param subject 标题
* @param content 正文
* @param imageMap 图片与占位符占位符格式为cid:$IMAGE_PLACEHOLDER
* @param isHtml 是否为HTML
* @param files 附件列表
* @param isHtml 是否为HTML
* @param files 附件列表
* @return message-id
* @since 4.0.3
*/
public static void send(Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
send(GlobalMailAccount.INSTANCE.getAccount(), true, tos, ccs, bccs, subject, content, imageMap, isHtml, files);
public static String send(Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
return send(GlobalMailAccount.INSTANCE.getAccount(), true, tos, ccs, bccs, subject, content, imageMap, isHtml, files);
}
// ------------------------------------------------------------------------------------------------------------------------------- Custom MailAccount
/**
* 发送邮件给多人
*
*
* @param mailAccount 邮件认证对象
* @param to 收件人多个收件人逗号或者分号隔开
* @param subject 标题
* @param content 正文
* @param imageMap 图片与占位符占位符格式为cid:$IMAGE_PLACEHOLDER
* @param isHtml 是否为HTML格式
* @param files 附件列表
* @param to 收件人多个收件人逗号或者分号隔开
* @param subject 标题
* @param content 正文
* @param imageMap 图片与占位符占位符格式为cid:$IMAGE_PLACEHOLDER
* @param isHtml 是否为HTML格式
* @param files 附件列表
* @return message-id
* @since 3.2.0
*/
public static void send(MailAccount mailAccount, String to, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
send(mailAccount, splitAddress(to), subject, content, imageMap, isHtml, files);
public static String send(MailAccount mailAccount, String to, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
return send(mailAccount, splitAddress(to), subject, content, imageMap, isHtml, files);
}
/**
* 发送邮件给多人
*
*
* @param mailAccount 邮件帐户信息
* @param tos 收件人列表
* @param subject 标题
* @param content 正文
* @param imageMap 图片与占位符占位符格式为cid:$IMAGE_PLACEHOLDER
* @param isHtml 是否为HTML格式
* @param files 附件列表
* @param tos 收件人列表
* @param subject 标题
* @param content 正文
* @param imageMap 图片与占位符占位符格式为cid:$IMAGE_PLACEHOLDER
* @param isHtml 是否为HTML格式
* @param files 附件列表
* @return message-id
* @since 4.6.3
*/
public static void send(MailAccount mailAccount, Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
send(mailAccount, tos, null, null, subject, content, imageMap, isHtml, files);
public static String send(MailAccount mailAccount, Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
return send(mailAccount, tos, null, null, subject, content, imageMap, isHtml, files);
}
/**
* 发送邮件给多人
*
*
* @param mailAccount 邮件帐户信息
* @param tos 收件人列表
* @param ccs 抄送人列表可以为null或空
* @param bccs 密送人列表可以为null或空
* @param subject 标题
* @param content 正文
* @param imageMap 图片与占位符占位符格式为cid:$IMAGE_PLACEHOLDER
* @param isHtml 是否为HTML格式
* @param files 附件列表
* @param tos 收件人列表
* @param ccs 抄送人列表可以为null或空
* @param bccs 密送人列表可以为null或空
* @param subject 标题
* @param content 正文
* @param imageMap 图片与占位符占位符格式为cid:$IMAGE_PLACEHOLDER
* @param isHtml 是否为HTML格式
* @param files 附件列表
* @return message-id
* @since 4.6.3
*/
public static void send(MailAccount mailAccount, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, Map<String, InputStream> imageMap,
boolean isHtml, File... files) {
send(mailAccount, false, tos, ccs, bccs, subject, content, imageMap, isHtml, files);
public static String send(MailAccount mailAccount, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, Map<String, InputStream> imageMap,
boolean isHtml, File... files) {
return send(mailAccount, false, tos, ccs, bccs, subject, content, imageMap, isHtml, files);
}
// ------------------------------------------------------------------------------------------------------------------------ Private method start
/**
* 发送邮件给多人
*
* @param mailAccount 邮件帐户信息
*
* @param mailAccount 邮件帐户信息
* @param useGlobalSession 是否全局共享Session
* @param tos 收件人列表
* @param ccs 抄送人列表可以为null或空
* @param bccs 密送人列表可以为null或空
* @param subject 标题
* @param content 正文
* @param imageMap 图片与占位符占位符格式为cid:${cid}
* @param isHtml 是否为HTML格式
* @param files 附件列表
* @param tos 收件人列表
* @param ccs 抄送人列表可以为null或空
* @param bccs 密送人列表可以为null或空
* @param subject 标题
* @param content 正文
* @param imageMap 图片与占位符占位符格式为cid:${cid}
* @param isHtml 是否为HTML格式
* @param files 附件列表
* @return message-id
* @since 4.6.3
*/
private static void send(MailAccount mailAccount, boolean useGlobalSession, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content,
Map<String, InputStream> imageMap, boolean isHtml, File... files) {
private static String send(MailAccount mailAccount, boolean useGlobalSession, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content,
Map<String, InputStream> imageMap, boolean isHtml, File... files) {
final Mail mail = Mail.create(mailAccount).setUseGlobalSession(useGlobalSession);
// 可选抄送人
@ -358,9 +382,9 @@ public class MailUtil {
mail.setContent(content);
mail.setHtml(isHtml);
mail.setFiles(files);
// 图片
if(MapUtil.isNotEmpty(imageMap)) {
if (MapUtil.isNotEmpty(imageMap)) {
for (Entry<String, InputStream> entry : imageMap.entrySet()) {
mail.addImage(entry.getKey(), entry.getValue());
// 关闭流
@ -368,12 +392,12 @@ public class MailUtil {
}
}
mail.send();
return mail.send();
}
/**
* 将多个联系人转为列表分隔符为逗号或者分号
*
*
* @param addresses 多个联系人如果为空返回null
* @return 联系人列表
*/

View File

@ -238,9 +238,6 @@ public class JschUtil {
*/
public static int openAndBindPortToLocal(Connector sshConn, String remoteHost, int remotePort) throws JschRuntimeException {
final Session session = openSession(sshConn.getHost(), sshConn.getPort(), sshConn.getUser(), sshConn.getPassword());
if (session == null) {
throw new JschRuntimeException("Error to create SSH Session");
}
final int localPort = generateLocalPort();
bindPort(session, remoteHost, remotePort, localPort);
return localPort;
@ -359,13 +356,13 @@ public class JschUtil {
if (null == charset) {
charset = CharsetUtil.CHARSET_UTF_8;
}
ChannelExec channel = (ChannelExec) openChannel(session, ChannelType.EXEC);
final ChannelExec channel = (ChannelExec) createChannel(session, ChannelType.EXEC);
channel.setCommand(StrUtil.bytes(cmd, charset));
channel.setInputStream(null);
channel.setErrStream(errStream);
InputStream in = null;
try {
channel.start();
channel.connect();
in = channel.getInputStream();
return IoUtil.read(in, CharsetUtil.CHARSET_UTF_8);
} catch (IOException e) {

View File

@ -1,12 +1,9 @@
package cn.hutool.extra.ssh;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Filter;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ftp.AbstractFtp;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.ChannelSftp.LsEntrySelector;
@ -14,10 +11,11 @@ import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.SftpProgressMonitor;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Filter;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ftp.AbstractFtp;
import java.io.File;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
/**
* SFTP是Secure File Transfer Protocol的缩写安全文件传送协议可以为传输文件提供一种安全的加密方法<br>
@ -336,8 +334,8 @@ public class Sftp extends AbstractFtp {
}
@Override
public boolean upload(String srcFilePath, File destFile) {
put(srcFilePath, FileUtil.getAbsolutePath(destFile));
public boolean upload(String destPath, File file) {
put(FileUtil.getAbsolutePath(file), destPath);
return true;
}

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-http</artifactId>

View File

@ -42,27 +42,4 @@ public class SoapClientTest {
SOAPMessage message = client.sendForMessage();
Console.log(message.getSOAPBody().getTextContent());
}
@Test
public void test(){
final SoapClient soapClient = SoapClient.create("http://117.132.161.47:6403/services/JybgService")
.setMethod("ser:zzjRequest", "http://service.jfsoft.com/")
.setParam("arg0", "<![CDATA[\n" +
"<Request>\n" +
"<CardType>3</CardType>\n" +
"<CardNo>C00002347</CardNo>\n" +
"<BeginDate>20191101</BeginDate>\n" +
"<EndDate>20191115</EndDate>\n" +
"<TerminalNo>JKGCOnline000001</TerminalNo>\n" +
"<BusinessCode>GetLisReport</BusinessCode>\n" +
"<OperName>自助机01</OperName>\n" +
"<OperCode>zzj01</OperCode>\n" +
"<OperTime>20191116153748</OperTime>\n" +
"</Request>\n" +
"]]>", false);
final String send = soapClient.send();
Console.log(HtmlUtil.unescape(send));
}
}

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-json</artifactId>

View File

@ -2,6 +2,7 @@ package cn.hutool.json;
import java.io.IOException;
import java.io.Writer;
import java.time.temporal.TemporalAccessor;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
@ -43,12 +44,12 @@ final class InternalJSONUtil {
} else if (value instanceof JSON) {
((JSON) value).write(writer, indentFactor, indent);
} else if (value instanceof Map) {
new JSONObject((Map<?, ?>) value).write(writer, indentFactor, indent);
new JSONObject(value).write(writer, indentFactor, indent);
} else if (value instanceof Iterable || value instanceof Iterator || value.getClass().isArray()) {
new JSONArray(value).write(writer, indentFactor, indent);
} else if (value instanceof Number) {
writer.write(NumberUtil.toStr((Number) value));
} else if (value instanceof Date || value instanceof Calendar) {
} else if (value instanceof Date || value instanceof Calendar || value instanceof TemporalAccessor) {
final String format = (null == config) ? null : config.getDateFormat();
writer.write(formatDate(value, format));
} else if (value instanceof Boolean) {
@ -138,7 +139,6 @@ final class InternalJSONUtil {
* @return A simple JSON value.
*/
protected static Object stringToValue(String string) {
Double d;
if (null == string || "null".equalsIgnoreCase(string)) {
return JSONNull.NULL;
}
@ -158,8 +158,8 @@ final class InternalJSONUtil {
if ((b >= '0' && b <= '9') || b == '-') {
try {
if (string.indexOf('.') > -1 || string.indexOf('e') > -1 || string.indexOf('E') > -1) {
d = Double.valueOf(string);
if (!d.isInfinite() && !d.isNaN()) {
double d = Double.parseDouble(string);
if (false == Double.isInfinite(d) && false == Double.isNaN(d)) {
return d;
}
} else {
@ -228,12 +228,21 @@ final class InternalJSONUtil {
*/
private static String formatDate(Object dateObj, String format) {
if (StrUtil.isNotBlank(format)) {
final Date date = (dateObj instanceof Date) ? (Date) dateObj : ((Calendar) dateObj).getTime();
//用户定义了日期格式
return JSONUtil.quote(DateUtil.format(date, format));
return JSONUtil.quote(DateUtil.format(Convert.toDate(dateObj), format));
}
//默认使用时间戳
return String.valueOf((dateObj instanceof Date) ? ((Date) dateObj).getTime() : ((Calendar) dateObj).getTimeInMillis());
long timeMillis;
if(dateObj instanceof TemporalAccessor){
timeMillis = DateUtil.toInstant((TemporalAccessor)dateObj).toEpochMilli();
} else if(dateObj instanceof Date){
timeMillis = ((Date) dateObj).getTime();
} else if(dateObj instanceof Calendar){
timeMillis = ((Calendar) dateObj).getTimeInMillis();
} else{
throw new UnsupportedOperationException("Unsupported Date type: " + dateObj.getClass());
}
return String.valueOf(timeMillis);
}
}

View File

@ -19,6 +19,8 @@ import java.util.List;
import java.util.ListIterator;
import java.util.RandomAccess;
import static cn.hutool.json.JSONConverter.*;
/**
* JSON数组<br>
* JSON数组是表示中括号括住的数据表现形式<br>
@ -30,7 +32,7 @@ import java.util.RandomAccess;
*
* @author looly
*/
public class JSONArray extends JSONGetter<Integer> implements JSON, List<Object>, RandomAccess {
public class JSONArray implements JSON, JSONGetter<Integer>, List<Object>, RandomAccess {
private static final long serialVersionUID = 2664900568717612292L;
/** 默认初始大小 */
@ -236,7 +238,7 @@ public class JSONArray extends JSONGetter<Integer> implements JSON, List<Object>
@Override
public <T> T getByPath(String expression, Class<T> resultType) {
return JSONConverter.jsonConvert(resultType, getByPath(expression), true);
return jsonConvert(resultType, getByPath(expression), true);
}
@Override
@ -314,6 +316,7 @@ public class JSONArray extends JSONGetter<Integer> implements JSON, List<Object>
}
}
@SuppressWarnings("NullableProblems")
@Override
public Iterator<Object> iterator() {
return rawList.iterator();
@ -344,13 +347,14 @@ public class JSONArray extends JSONGetter<Integer> implements JSON, List<Object>
return rawList.contains(o);
}
@SuppressWarnings("NullableProblems")
@Override
public Object[] toArray() {
return rawList.toArray();
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings({"unchecked", "NullableProblems"})
public <T> T[] toArray(T[] a) {
return (T[]) JSONConverter.toArray(this, a.getClass().getComponentType());
}
@ -370,11 +374,13 @@ public class JSONArray extends JSONGetter<Integer> implements JSON, List<Object>
return rawList.remove(o);
}
@SuppressWarnings("NullableProblems")
@Override
public boolean containsAll(Collection<?> c) {
return rawList.containsAll(c);
}
@SuppressWarnings("NullableProblems")
@Override
public boolean addAll(Collection<?> c) {
if (CollUtil.isEmpty(c)) {
@ -386,6 +392,7 @@ public class JSONArray extends JSONGetter<Integer> implements JSON, List<Object>
return true;
}
@SuppressWarnings("NullableProblems")
@Override
public boolean addAll(int index, Collection<?> c) {
if (CollUtil.isEmpty(c)) {
@ -398,11 +405,13 @@ public class JSONArray extends JSONGetter<Integer> implements JSON, List<Object>
return rawList.addAll(index, list);
}
@SuppressWarnings("NullableProblems")
@Override
public boolean removeAll(Collection<?> c) {
return this.rawList.removeAll(c);
}
@SuppressWarnings("NullableProblems")
@Override
public boolean retainAll(Collection<?> c) {
return this.rawList.retainAll(c);
@ -446,16 +455,19 @@ public class JSONArray extends JSONGetter<Integer> implements JSON, List<Object>
return this.rawList.lastIndexOf(o);
}
@SuppressWarnings("NullableProblems")
@Override
public ListIterator<Object> listIterator() {
return this.rawList.listIterator();
}
@SuppressWarnings("NullableProblems")
@Override
public ListIterator<Object> listIterator(int index) {
return this.rawList.listIterator(index);
}
@SuppressWarnings("NullableProblems")
@Override
public List<Object> subList(int fromIndex, int toIndex) {
return this.rawList.subList(fromIndex, toIndex);

View File

@ -9,7 +9,7 @@ import cn.hutool.core.getter.OptNullBasicTypeFromObjectGetter;
*
* @param <K> Key类型
*/
public abstract class JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K>{
public interface JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K>{
/**
* key对应值是否为<code>null</code>或无此key
@ -17,7 +17,7 @@ public abstract class JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K>{
* @param key
* @return true 无此key或值为<code>null</code>{@link JSONNull#NULL}返回<code>false</code>其它返回<code>true</code>
*/
public boolean isNull(K key) {
default boolean isNull(K key) {
return JSONNull.NULL.equals(this.getObj(key));
}
@ -28,7 +28,7 @@ public abstract class JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K>{
* @return 字符串类型值
* @since 4.2.2
*/
public String getStrEscaped(K key) {
default String getStrEscaped(K key) {
return getStrEscaped(key, null);
}
@ -40,7 +40,7 @@ public abstract class JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K>{
* @return 字符串类型值
* @since 4.2.2
*/
public String getStrEscaped(K key, String defaultValue) {
default String getStrEscaped(K key, String defaultValue) {
return JSONUtil.escape(getStr(key, defaultValue));
}
@ -51,7 +51,7 @@ public abstract class JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K>{
* @param key KEY
* @return JSONArray对象如果值为null或者非JSONArray类型返回null
*/
public JSONArray getJSONArray(K key) {
default JSONArray getJSONArray(K key) {
final Object object = this.getObj(key);
if(null == object) {
return null;
@ -70,7 +70,7 @@ public abstract class JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K>{
* @param key KEY
* @return JSONArray对象如果值为null或者非JSONObject类型返回null
*/
public JSONObject getJSONObject(K key) {
default JSONObject getJSONObject(K key) {
final Object object = this.getObj(key);
if(null == object) {
return null;
@ -92,7 +92,7 @@ public abstract class JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K>{
* @return Bean对象如果值为null或者非JSONObject类型返回null
* @since 3.1.1
*/
public <T> T getBean(K key, Class<T> beanType) {
default <T> T getBean(K key, Class<T> beanType) {
final JSONObject obj = getJSONObject(key);
return (null == obj) ? null : obj.toBean(beanType);
}
@ -108,7 +108,7 @@ public abstract class JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K>{
* @throws ConvertException 转换异常
* @since 3.0.8
*/
public <T> T get(K key, Class<T> type) throws ConvertException{
default <T> T get(K key, Class<T> type) throws ConvertException{
return get(key, type, false);
}
@ -123,7 +123,7 @@ public abstract class JSONGetter<K> extends OptNullBasicTypeFromObjectGetter<K>{
* @throws ConvertException 转换异常
* @since 3.0.8
*/
public <T> T get(K key, Class<T> type, boolean ignoreError) throws ConvertException{
default <T> T get(K key, Class<T> type, boolean ignoreError) throws ConvertException{
final Object value = this.getObj(key);
if(null == value){
return null;

View File

@ -37,7 +37,7 @@ import java.util.Set;
*
* @author looly
*/
public class JSONObject extends JSONGetter<String> implements JSON, Map<String, Object> {
public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object> {
private static final long serialVersionUID = -330220388580734346L;
/** 默认初始大小 */
@ -163,7 +163,7 @@ public class JSONObject extends JSONGetter<String> implements JSON, Map<String,
*/
public JSONObject(Object source, boolean ignoreNullValue, boolean isOrder) {
this(source, JSONConfig.create().setOrder(isOrder)//
.setIgnoreCase((source instanceof CaseInsensitiveMap) || (source instanceof CaseInsensitiveLinkedMap))//
.setIgnoreCase((source instanceof CaseInsensitiveMap))//
.setIgnoreNullValue(ignoreNullValue));
}
@ -478,16 +478,19 @@ public class JSONObject extends JSONGetter<String> implements JSON, Map<String,
rawHashMap.clear();
}
@SuppressWarnings("NullableProblems")
@Override
public Set<String> keySet() {
return this.rawHashMap.keySet();
}
@SuppressWarnings("NullableProblems")
@Override
public Collection<Object> values() {
return rawHashMap.values();
}
@SuppressWarnings("NullableProblems")
@Override
public Set<Entry<String, Object>> entrySet() {
return rawHashMap.entrySet();
@ -643,7 +646,7 @@ public class JSONObject extends JSONGetter<String> implements JSON, Map<String,
*
* @param source JavaBean或者Map对象或者String
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@SuppressWarnings({"rawtypes", "unchecked", "StatementWithEmptyBody"})
private void init(Object source) {
if (null == source) {
return;

View File

@ -6,6 +6,8 @@ import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAccessor;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
@ -650,7 +652,10 @@ public final class JSONUtil {
}
// 日期类型原样保存便于格式化
if (object instanceof Date || object instanceof Calendar) {
if (object instanceof Date
|| object instanceof Calendar
|| object instanceof TemporalAccessor
) {
return object;
}
// 枚举类保存其字符串形式4.0.2新增

View File

@ -0,0 +1,32 @@
package cn.hutool.json;
import lombok.Data;
import org.junit.Assert;
import org.junit.Test;
import java.time.LocalDateTime;
/**
* 问题反馈对象中有JDK8日期对象时转换失败5.0.7修复
*/
public class Isse644Test {
@Test
public void toBeanTest(){
final BeanWithDate beanWithDate = new BeanWithDate();
beanWithDate.setDate(LocalDateTime.now());
final JSONObject jsonObject = JSONUtil.parseObj(beanWithDate);
BeanWithDate beanWithDate2 = JSONUtil.toBean(jsonObject, BeanWithDate.class);
Assert.assertEquals(beanWithDate.getDate(), beanWithDate2.getDate());
beanWithDate2 = JSONUtil.toBean(jsonObject.toString(), BeanWithDate.class);
Assert.assertEquals(beanWithDate.getDate(), beanWithDate2.getDate());
}
@Data
static class BeanWithDate{
private LocalDateTime date;
}
}

View File

@ -3,6 +3,7 @@ package cn.hutool.json;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import org.junit.Assert;
import org.junit.Ignore;
@ -58,8 +59,8 @@ public class JSONObjectTest {
*/
@Test
public void toStringTest3() {
JSONObject json = JSONUtil.createObj()//
.put("dateTime", DateUtil.parse("2019-05-02 22:12:01"))//
JSONObject json = Objects.requireNonNull(JSONUtil.createObj()//
.put("dateTime", DateUtil.parse("2019-05-02 22:12:01")))//
.setDateFormat(DatePattern.NORM_DATE_PATTERN);
Assert.assertEquals("{\"dateTime\":\"2019-05-02\"}", json.toString());
}
@ -67,9 +68,10 @@ public class JSONObjectTest {
@Test
public void toStringWithDateTest() {
JSONObject json = JSONUtil.createObj().put("date", DateUtil.parse("2019-05-08 19:18:21"));
assert json != null;
Assert.assertEquals("{\"date\":1557314301000}", json.toString());
json = JSONUtil.createObj().put("date", DateUtil.parse("2019-05-08 19:18:21")).setDateFormat(DatePattern.NORM_DATE_PATTERN);
json = Objects.requireNonNull(JSONUtil.createObj().put("date", DateUtil.parse("2019-05-08 19:18:21"))).setDateFormat(DatePattern.NORM_DATE_PATTERN);
Assert.assertEquals("{\"date\":\"2019-05-08\"}", json.toString());
}
@ -131,6 +133,7 @@ public class JSONObjectTest {
Console.log(json2);
}
@SuppressWarnings("ConstantConditions")
@Test
public void toBeanTest() {
JSONObject subJson = JSONUtil.createObj().put("value1", "strValue1").put("value2", "234");
@ -149,6 +152,7 @@ public class JSONObjectTest {
Assert.assertEquals(TestEnum.TYPE_A, bean.getTestEnum());
}
@SuppressWarnings("ConstantConditions")
@Test
public void toBeanNullStrTest() {
JSONObject json = JSONUtil.createObj()//
@ -217,6 +221,7 @@ public class JSONObjectTest {
/**
* 在JSON转Bean过程中Bean中字段如果为父类定义的泛型类型则应正确转换此方法用于测试这类情况
*/
@SuppressWarnings("ConstantConditions")
@Test
public void toBeanTest6() {
JSONObject json = JSONUtil.createObj().put("targetUrl", "http://test.com").put("success", "true").put("result", JSONUtil.createObj().put("token", "tokenTest").put("userId", "测试用户1"));
@ -271,6 +276,7 @@ public class JSONObjectTest {
Assert.assertEquals(bean.toString(), bean2.toString());
}
@SuppressWarnings("ConstantConditions")
@Test
public void parseBeanTest3() {
JSONObject json = JSONUtil.createObj().put("code", 22).put("data", "{\"jobId\": \"abc\", \"videoUrl\": \"http://a.com/a.mp4\"}");
@ -310,6 +316,7 @@ public class JSONObjectTest {
Assert.assertEquals(DateUtil.parse("2018-10-25"), bean.getDate());
}
@SuppressWarnings("ConstantConditions")
@Test
public void beanTransTest3() {
JSONObject userAJson = JSONUtil.createObj().put("a", "AValue").put("name", "nameValue").put("date", "08:00:00");

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-log</artifactId>

View File

@ -8,7 +8,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-poi</artifactId>

View File

@ -153,20 +153,53 @@ public class CellUtil {
}
}
if (value instanceof Date) {
if (null != styleSet && null != styleSet.getCellStyleForDate()) {
cell.setCellStyle(styleSet.getCellStyleForDate());
}
} else if (value instanceof TemporalAccessor) {
if (null != styleSet && null != styleSet.getCellStyleForDate()) {
cell.setCellStyle(styleSet.getCellStyleForDate());
}
} else if (value instanceof Calendar) {
if (null != styleSet && null != styleSet.getCellStyleForDate()) {
cell.setCellStyle(styleSet.getCellStyleForDate());
}
} else if (value instanceof Number) {
if ((value instanceof Double || value instanceof Float || value instanceof BigDecimal) && null != styleSet && null != styleSet.getCellStyleForNumber()) {
cell.setCellStyle(styleSet.getCellStyleForNumber());
}
}
setCellValue(cell, value, null);
}
/**
* 设置单元格值<br>
* 根据传入的styleSet自动匹配样式<br>
* 当为头部样式时默认赋值头部样式但是头部中如果有数字日期等类型将按照数字日期样式设置
*
* @param cell 单元格
* @param value
* @param style 自定义样式null表示无样式
*/
public static void setCellValue(Cell cell, Object value, CellStyle style) {
if (null == cell) {
return;
}
if (null != style) {
cell.setCellStyle(style);
}
if (null == value) {
cell.setCellValue(StrUtil.EMPTY);
} else if (value instanceof FormulaCellValue) {
// 公式
cell.setCellFormula(((FormulaCellValue) value).getValue());
} else if (value instanceof Date) {
if (null != styleSet && null != styleSet.getCellStyleForDate()) {
cell.setCellStyle(styleSet.getCellStyleForDate());
}
cell.setCellValue((Date) value);
} else if (value instanceof TemporalAccessor) {
if (null != styleSet && null != styleSet.getCellStyleForDate()) {
cell.setCellStyle(styleSet.getCellStyleForDate());
}
if (value instanceof Instant) {
cell.setCellValue(Date.from((Instant) value));
} else if (value instanceof LocalDateTime) {
@ -175,18 +208,12 @@ public class CellUtil {
cell.setCellValue((LocalDate) value);
}
} else if (value instanceof Calendar) {
if (null != styleSet && null != styleSet.getCellStyleForDate()) {
cell.setCellStyle(styleSet.getCellStyleForDate());
}
cell.setCellValue((Calendar) value);
} else if (value instanceof Boolean) {
cell.setCellValue((Boolean) value);
} else if (value instanceof RichTextString) {
cell.setCellValue((RichTextString) value);
} else if (value instanceof Number) {
if ((value instanceof Double || value instanceof Float || value instanceof BigDecimal) && null != styleSet && null != styleSet.getCellStyleForNumber()) {
cell.setCellStyle(styleSet.getCellStyleForNumber());
}
cell.setCellValue(((Number) value).doubleValue());
} else {
cell.setCellValue(value.toString());

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-script</artifactId>

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-setting</artifactId>

View File

@ -18,7 +18,7 @@ import cn.hutool.log.LogFactory;
*
* @author Looly
*/
public abstract class AbsSetting extends OptNullBasicTypeFromStringGetter<String> implements Serializable {
public abstract class AbsSetting implements OptNullBasicTypeFromStringGetter<String>, Serializable {
private static final long serialVersionUID = 6200156302595905863L;
private final static Log log = LogFactory.get();
@ -268,6 +268,7 @@ public abstract class AbsSetting extends OptNullBasicTypeFromStringGetter<String
* 将setting中的键值关系映射到对象中原理是调用对象对应的set方法<br>
* 只支持基本类型的转换
*
* @param <T> Bean类型
* @param group 分组
* @param bean Bean对象
* @return Bean
@ -291,6 +292,7 @@ public abstract class AbsSetting extends OptNullBasicTypeFromStringGetter<String
* 将setting中的键值关系映射到对象中原理是调用对象对应的set方法<br>
* 只支持基本类型的转换
*
* @param <T> Bean类型
* @param group 分组
* @param beanClass Bean类型
* @return Bean

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-socket</artifactId>

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
</parent>
<artifactId>hutool-system</artifactId>

View File

@ -23,8 +23,8 @@ public class RuntimeInfo implements Serializable{
}
/**
* 获得JVM最大可用内存
* @return 最大可用内存
* 获得JVM最大内存
* @return 最大内存
*/
public final long getMaxMemory(){
return currentRuntime.maxMemory();

View File

@ -8,7 +8,7 @@
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.0.6</version>
<version>5.0.7</version>
<name>hutool</name>
<description>提供丰富的Java工具方法</description>
<url>https://github.com/looly/hutool</url>