mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix code
This commit is contained in:
parent
1218a51509
commit
17be56a99c
@ -14,6 +14,9 @@
|
||||
* 【script 】 增加createXXXScript,区别单例
|
||||
* 【core 】 修改FileUtil.writeFileToStream等方法返回值为long
|
||||
* 【core 】 CollUtil.split增加空集合判定(issue#814@Github)
|
||||
* 【core 】 NetUtil增加parseCookies方法
|
||||
* 【core 】 CollUtil增加toMap方法
|
||||
* 【core 】 CollUtil和IterUtil废弃一些方法
|
||||
|
||||
### Bug修复
|
||||
* 【extra 】 修复SpringUtil使用devtools重启报错问题
|
||||
|
@ -9,6 +9,7 @@ import cn.hutool.core.exceptions.UtilException;
|
||||
import cn.hutool.core.lang.Editor;
|
||||
import cn.hutool.core.lang.Filter;
|
||||
import cn.hutool.core.lang.Matcher;
|
||||
import cn.hutool.core.lang.func.Func1;
|
||||
import cn.hutool.core.lang.hash.Hash32;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
@ -245,7 +246,7 @@ public class CollUtil {
|
||||
*
|
||||
* @param coll1 集合1
|
||||
* @param coll2 集合2
|
||||
* @param <T> 元素类型
|
||||
* @param <T> 元素类型
|
||||
* @return 单差集
|
||||
*/
|
||||
public static <T> Collection<T> subtract(Collection<T> coll1, Collection<T> coll2) {
|
||||
@ -327,10 +328,10 @@ public class CollUtil {
|
||||
* @param <T> 集合元素类型
|
||||
* @param collection 集合
|
||||
* @return {@link Map}
|
||||
* @see IterUtil#countMap(Iterable)
|
||||
* @see IterUtil#countMap(Iterator)
|
||||
*/
|
||||
public static <T> Map<T, Integer> countMap(Iterable<T> collection) {
|
||||
return IterUtil.countMap(collection);
|
||||
return IterUtil.countMap(null == collection ? null : collection.iterator());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -341,10 +342,13 @@ public class CollUtil {
|
||||
* @param iterable {@link Iterable}
|
||||
* @param conjunction 分隔符
|
||||
* @return 连接后的字符串
|
||||
* @see IterUtil#join(Iterable, CharSequence)
|
||||
* @see IterUtil#join(Iterator, CharSequence)
|
||||
*/
|
||||
public static <T> String join(Iterable<T> iterable, CharSequence conjunction) {
|
||||
return IterUtil.join(iterable, conjunction);
|
||||
if (null == iterable) {
|
||||
return null;
|
||||
}
|
||||
return IterUtil.join(iterable.iterator(), conjunction);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -355,8 +359,9 @@ public class CollUtil {
|
||||
* @param iterator 集合
|
||||
* @param conjunction 分隔符
|
||||
* @return 连接后的字符串
|
||||
* @see IterUtil#join(Iterator, CharSequence)
|
||||
* @deprecated 请使用IterUtil#join(Iterator, CharSequence)
|
||||
*/
|
||||
@Deprecated
|
||||
public static <T> String join(Iterator<T> iterator, CharSequence conjunction) {
|
||||
return IterUtil.join(iterator, conjunction);
|
||||
}
|
||||
@ -643,8 +648,8 @@ public class CollUtil {
|
||||
* 新建一个List<br>
|
||||
* 提供的参数为null时返回空{@link ArrayList}
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param isLinked 是否新建LinkedList
|
||||
* @param <T> 集合元素类型
|
||||
* @param isLinked 是否新建LinkedList
|
||||
* @param enumeration {@link Enumeration}
|
||||
* @return ArrayList对象
|
||||
* @since 3.0.8
|
||||
@ -707,7 +712,7 @@ public class CollUtil {
|
||||
* 新建一个ArrayList<br>
|
||||
* 提供的参数为null时返回空{@link ArrayList}
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param <T> 集合元素类型
|
||||
* @param iterator {@link Iterator}
|
||||
* @return ArrayList对象
|
||||
* @since 3.0.8
|
||||
@ -720,7 +725,7 @@ public class CollUtil {
|
||||
* 新建一个ArrayList<br>
|
||||
* 提供的参数为null时返回空{@link ArrayList}
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param <T> 集合元素类型
|
||||
* @param enumeration {@link Enumeration}
|
||||
* @return ArrayList对象
|
||||
* @since 3.0.8
|
||||
@ -1204,6 +1209,36 @@ public class CollUtil {
|
||||
return Convert.toList(elementType, fieldValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字段值与列表值对应的Map,常用于元素对象中有唯一ID时需要按照这个ID查找对象的情况<br>
|
||||
* 例如:车牌号 =》车
|
||||
*
|
||||
* @param <K> 字段名对应值得类型,不确定请使用Object
|
||||
* @param <V> 对象类型
|
||||
* @param iterable 对象列表
|
||||
* @param fieldName 字段名(会通过反射获取其值)
|
||||
* @return 某个字段值与对象对应Map
|
||||
* @since 5.0.6
|
||||
*/
|
||||
public static <K, V> Map<K, V> fieldValueMap(Iterable<V> iterable, String fieldName) {
|
||||
return IterUtil.fieldValueMap(null == iterable ? null : iterable.iterator(), fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 两个字段值组成新的Map
|
||||
*
|
||||
* @param <K> 字段名对应值得类型,不确定请使用Object
|
||||
* @param <V> 值类型,不确定使用Object
|
||||
* @param iterable 对象列表
|
||||
* @param fieldNameForKey 做为键的字段名(会通过反射获取其值)
|
||||
* @param fieldNameForValue 做为值的字段名(会通过反射获取其值)
|
||||
* @return 某个字段值与对象对应Map
|
||||
* @since 5.0.6
|
||||
*/
|
||||
public static <K, V> Map<K, V> fieldValueAsMap(Iterable<?> iterable, String fieldNameForKey, String fieldNameForValue) {
|
||||
return IterUtil.fieldValueAsMap(null == iterable ? null : iterable.iterator(), fieldNameForKey, fieldNameForValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找第一个匹配元素对象
|
||||
*
|
||||
@ -1316,13 +1351,13 @@ public class CollUtil {
|
||||
* 获取匹配规则定义中匹配到元素的所有位置<br>
|
||||
* 此方法对于某些无序集合的位置信息,以转换为数组后的位置为准。
|
||||
*
|
||||
* @param <T> 元素类型
|
||||
* @param <T> 元素类型
|
||||
* @param collection 集合
|
||||
* @param matcher 匹配器,为空则全部匹配
|
||||
* @param matcher 匹配器,为空则全部匹配
|
||||
* @return 位置数组
|
||||
* @since 5.2.5
|
||||
*/
|
||||
public static <T> int[] indexOfAll(Collection<T> collection, Matcher<T> matcher){
|
||||
public static <T> int[] indexOfAll(Collection<T> collection, Matcher<T> matcher) {
|
||||
final List<Integer> indexList = new ArrayList<>();
|
||||
if (null != collection) {
|
||||
int index = 0;
|
||||
@ -1718,6 +1753,38 @@ public class CollUtil {
|
||||
return MapUtil.toMapList(listMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 集合转换为Map,转换规则为:<br>
|
||||
* 按照keyFunc函数规则根据元素对象生成Key,元素作为值
|
||||
*
|
||||
* @param <K> Map键类型
|
||||
* @param <V> Map值类型
|
||||
* @param values 数据列表
|
||||
* @param keyFunc 生成key的函数
|
||||
* @return 生成的map
|
||||
* @since 5.2.6
|
||||
*/
|
||||
public static <K, V> Map<K, V> toMap(Iterable<V> values, Map<K, V> map, Func1<V, K> keyFunc) {
|
||||
return IterUtil.toMap(null == values ? null : values.iterator(), map, keyFunc);
|
||||
}
|
||||
|
||||
/**
|
||||
* 集合转换为Map,转换规则为:<br>
|
||||
* 按照keyFunc函数规则根据元素对象生成Key,按照valueFunc函数规则根据元素对象生成value组成新的Map
|
||||
*
|
||||
* @param <K> Map键类型
|
||||
* @param <V> Map值类型
|
||||
* @param <E> 元素类型
|
||||
* @param values 数据列表
|
||||
* @param map Map对象,转换后的键值对加入此Map,通过传入此对象自定义Map类型
|
||||
* @param keyFunc 生成key的函数
|
||||
* @return 生成的map
|
||||
* @since 5.2.6
|
||||
*/
|
||||
public static <K, V, E> Map<K, V> toMap(Iterable<E> values, Map<K, V> map, Func1<E, K> keyFunc, Func1<E, V> valueFunc) {
|
||||
return IterUtil.toMap(null == values ? null : values.iterator(), map, keyFunc, valueFunc);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将指定对象全部加入到集合中<br>
|
||||
* 提供的对象如果为集合类型,会自动转换为目标元素类型<br>
|
||||
|
@ -1,17 +1,24 @@
|
||||
package cn.hutool.core.collection;
|
||||
|
||||
import cn.hutool.core.exceptions.UtilException;
|
||||
import cn.hutool.core.lang.Filter;
|
||||
import cn.hutool.core.lang.func.Func1;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* {@link Iterable} 和 {@link Iterator} 相关工具类
|
||||
*
|
||||
*
|
||||
* @author Looly
|
||||
* @since 3.1.0
|
||||
*/
|
||||
@ -19,7 +26,7 @@ public class IterUtil {
|
||||
|
||||
/**
|
||||
* Iterable是否为空
|
||||
*
|
||||
*
|
||||
* @param iterable Iterable对象
|
||||
* @return 是否为空
|
||||
*/
|
||||
@ -29,7 +36,7 @@ public class IterUtil {
|
||||
|
||||
/**
|
||||
* Iterator是否为空
|
||||
*
|
||||
*
|
||||
* @param Iterator Iterator对象
|
||||
* @return 是否为空
|
||||
*/
|
||||
@ -39,7 +46,7 @@ public class IterUtil {
|
||||
|
||||
/**
|
||||
* Iterable是否为空
|
||||
*
|
||||
*
|
||||
* @param iterable Iterable对象
|
||||
* @return 是否为空
|
||||
*/
|
||||
@ -49,7 +56,7 @@ public class IterUtil {
|
||||
|
||||
/**
|
||||
* Iterator是否为空
|
||||
*
|
||||
*
|
||||
* @param Iterator Iterator对象
|
||||
* @return 是否为空
|
||||
*/
|
||||
@ -59,7 +66,7 @@ public class IterUtil {
|
||||
|
||||
/**
|
||||
* 是否包含{@code null}元素
|
||||
*
|
||||
*
|
||||
* @param iter 被检查的{@link Iterable}对象,如果为{@code null} 返回true
|
||||
* @return 是否包含{@code null}元素
|
||||
*/
|
||||
@ -69,7 +76,7 @@ public class IterUtil {
|
||||
|
||||
/**
|
||||
* 是否包含{@code null}元素
|
||||
*
|
||||
*
|
||||
* @param iter 被检查的{@link Iterator}对象,如果为{@code null} 返回true
|
||||
* @return 是否包含{@code null}元素
|
||||
*/
|
||||
@ -88,7 +95,7 @@ public class IterUtil {
|
||||
|
||||
/**
|
||||
* 是否全部元素为null
|
||||
*
|
||||
*
|
||||
* @param iter iter 被检查的{@link Iterable}对象,如果为{@code null} 返回true
|
||||
* @return 是否全部元素为null
|
||||
* @since 3.3.0
|
||||
@ -99,7 +106,7 @@ public class IterUtil {
|
||||
|
||||
/**
|
||||
* 是否全部元素为null
|
||||
*
|
||||
*
|
||||
* @param iter iter 被检查的{@link Iterator}对象,如果为{@code null} 返回true
|
||||
* @return 是否全部元素为null
|
||||
* @since 3.3.0
|
||||
@ -124,11 +131,13 @@ public class IterUtil {
|
||||
* a: 1<br>
|
||||
* b: 1<br>
|
||||
* c: 3<br>
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param iter {@link Iterable},如果为null返回一个空的Map
|
||||
* @return {@link Map}
|
||||
* @deprecated 如果对象同时实现Iterable和Iterator接口会产生歧义,请使用CollUtil.countMap
|
||||
*/
|
||||
@Deprecated
|
||||
public static <T> Map<T, Integer> countMap(Iterable<T> iter) {
|
||||
return countMap(null == iter ? null : iter.iterator());
|
||||
}
|
||||
@ -140,8 +149,8 @@ public class IterUtil {
|
||||
* a: 1<br>
|
||||
* b: 1<br>
|
||||
* c: 3<br>
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param iter {@link Iterator},如果为null返回一个空的Map
|
||||
* @return {@link Map}
|
||||
*/
|
||||
@ -166,14 +175,16 @@ public class IterUtil {
|
||||
/**
|
||||
* 字段值与列表值对应的Map,常用于元素对象中有唯一ID时需要按照这个ID查找对象的情况<br>
|
||||
* 例如:车牌号 =》车
|
||||
*
|
||||
* @param <K> 字段名对应值得类型,不确定请使用Object
|
||||
* @param <V> 对象类型
|
||||
* @param iter 对象列表
|
||||
*
|
||||
* @param <K> 字段名对应值得类型,不确定请使用Object
|
||||
* @param <V> 对象类型
|
||||
* @param iter 对象列表
|
||||
* @param fieldName 字段名(会通过反射获取其值)
|
||||
* @return 某个字段值与对象对应Map
|
||||
* @since 4.0.4
|
||||
* @deprecated 如果对象同时实现Iterable和Iterator接口会产生歧义,请使用CollUtil.fieldValueMap
|
||||
*/
|
||||
@Deprecated
|
||||
public static <K, V> Map<K, V> fieldValueMap(Iterable<V> iter, String fieldName) {
|
||||
return fieldValueMap(null == iter ? null : iter.iterator(), fieldName);
|
||||
}
|
||||
@ -181,71 +192,60 @@ public class IterUtil {
|
||||
/**
|
||||
* 字段值与列表值对应的Map,常用于元素对象中有唯一ID时需要按照这个ID查找对象的情况<br>
|
||||
* 例如:车牌号 =》车
|
||||
*
|
||||
* @param <K> 字段名对应值得类型,不确定请使用Object
|
||||
* @param <V> 对象类型
|
||||
* @param iter 对象列表
|
||||
*
|
||||
* @param <K> 字段名对应值得类型,不确定请使用Object
|
||||
* @param <V> 对象类型
|
||||
* @param iter 对象列表
|
||||
* @param fieldName 字段名(会通过反射获取其值)
|
||||
* @return 某个字段值与对象对应Map
|
||||
* @since 4.0.4
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <K, V> Map<K, V> fieldValueMap(Iterator<V> iter, String fieldName) {
|
||||
final Map<K, V> result = new HashMap<>();
|
||||
if (null != iter) {
|
||||
V value;
|
||||
while (iter.hasNext()) {
|
||||
value = iter.next();
|
||||
result.put((K) ReflectUtil.getFieldValue(value, fieldName), value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return toMap(iter, new HashMap<>(), (value)->(K)ReflectUtil.getFieldValue(value, fieldName));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 两个字段值组成新的Map
|
||||
*
|
||||
* @param <K> 字段名对应值得类型,不确定请使用Object
|
||||
* @param <V> 值类型,不确定使用Object
|
||||
* @param iterable 对象列表
|
||||
* @param fieldNameForKey 做为键的字段名(会通过反射获取其值)
|
||||
*
|
||||
* @param <K> 字段名对应值得类型,不确定请使用Object
|
||||
* @param <V> 值类型,不确定使用Object
|
||||
* @param iterable 对象列表
|
||||
* @param fieldNameForKey 做为键的字段名(会通过反射获取其值)
|
||||
* @param fieldNameForValue 做为值的字段名(会通过反射获取其值)
|
||||
* @return 某个字段值与对象对应Map
|
||||
* @since 4.6.2
|
||||
* @deprecated 如果对象同时实现Iterable和Iterator接口会产生歧义,请使用CollUtil.fieldValueMap
|
||||
*/
|
||||
@Deprecated
|
||||
public static <K, V> Map<K, V> fieldValueAsMap(Iterable<?> iterable, String fieldNameForKey, String fieldNameForValue) {
|
||||
return fieldValueAsMap(null == iterable ? null : iterable.iterator(), fieldNameForKey, fieldNameForValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 两个字段值组成新的Map
|
||||
*
|
||||
* @param <K> 字段名对应值得类型,不确定请使用Object
|
||||
* @param <V> 值类型,不确定使用Object
|
||||
* @param iter 对象列表
|
||||
* @param fieldNameForKey 做为键的字段名(会通过反射获取其值)
|
||||
*
|
||||
* @param <K> 字段名对应值得类型,不确定请使用Object
|
||||
* @param <V> 值类型,不确定使用Object
|
||||
* @param iter 对象列表
|
||||
* @param fieldNameForKey 做为键的字段名(会通过反射获取其值)
|
||||
* @param fieldNameForValue 做为值的字段名(会通过反射获取其值)
|
||||
* @return 某个字段值与对象对应Map
|
||||
* @since 4.0.10
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <K, V> Map<K, V> fieldValueAsMap(Iterator<?> iter, String fieldNameForKey, String fieldNameForValue) {
|
||||
final Map<K, V> result = new HashMap<>();
|
||||
if (null != iter) {
|
||||
Object value;
|
||||
while (iter.hasNext()) {
|
||||
value = iter.next();
|
||||
result.put((K) ReflectUtil.getFieldValue(value, fieldNameForKey), (V) ReflectUtil.getFieldValue(value, fieldNameForValue));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return toMap(iter, new HashMap<>(),
|
||||
(value)->(K)ReflectUtil.getFieldValue(value, fieldNameForKey),
|
||||
(value)->(V)ReflectUtil.getFieldValue(value, fieldNameForValue)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定Bean列表中某个字段,生成新的列表
|
||||
*
|
||||
* @param <V> 对象类型
|
||||
* @param iterable 对象列表
|
||||
*
|
||||
* @param <V> 对象类型
|
||||
* @param iterable 对象列表
|
||||
* @param fieldName 字段名(会通过反射获取其值)
|
||||
* @return 某个字段值与对象对应Map
|
||||
* @since 4.6.2
|
||||
@ -256,9 +256,9 @@ public class IterUtil {
|
||||
|
||||
/**
|
||||
* 获取指定Bean列表中某个字段,生成新的列表
|
||||
*
|
||||
* @param <V> 对象类型
|
||||
* @param iter 对象列表
|
||||
*
|
||||
* @param <V> 对象类型
|
||||
* @param iter 对象列表
|
||||
* @param fieldName 字段名(会通过反射获取其值)
|
||||
* @return 某个字段值与对象对应Map
|
||||
* @since 4.0.10
|
||||
@ -277,27 +277,29 @@ public class IterUtil {
|
||||
|
||||
/**
|
||||
* 以 conjunction 为分隔符将集合转换为字符串
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param iterable {@link Iterable}
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param iterable {@link Iterable}
|
||||
* @param conjunction 分隔符
|
||||
* @return 连接后的字符串
|
||||
* @deprecated 如果对象同时实现Iterable和Iterator接口会产生歧义,请使用CollUtil.join
|
||||
*/
|
||||
@Deprecated
|
||||
public static <T> String join(Iterable<T> iterable, CharSequence conjunction) {
|
||||
if (null == iterable) {
|
||||
return null;
|
||||
}
|
||||
return join(iterable.iterator(), conjunction);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 以 conjunction 为分隔符将集合转换为字符串
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param iterable {@link Iterable}
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param iterable {@link Iterable}
|
||||
* @param conjunction 分隔符
|
||||
* @param prefix 每个元素添加的前缀,null表示不添加
|
||||
* @param suffix 每个元素添加的后缀,null表示不添加
|
||||
* @param prefix 每个元素添加的前缀,null表示不添加
|
||||
* @param suffix 每个元素添加的后缀,null表示不添加
|
||||
* @return 连接后的字符串
|
||||
* @since 4.0.10
|
||||
*/
|
||||
@ -307,13 +309,13 @@ public class IterUtil {
|
||||
}
|
||||
return join(iterable.iterator(), conjunction, prefix, suffix);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 以 conjunction 为分隔符将集合转换为字符串<br>
|
||||
* 如果集合元素为数组、{@link Iterable}或{@link Iterator},则递归组合其为字符串
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param iterator 集合
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param iterator 集合
|
||||
* @param conjunction 分隔符
|
||||
* @return 连接后的字符串
|
||||
*/
|
||||
@ -324,12 +326,12 @@ public class IterUtil {
|
||||
/**
|
||||
* 以 conjunction 为分隔符将集合转换为字符串<br>
|
||||
* 如果集合元素为数组、{@link Iterable}或{@link Iterator},则递归组合其为字符串
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param iterator 集合
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param iterator 集合
|
||||
* @param conjunction 分隔符
|
||||
* @param prefix 每个元素添加的前缀,null表示不添加
|
||||
* @param suffix 每个元素添加的后缀,null表示不添加
|
||||
* @param prefix 每个元素添加的前缀,null表示不添加
|
||||
* @param suffix 每个元素添加的后缀,null表示不添加
|
||||
* @return 连接后的字符串
|
||||
* @since 4.0.10
|
||||
*/
|
||||
@ -364,9 +366,9 @@ public class IterUtil {
|
||||
|
||||
/**
|
||||
* 将Entry集合转换为HashMap
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @param entryIter entry集合
|
||||
* @return Map
|
||||
*/
|
||||
@ -379,15 +381,15 @@ public class IterUtil {
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将键列表和值列表转换为Map<br>
|
||||
* 以键为准,值与键位置需对应。如果键元素数多于值元素,多余部分值用null代替。<br>
|
||||
* 如果值多于键,忽略多余的值。
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @param keys 键列表
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @param keys 键列表
|
||||
* @param values 值列表
|
||||
* @return 标题内容Map
|
||||
* @since 3.1.0
|
||||
@ -400,11 +402,11 @@ public class IterUtil {
|
||||
* 将键列表和值列表转换为Map<br>
|
||||
* 以键为准,值与键位置需对应。如果键元素数多于值元素,多余部分值用null代替。<br>
|
||||
* 如果值多于键,忽略多余的值。
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @param keys 键列表
|
||||
* @param values 值列表
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @param keys 键列表
|
||||
* @param values 值列表
|
||||
* @param isOrder 是否有序
|
||||
* @return 标题内容Map
|
||||
* @since 4.1.12
|
||||
@ -412,15 +414,15 @@ public class IterUtil {
|
||||
public static <K, V> Map<K, V> toMap(Iterable<K> keys, Iterable<V> values, boolean isOrder) {
|
||||
return toMap(null == keys ? null : keys.iterator(), null == values ? null : values.iterator(), isOrder);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将键列表和值列表转换为Map<br>
|
||||
* 以键为准,值与键位置需对应。如果键元素数多于值元素,多余部分值用null代替。<br>
|
||||
* 如果值多于键,忽略多余的值。
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @param keys 键列表
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @param keys 键列表
|
||||
* @param values 值列表
|
||||
* @return 标题内容Map
|
||||
* @since 3.1.0
|
||||
@ -433,11 +435,11 @@ public class IterUtil {
|
||||
* 将键列表和值列表转换为Map<br>
|
||||
* 以键为准,值与键位置需对应。如果键元素数多于值元素,多余部分值用null代替。<br>
|
||||
* 如果值多于键,忽略多余的值。
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @param keys 键列表
|
||||
* @param values 值列表
|
||||
*
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @param keys 键列表
|
||||
* @param values 值列表
|
||||
* @param isOrder 是否有序
|
||||
* @return 标题内容Map
|
||||
* @since 4.1.12
|
||||
@ -455,14 +457,14 @@ public class IterUtil {
|
||||
/**
|
||||
* Iterator转List<br>
|
||||
* 不判断,直接生成新的List
|
||||
*
|
||||
* @param <E> 元素类型
|
||||
*
|
||||
* @param <E> 元素类型
|
||||
* @param iter {@link Iterator}
|
||||
* @return List
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static <E> List<E> toList(Iterable<E> iter) {
|
||||
if(null == iter) {
|
||||
if (null == iter) {
|
||||
return null;
|
||||
}
|
||||
return toList(iter.iterator());
|
||||
@ -471,8 +473,8 @@ public class IterUtil {
|
||||
/**
|
||||
* Iterator转List<br>
|
||||
* 不判断,直接生成新的List
|
||||
*
|
||||
* @param <E> 元素类型
|
||||
*
|
||||
* @param <E> 元素类型
|
||||
* @param iter {@link Iterator}
|
||||
* @return List
|
||||
* @since 4.0.6
|
||||
@ -489,9 +491,9 @@ public class IterUtil {
|
||||
* Enumeration转换为Iterator
|
||||
* <p>
|
||||
* Adapt the specified <code>Enumeration</code> to the <code>Iterator</code> interface
|
||||
*
|
||||
*
|
||||
* @param <E> 集合元素类型
|
||||
* @param e {@link Enumeration}
|
||||
* @param e {@link Enumeration}
|
||||
* @return {@link Iterator}
|
||||
*/
|
||||
public static <E> Iterator<E> asIterator(Enumeration<E> e) {
|
||||
@ -500,8 +502,8 @@ public class IterUtil {
|
||||
|
||||
/**
|
||||
* {@link Iterator} 转为 {@link Iterable}
|
||||
*
|
||||
* @param <E> 元素类型
|
||||
*
|
||||
* @param <E> 元素类型
|
||||
* @param iter {@link Iterator}
|
||||
* @return {@link Iterable}
|
||||
*/
|
||||
@ -511,8 +513,8 @@ public class IterUtil {
|
||||
|
||||
/**
|
||||
* 获取集合的第一个元素
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param iterable {@link Iterable}
|
||||
* @return 第一个元素
|
||||
*/
|
||||
@ -525,8 +527,8 @@ public class IterUtil {
|
||||
|
||||
/**
|
||||
* 获取集合的第一个元素
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param iterator {@link Iterator}
|
||||
* @return 第一个元素
|
||||
*/
|
||||
@ -540,7 +542,7 @@ public class IterUtil {
|
||||
/**
|
||||
* 获得{@link Iterable}对象的元素类型(通过第一个非空元素判断)<br>
|
||||
* 注意,此方法至少会调用多次next方法
|
||||
*
|
||||
*
|
||||
* @param iterable {@link Iterable}
|
||||
* @return 元素类型,当列表为空或元素全部为null时,返回null
|
||||
*/
|
||||
@ -555,7 +557,7 @@ public class IterUtil {
|
||||
/**
|
||||
* 获得{@link Iterator}对象的元素类型(通过第一个非空元素判断)<br>
|
||||
* 注意,此方法至少会调用多次next方法
|
||||
*
|
||||
*
|
||||
* @param iterator {@link Iterator}
|
||||
* @return 元素类型,当列表为空或元素全部为null时,返回null
|
||||
*/
|
||||
@ -569,42 +571,42 @@ public class IterUtil {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 过滤集合,此方法在原集合上直接修改<br>
|
||||
* 通过实现Filter接口,完成元素的过滤,这个Filter实现可以实现以下功能:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* 1、过滤出需要的对象,{@link Filter#accept(Object)}方法返回false的对象将被使用{@link Iterator#remove()}方法移除
|
||||
* </pre>
|
||||
*
|
||||
* @param <T> 集合类型
|
||||
* @param <E> 集合元素类型
|
||||
* @param iter 集合
|
||||
*
|
||||
* @param <T> 集合类型
|
||||
* @param <E> 集合元素类型
|
||||
* @param iter 集合
|
||||
* @param filter 过滤器接口
|
||||
* @return 编辑后的集合
|
||||
* @since 4.6.5
|
||||
*/
|
||||
public static <T extends Iterable<E>, E> T filter(T iter, Filter<E> filter) {
|
||||
if(null == iter) {
|
||||
if (null == iter) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
filter(iter.iterator(), filter);
|
||||
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 过滤集合,此方法在原集合上直接修改<br>
|
||||
* 通过实现Filter接口,完成元素的过滤,这个Filter实现可以实现以下功能:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* 1、过滤出需要的对象,{@link Filter#accept(Object)}方法返回false的对象将被使用{@link Iterator#remove()}方法移除
|
||||
* </pre>
|
||||
*
|
||||
* @param <E> 集合元素类型
|
||||
* @param iter 集合
|
||||
*
|
||||
* @param <E> 集合元素类型
|
||||
* @param iter 集合
|
||||
* @param filter 过滤器接口
|
||||
* @return 编辑后的集合
|
||||
* @since 4.6.5
|
||||
@ -614,11 +616,61 @@ public class IterUtil {
|
||||
return iter;
|
||||
}
|
||||
|
||||
while(iter.hasNext()) {
|
||||
if(false == filter.accept(iter.next())) {
|
||||
while (iter.hasNext()) {
|
||||
if (false == filter.accept(iter.next())) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
return iter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator转换为Map,转换规则为:<br>
|
||||
* 按照keyFunc函数规则根据元素对象生成Key,元素作为值
|
||||
*
|
||||
* @param <K> Map键类型
|
||||
* @param <V> Map值类型
|
||||
* @param iterator 数据列表
|
||||
* @param map Map对象,转换后的键值对加入此Map,通过传入此对象自定义Map类型
|
||||
* @param keyFunc 生成key的函数
|
||||
* @return 生成的map
|
||||
* @since 5.2.6
|
||||
*/
|
||||
public static <K, V> Map<K, V> toMap(Iterator<V> iterator, Map<K, V> map, Func1<V, K> keyFunc) {
|
||||
return toMap(iterator, map, keyFunc, (value) -> value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 集合转换为Map,转换规则为:<br>
|
||||
* 按照keyFunc函数规则根据元素对象生成Key,按照valueFunc函数规则根据元素对象生成value组成新的Map
|
||||
*
|
||||
* @param <K> Map键类型
|
||||
* @param <V> Map值类型
|
||||
* @param <E> 元素类型
|
||||
* @param iterator 数据列表
|
||||
* @param map Map对象,转换后的键值对加入此Map,通过传入此对象自定义Map类型
|
||||
* @param keyFunc 生成key的函数
|
||||
* @return 生成的map
|
||||
* @since 5.2.6
|
||||
*/
|
||||
public static <K, V, E> Map<K, V> toMap(Iterator<E> iterator, Map<K, V> map, Func1<E, K> keyFunc, Func1<E, V> valueFunc) {
|
||||
if (null == iterator) {
|
||||
return map;
|
||||
}
|
||||
|
||||
if (null == map) {
|
||||
map = MapUtil.newHashMap(true);
|
||||
}
|
||||
|
||||
E element;
|
||||
while (iterator.hasNext()) {
|
||||
element = iterator.next();
|
||||
try {
|
||||
map.put(keyFunc.call(element), valueFunc.call(element));
|
||||
} catch (Exception e) {
|
||||
throw new UtilException(e);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.HttpCookie;
|
||||
import java.net.IDN;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
@ -29,6 +30,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
@ -647,7 +649,7 @@ public class NetUtil {
|
||||
if (ip != null && ip.indexOf(",") > 0) {
|
||||
final String[] ips = ip.trim().split(",");
|
||||
for (String subIp : ips) {
|
||||
if (false == isUnknow(subIp)) {
|
||||
if (false == isUnknown(subIp)) {
|
||||
ip = subIp;
|
||||
break;
|
||||
}
|
||||
@ -662,8 +664,20 @@ public class NetUtil {
|
||||
* @param checkString 被检测的字符串
|
||||
* @return 是否未知
|
||||
* @since 4.4.1
|
||||
* @deprecated 拼写错误,请使用{@link #isUnknown(String)}
|
||||
*/
|
||||
public static boolean isUnknow(String checkString) {
|
||||
return isUnknown(checkString);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测给定字符串是否为未知,多用于检测HTTP请求相关<br>
|
||||
*
|
||||
* @param checkString 被检测的字符串
|
||||
* @return 是否未知
|
||||
* @since 5.2.6
|
||||
*/
|
||||
public static boolean isUnknown(String checkString) {
|
||||
return StrUtil.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
|
||||
}
|
||||
|
||||
@ -692,6 +706,19 @@ public class NetUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析Cookie信息
|
||||
*
|
||||
* @param cookieStr Cookie字符串
|
||||
* @return cookie字符串
|
||||
* @since 5.2.6
|
||||
*/
|
||||
public static List<HttpCookie> parseCookies(String cookieStr){
|
||||
if(StrUtil.isBlank(cookieStr)){
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
return HttpCookie.parse(cookieStr);
|
||||
}
|
||||
// ----------------------------------------------------------------------------------------- Private method start
|
||||
|
||||
/**
|
||||
|
@ -277,6 +277,32 @@ public class CollUtilTest {
|
||||
Assert.assertEquals("张三", list.get(2).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fieldValueMapTest() {
|
||||
List<TestBean> list = CollUtil.newArrayList(new TestBean("张三", 12, DateUtil.parse("2018-05-01")), //
|
||||
new TestBean("李四", 13, DateUtil.parse("2018-03-01")), //
|
||||
new TestBean("王五", 12, DateUtil.parse("2018-04-01"))//
|
||||
);
|
||||
|
||||
final Map<String, TestBean> map = CollUtil.fieldValueMap(list, "name");
|
||||
Assert.assertEquals("李四", map.get("李四").getName());
|
||||
Assert.assertEquals("王五", map.get("王五").getName());
|
||||
Assert.assertEquals("张三", map.get("张三").getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fieldValueAsMapTest() {
|
||||
List<TestBean> list = CollUtil.newArrayList(new TestBean("张三", 12, DateUtil.parse("2018-05-01")), //
|
||||
new TestBean("李四", 13, DateUtil.parse("2018-03-01")), //
|
||||
new TestBean("王五", 14, DateUtil.parse("2018-04-01"))//
|
||||
);
|
||||
|
||||
final Map<String, Integer> map = CollUtil.fieldValueAsMap(list, "name", "age");
|
||||
Assert.assertEquals(new Integer(12), map.get("张三"));
|
||||
Assert.assertEquals(new Integer(13), map.get("李四"));
|
||||
Assert.assertEquals(new Integer(14), map.get("王五"));
|
||||
}
|
||||
|
||||
public static class TestBean {
|
||||
private String name;
|
||||
private int age;
|
||||
@ -600,4 +626,25 @@ public class CollUtilTest {
|
||||
Assert.assertEquals(3, map.get("c").intValue());
|
||||
Assert.assertEquals(4, map.get("d").intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toMapTest(){
|
||||
Collection<String> keys = CollUtil.newArrayList("a", "b", "c", "d");
|
||||
final Map<String, String> map = CollUtil.toMap(keys, new HashMap<>(), (value)->"key" + value);
|
||||
Assert.assertEquals("a", map.get("keya"));
|
||||
Assert.assertEquals("b", map.get("keyb"));
|
||||
Assert.assertEquals("c", map.get("keyc"));
|
||||
Assert.assertEquals("d", map.get("keyd"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void countMapTest() {
|
||||
ArrayList<String> list = CollUtil.newArrayList("a", "b", "c", "c", "a", "b", "d");
|
||||
Map<String, Integer> countMap = CollUtil.countMap(list);
|
||||
|
||||
Assert.assertEquals(Integer.valueOf(2), countMap.get("a"));
|
||||
Assert.assertEquals(Integer.valueOf(2), countMap.get("b"));
|
||||
Assert.assertEquals(Integer.valueOf(2), countMap.get("c"));
|
||||
Assert.assertEquals(Integer.valueOf(1), countMap.get("d"));
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
package cn.hutool.core.collection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@link IterUtil} 单元测试
|
||||
* @author looly
|
||||
@ -13,17 +13,6 @@ import org.junit.Test;
|
||||
*/
|
||||
public class IterUtilTest {
|
||||
|
||||
@Test
|
||||
public void countMapTest() {
|
||||
ArrayList<String> list = CollUtil.newArrayList("a", "b", "c", "c", "a", "b", "d");
|
||||
Map<String, Integer> countMap = IterUtil.countMap(list);
|
||||
|
||||
Assert.assertEquals(Integer.valueOf(2), countMap.get("a"));
|
||||
Assert.assertEquals(Integer.valueOf(2), countMap.get("b"));
|
||||
Assert.assertEquals(Integer.valueOf(2), countMap.get("c"));
|
||||
Assert.assertEquals(Integer.valueOf(1), countMap.get("d"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fieldValueMapTest() {
|
||||
ArrayList<Car> carList = CollUtil.newArrayList(new Car("123", "大众"), new Car("345", "奔驰"), new Car("567", "路虎"));
|
||||
|
@ -6,7 +6,9 @@ import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.net.HttpCookie;
|
||||
import java.net.InetAddress;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* NetUtil单元测试
|
||||
@ -57,4 +59,18 @@ public class NetUtilTest {
|
||||
public void isUsableLocalPortTest(){
|
||||
Assert.assertTrue(NetUtil.isUsableLocalPort(80));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseCookiesTest(){
|
||||
String cookieStr = "cookieName=\"cookieValue\";Path=\"/\";Domain=\"cookiedomain.com\"";
|
||||
final List<HttpCookie> httpCookies = NetUtil.parseCookies(cookieStr);
|
||||
Assert.assertEquals(1, httpCookies.size());
|
||||
|
||||
final HttpCookie httpCookie = httpCookies.get(0);
|
||||
Assert.assertEquals(0, httpCookie.getVersion());
|
||||
Assert.assertEquals("cookieName", httpCookie.getName());
|
||||
Assert.assertEquals("cookieValue", httpCookie.getValue());
|
||||
Assert.assertEquals("/", httpCookie.getPath());
|
||||
Assert.assertEquals("cookiedomain.com", httpCookie.getDomain());
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,14 @@ package cn.hutool.extra.servlet;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.bean.copier.CopyOptions;
|
||||
import cn.hutool.core.bean.copier.ValueProvider;
|
||||
import cn.hutool.core.collection.ArrayIter;
|
||||
import cn.hutool.core.collection.IterUtil;
|
||||
import cn.hutool.core.exceptions.UtilException;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.map.CaseInsensitiveMap;
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
@ -227,13 +230,13 @@ public class ServletUtil {
|
||||
String ip;
|
||||
for (String header : headerNames) {
|
||||
ip = request.getHeader(header);
|
||||
if (false == isUnknow(ip)) {
|
||||
return getMultistageReverseProxyIp(ip);
|
||||
if (false == NetUtil.isUnknown(ip)) {
|
||||
return NetUtil.getMultistageReverseProxyIp(ip);
|
||||
}
|
||||
}
|
||||
|
||||
ip = request.getRemoteAddr();
|
||||
return getMultistageReverseProxyIp(ip);
|
||||
return NetUtil.getMultistageReverseProxyIp(ip);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -415,14 +418,10 @@ public class ServletUtil {
|
||||
* @return Cookie map
|
||||
*/
|
||||
public static Map<String, Cookie> readCookieMap(HttpServletRequest httpServletRequest) {
|
||||
final Map<String, Cookie> cookieMap = new CaseInsensitiveMap<>();
|
||||
final Cookie[] cookies = httpServletRequest.getCookies();
|
||||
if (null != cookies) {
|
||||
for (Cookie cookie : cookies) {
|
||||
cookieMap.put(cookie.getName(), cookie);
|
||||
}
|
||||
}
|
||||
return cookieMap;
|
||||
return IterUtil.toMap(
|
||||
new ArrayIter<>(httpServletRequest.getCookies()),
|
||||
new CaseInsensitiveMap<>(),
|
||||
Cookie::getName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -614,37 +613,4 @@ public class ServletUtil {
|
||||
}
|
||||
}
|
||||
// --------------------------------------------------------- Response end
|
||||
|
||||
// --------------------------------------------------------- Private methd start
|
||||
/**
|
||||
* 从多级反向代理中获得第一个非unknown IP地址
|
||||
*
|
||||
* @param ip 获得的IP地址
|
||||
* @return 第一个非unknown IP地址
|
||||
*/
|
||||
private static String getMultistageReverseProxyIp(String ip) {
|
||||
// 多级反向代理检测
|
||||
if (ip != null && ip.indexOf(",") > 0) {
|
||||
final String[] ips = ip.trim().split(",");
|
||||
for (String subIp : ips) {
|
||||
if (false == isUnknow(subIp)) {
|
||||
ip = subIp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测给定字符串是否为未知,多用于检测HTTP请求相关<br>
|
||||
*
|
||||
* @param checkString 被检测的字符串
|
||||
* @return 是否未知
|
||||
*/
|
||||
private static boolean isUnknow(String checkString) {
|
||||
return StrUtil.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
|
||||
}
|
||||
// --------------------------------------------------------- Private methd end
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
package cn.hutool.http.server;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.map.CaseInsensitiveMap;
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.Header;
|
||||
@ -12,8 +16,11 @@ import com.sun.net.httpserver.Headers;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpCookie;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Http请求对象,对{@link HttpExchange}封装
|
||||
@ -25,6 +32,8 @@ public class HttpRequest {
|
||||
|
||||
private final HttpExchange httpExchange;
|
||||
|
||||
private Map<String, HttpCookie> cookieCache;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
@ -97,6 +106,16 @@ public class HttpRequest {
|
||||
return this.httpExchange.getRequestHeaders();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得请求header中的信息
|
||||
*
|
||||
* @param headerKey 头信息的KEY
|
||||
* @return header值
|
||||
*/
|
||||
public String getHeader(Header headerKey) {
|
||||
return getHeader(headerKey.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得请求header中的信息
|
||||
*
|
||||
@ -122,13 +141,22 @@ public class HttpRequest {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Content-Type头信息
|
||||
*
|
||||
* @return Content-Type头信息
|
||||
*/
|
||||
public String getContentType() {
|
||||
return getHeader(Header.USER_AGENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得User-Agent
|
||||
*
|
||||
* @return User-Agent字符串
|
||||
*/
|
||||
public String getUserAgentStr() {
|
||||
return getHeader("User-Agent");
|
||||
return getHeader(Header.USER_AGENT);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -140,6 +168,49 @@ public class HttpRequest {
|
||||
return UserAgentUtil.parse(getUserAgentStr());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得Cookie信息字符串
|
||||
*
|
||||
* @return cookie字符串
|
||||
*/
|
||||
public String getCookiesStr() {
|
||||
return getHeader(Header.COOKIE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得Cookie信息列表
|
||||
*
|
||||
* @return Cookie信息列表
|
||||
*/
|
||||
public Collection<HttpCookie> getCookies() {
|
||||
return getCookieMap().values();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得Cookie信息Map,键为Cookie名,值为HttpCookie对象
|
||||
*
|
||||
* @return Cookie信息Map
|
||||
*/
|
||||
public Map<String, HttpCookie> getCookieMap() {
|
||||
if (null == this.cookieCache) {
|
||||
cookieCache = CollUtil.toMap(
|
||||
NetUtil.parseCookies(getCookiesStr()),
|
||||
new CaseInsensitiveMap<>(),
|
||||
HttpCookie::getName);
|
||||
}
|
||||
return cookieCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得指定Cookie名对应的HttpCookie对象
|
||||
*
|
||||
* @param cookieName Cookie名
|
||||
* @return HttpCookie对象
|
||||
*/
|
||||
public HttpCookie getCookie(String cookieName) {
|
||||
return getCookieMap().get(cookieName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求体的流,流中可以读取请求内容,包括请求表单数据或文件上传数据
|
||||
*
|
||||
@ -156,7 +227,7 @@ public class HttpRequest {
|
||||
* @return 请求
|
||||
*/
|
||||
public String getBody() {
|
||||
final String contentType = getHeader(Header.CONTENT_TYPE.toString());
|
||||
final String contentType = getContentType();
|
||||
final String charsetStr = HttpUtil.getCharset(contentType);
|
||||
final Charset charset = CharsetUtil.parse(charsetStr, CharsetUtil.CHARSET_UTF_8);
|
||||
|
||||
@ -189,11 +260,66 @@ public class HttpRequest {
|
||||
return false;
|
||||
}
|
||||
|
||||
final String contentType = getHeader(Header.CONTENT_TYPE.toString());
|
||||
final String contentType = getContentType();
|
||||
if (StrUtil.isBlank(contentType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return contentType.toLowerCase().startsWith("multipart/");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户端IP
|
||||
*
|
||||
* <p>
|
||||
* 默认检测的Header:
|
||||
*
|
||||
* <pre>
|
||||
* 1、X-Forwarded-For
|
||||
* 2、X-Real-IP
|
||||
* 3、Proxy-Client-IP
|
||||
* 4、WL-Proxy-Client-IP
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* otherHeaderNames参数用于自定义检测的Header<br>
|
||||
* 需要注意的是,使用此方法获取的客户IP地址必须在Http服务器(例如Nginx)中配置头信息,否则容易造成IP伪造。
|
||||
* </p>
|
||||
*
|
||||
* @param otherHeaderNames 其他自定义头文件,通常在Http服务器(例如Nginx)中配置
|
||||
* @return IP地址
|
||||
*/
|
||||
public String getClientIP(String... otherHeaderNames) {
|
||||
String[] headers = {"X-Forwarded-For", "X-Real-IP", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"};
|
||||
if (ArrayUtil.isNotEmpty(otherHeaderNames)) {
|
||||
headers = ArrayUtil.addAll(headers, otherHeaderNames);
|
||||
}
|
||||
|
||||
return getClientIPByHeader(headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户端IP
|
||||
*
|
||||
* <p>
|
||||
* headerNames参数用于自定义检测的Header<br>
|
||||
* 需要注意的是,使用此方法获取的客户IP地址必须在Http服务器(例如Nginx)中配置头信息,否则容易造成IP伪造。
|
||||
* </p>
|
||||
*
|
||||
* @param headerNames 自定义头,通常在Http服务器(例如Nginx)中配置
|
||||
* @return IP地址
|
||||
* @since 4.4.1
|
||||
*/
|
||||
public String getClientIPByHeader(String... headerNames) {
|
||||
String ip;
|
||||
for (String header : headerNames) {
|
||||
ip = getHeader(header);
|
||||
if (false == NetUtil.isUnknown(ip)) {
|
||||
return NetUtil.getMultistageReverseProxyIp(ip);
|
||||
}
|
||||
}
|
||||
|
||||
ip = this.httpExchange.getRemoteAddress().getHostName();
|
||||
return NetUtil.getMultistageReverseProxyIp(ip);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user