From 6b13cb5263efdf65adee18744f8f07e9604fae71 Mon Sep 17 00:00:00 2001
From: Looly
Date: Sat, 4 Apr 2020 00:50:44 +0800
Subject: [PATCH] prepare 5.3.0
---
CHANGELOG.md | 3 +
README.md | 10 +-
bin/version.txt | 2 +-
docs/js/version.js | 2 +-
hutool-all/pom.xml | 2 +-
hutool-aop/pom.xml | 2 +-
hutool-bloomFilter/pom.xml | 2 +-
hutool-bom/pom.xml | 2 +-
hutool-cache/pom.xml | 2 +-
hutool-captcha/pom.xml | 2 +-
hutool-core/pom.xml | 2 +-
.../java/cn/hutool/core/codec/Base64.java | 14 +-
.../main/java/cn/hutool/core/map/BiMap.java | 71 ++++++++++
.../main/java/cn/hutool/core/map/MapUtil.java | 20 +++
.../java/cn/hutool/core/map/TableMap.java | 24 ++--
.../core/map/multi/CollectionValueMap.java | 12 +-
.../hutool/core/map/multi/ListValueMap.java | 4 +-
.../cn/hutool/core/map/multi/SetValueMap.java | 4 +-
.../net}/multipart/MultipartFormData.java | 25 +---
.../MultipartRequestInputStream.java | 39 ++++--
.../core/net}/multipart/UploadFile.java | 49 ++++---
.../core/net}/multipart/UploadFileHeader.java | 2 +-
.../core/net}/multipart/UploadSetting.java | 18 +--
.../core/net/multipart/package-info.java | 7 +
.../java/cn/hutool/core/util/CharsetUtil.java | 13 +-
hutool-cron/pom.xml | 2 +-
hutool-crypto/pom.xml | 2 +-
hutool-db/pom.xml | 2 +-
hutool-dfa/pom.xml | 2 +-
hutool-extra/pom.xml | 2 +-
.../cn/hutool/extra/servlet/ServletUtil.java | 6 +-
.../extra/servlet/multipart/package-info.java | 7 -
hutool-http/pom.xml | 2 +-
.../main/java/cn/hutool/http/ContentType.java | 26 +++-
.../main/java/cn/hutool/http/HttpUtil.java | 50 +++++--
.../cn/hutool/http/server/HttpServerBase.java | 5 +
.../hutool/http/server/HttpServerRequest.java | 120 +++++++++++++----
.../http/server/HttpServerResponse.java | 126 ++++++++++++++++--
.../cn/hutool/http/server/SimpleServer.java | 7 +-
.../hutool/http/server/action/RootAction.java | 62 +++++++++
.../http/server/handler/ActionHandler.java | 5 +-
.../http/server/handler/HandlerUtil.java | 91 -------------
.../http/server/handler/RootHandler.java | 45 -------
.../hutool/http/server/SimpleServerTest.java | 14 +-
.../cn/hutool/http/test/HttpUtilTest.java | 25 ++--
hutool-json/pom.xml | 2 +-
hutool-log/pom.xml | 2 +-
hutool-poi/pom.xml | 2 +-
hutool-script/pom.xml | 2 +-
hutool-setting/pom.xml | 2 +-
hutool-socket/pom.xml | 2 +-
hutool-system/pom.xml | 2 +-
pom.xml | 2 +-
53 files changed, 619 insertions(+), 331 deletions(-)
create mode 100644 hutool-core/src/main/java/cn/hutool/core/map/BiMap.java
rename {hutool-extra/src/main/java/cn/hutool/extra/servlet => hutool-core/src/main/java/cn/hutool/core/net}/multipart/MultipartFormData.java (86%)
rename {hutool-extra/src/main/java/cn/hutool/extra/servlet => hutool-core/src/main/java/cn/hutool/core/net}/multipart/MultipartRequestInputStream.java (84%)
rename {hutool-extra/src/main/java/cn/hutool/extra/servlet => hutool-core/src/main/java/cn/hutool/core/net}/multipart/UploadFile.java (89%)
rename {hutool-extra/src/main/java/cn/hutool/extra/servlet => hutool-core/src/main/java/cn/hutool/core/net}/multipart/UploadFileHeader.java (94%)
rename {hutool-extra/src/main/java/cn/hutool/extra/servlet => hutool-core/src/main/java/cn/hutool/core/net}/multipart/UploadSetting.java (94%)
create mode 100644 hutool-core/src/main/java/cn/hutool/core/net/multipart/package-info.java
delete mode 100644 hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/package-info.java
create mode 100644 hutool-http/src/main/java/cn/hutool/http/server/action/RootAction.java
delete mode 100644 hutool-http/src/main/java/cn/hutool/http/server/handler/HandlerUtil.java
delete mode 100644 hutool-http/src/main/java/cn/hutool/http/server/handler/RootHandler.java
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 80db6fe1e..52348afe1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,9 +18,12 @@
* 【core 】 CollUtil增加toMap方法
* 【core 】 CollUtil和IterUtil废弃一些方法
* 【core 】 添加ValidateObjectInputStream避免对象反序列化漏洞风险
+* 【core 】 添加BiMap
+* 【all 】 cn.hutool.extra.servlet.multipart包迁移到cn.hutool.core.net下
### Bug修复
* 【extra 】 修复SpringUtil使用devtools重启报错问题
+* 【http 】 修复HttpUtil.encodeParams针对无参数URL问题(issue#817@Github)
-------------------------------------------------------------------------------------------------------------
diff --git a/README.md b/README.md
index bf9a22421..1349f9835 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@
-- 主页:https://hutool.cn/ | https://www.hutool.club/ --
- -- QQ群③:555368316 --
+ -- QQ群③:555368316 --
-- QQ群④:718802356 --
@@ -116,21 +116,21 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不
cn.hutool
hutool-all
- 5.2.6
+ 5.3.0
```
### Gradle
```
-compile 'cn.hutool:hutool-all:5.2.6'
+compile 'cn.hutool:hutool-all:5.3.0'
```
### 非Maven项目
点击以下任一链接,下载`hutool-all-X.X.X.jar`即可:
-- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.2.6/)
-- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.2.6/)
+- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.3.0/)
+- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.3.0/)
> 注意
> Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类获工具方法可用。
diff --git a/bin/version.txt b/bin/version.txt
index a944d7e61..03f488b07 100755
--- a/bin/version.txt
+++ b/bin/version.txt
@@ -1 +1 @@
-5.2.6
+5.3.0
diff --git a/docs/js/version.js b/docs/js/version.js
index b5a3cc686..2f0178e29 100644
--- a/docs/js/version.js
+++ b/docs/js/version.js
@@ -1 +1 @@
-var version = '5.2.6'
\ No newline at end of file
+var version = '5.3.0'
\ No newline at end of file
diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml
index 0d5f10848..78044e36e 100644
--- a/hutool-all/pom.xml
+++ b/hutool-all/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-all
diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml
index 3c011fb9a..bb9458001 100644
--- a/hutool-aop/pom.xml
+++ b/hutool-aop/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-aop
diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml
index e7bf57f83..e885cda8f 100644
--- a/hutool-bloomFilter/pom.xml
+++ b/hutool-bloomFilter/pom.xml
@@ -7,7 +7,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-bloomFilter
diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml
index 403ddad61..67a2c345b 100644
--- a/hutool-bom/pom.xml
+++ b/hutool-bom/pom.xml
@@ -7,7 +7,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-bom
diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml
index 008e8704e..82467a4a7 100644
--- a/hutool-cache/pom.xml
+++ b/hutool-cache/pom.xml
@@ -7,7 +7,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-cache
diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml
index 0f9c30525..98c2d9dad 100644
--- a/hutool-captcha/pom.xml
+++ b/hutool-captcha/pom.xml
@@ -7,7 +7,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-captcha
diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml
index 94bd039cc..68a16cf32 100644
--- a/hutool-core/pom.xml
+++ b/hutool-core/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-core
diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/Base64.java b/hutool-core/src/main/java/cn/hutool/core/codec/Base64.java
index d796f882b..979b568c8 100644
--- a/hutool-core/src/main/java/cn/hutool/core/codec/Base64.java
+++ b/hutool-core/src/main/java/cn/hutool/core/codec/Base64.java
@@ -1,14 +1,14 @@
package cn.hutool.core.codec;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.CharsetUtil;
+
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
-import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.util.CharsetUtil;
-
/**
* Base64工具类,提供Base64的编码和解码方案
* base64编码是用64(2的6次方)个ASCII字符来表示256(2的8次方)个ASCII字符,
@@ -72,7 +72,7 @@ public class Base64 {
* @return 被加密后的字符串
*/
public static String encode(CharSequence source, String charset) {
- return Base64Encoder.encode(source, CharsetUtil.charset(charset));
+ return encode(source, CharsetUtil.charset(charset));
}
/**
@@ -84,7 +84,7 @@ public class Base64 {
* @since 3.0.6
*/
public static String encodeUrlSafe(CharSequence source, String charset) {
- return Base64Encoder.encodeUrlSafe(source, CharsetUtil.charset(charset));
+ return encodeUrlSafe(source, CharsetUtil.charset(charset));
}
/**
@@ -272,7 +272,7 @@ public class Base64 {
* @return 被加密后的字符串
*/
public static String decodeStr(CharSequence source, String charset) {
- return Base64Decoder.decodeStr(source, CharsetUtil.charset(charset));
+ return decodeStr(source, CharsetUtil.charset(charset));
}
/**
diff --git a/hutool-core/src/main/java/cn/hutool/core/map/BiMap.java b/hutool-core/src/main/java/cn/hutool/core/map/BiMap.java
new file mode 100644
index 000000000..9680675a6
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/map/BiMap.java
@@ -0,0 +1,71 @@
+package cn.hutool.core.map;
+
+import java.util.Map;
+
+/**
+ * 双向Map
+ * 互换键值对不检查值是否有重复,如果有则后加入的元素替换先加入的元素
+ * 值的顺序在HashMap中不确定,所以谁覆盖谁也不确定,在有序的Map中按照先后顺序覆盖,保留最后的值
+ * 它与TableMap的区别是,BiMap维护两个Map实现高效的正向和反向查找
+ *
+ * @param 键类型
+ * @param 值类型
+ * @since 5.2.6
+ */
+public class BiMap extends MapWrapper {
+
+ private Map inverse;
+
+ /**
+ * 构造
+ *
+ * @param raw 被包装的Map
+ */
+ public BiMap(Map raw) {
+ super(raw);
+ }
+
+ @Override
+ public V put(K key, V value) {
+ if (null != this.inverse) {
+ this.inverse.put(value, key);
+ }
+ return super.put(key, value);
+ }
+
+ @Override
+ public void putAll(Map extends K, ? extends V> m) {
+ super.putAll(m);
+ if (null != this.inverse) {
+ m.forEach((key, value) -> this.inverse.put(value, key));
+ }
+ }
+
+ @Override
+ public void clear() {
+ super.clear();
+ this.inverse = null;
+ }
+
+ /**
+ * 获取反向Map
+ *
+ * @return 反向Map
+ */
+ public Map getInverse() {
+ if (null == this.inverse) {
+ inverse = MapUtil.inverse(getRaw());
+ }
+ return this.inverse;
+ }
+
+ /**
+ * 根据值获得键
+ *
+ * @param value 值
+ * @return 键
+ */
+ public K getKey(V value) {
+ return getInverse().get(value);
+ }
+}
diff --git a/hutool-core/src/main/java/cn/hutool/core/map/MapUtil.java b/hutool-core/src/main/java/cn/hutool/core/map/MapUtil.java
index 39199103b..256b3d346 100644
--- a/hutool-core/src/main/java/cn/hutool/core/map/MapUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/map/MapUtil.java
@@ -681,11 +681,14 @@ public class MapUtil {
/**
* Map的键和值互换
+ * 互换键值对不检查值是否有重复,如果有则后加入的元素替换先加入的元素
+ * 值的顺序在HashMap中不确定,所以谁覆盖谁也不确定,在有序的Map中按照先后顺序覆盖,保留最后的值
*
* @param 键和值类型
* @param map Map对象,键值类型必须一致
* @return 互换后的Map
* @since 3.2.2
+ * @see #inverse(Map)
*/
public static Map reverse(Map map) {
return filter(map, (Editor>) t -> new Entry() {
@@ -707,6 +710,23 @@ public class MapUtil {
});
}
+ /**
+ * Map的键和值互换
+ * 互换键值对不检查值是否有重复,如果有则后加入的元素替换先加入的元素
+ * 值的顺序在HashMap中不确定,所以谁覆盖谁也不确定,在有序的Map中按照先后顺序覆盖,保留最后的值
+ *
+ * @param 键和值类型
+ * @param 键和值类型
+ * @param map Map对象,键值类型必须一致
+ * @return 互换后的Map
+ * @since 5.2.6
+ */
+ public static Map inverse(Map map) {
+ final Map result = createMap(map.getClass());
+ map.forEach((key, value) -> result.put(value, key));
+ return result;
+ }
+
/**
* 排序已有Map,Key有序的Map,使用默认Key排序方式(字母顺序)
*
diff --git a/hutool-core/src/main/java/cn/hutool/core/map/TableMap.java b/hutool-core/src/main/java/cn/hutool/core/map/TableMap.java
index b80ec2ed0..9190bec43 100644
--- a/hutool-core/src/main/java/cn/hutool/core/map/TableMap.java
+++ b/hutool-core/src/main/java/cn/hutool/core/map/TableMap.java
@@ -16,12 +16,13 @@ import java.util.Objects;
import java.util.Set;
/**
- * 可重复键的Map
- *
- * @author looly
+ * 可重复键和值的Map
+ * 通过键值单独建立List方式,使键值对一一对应,实现正向和反向两种查找
+ * 无论是正向还是反向,都是遍历列表查找过程,相比标准的HashMap要慢,数据越多越慢
*
* @param 键类型
* @param 值类型
+ * @author looly
*/
public class TableMap implements Map, Serializable {
private static final long serialVersionUID = 1L;
@@ -31,7 +32,7 @@ public class TableMap implements Map, Serializable {
/**
* 构造
- *
+ *
* @param size 初始容量
*/
public TableMap(int size) {
@@ -41,8 +42,8 @@ public class TableMap implements Map, Serializable {
/**
* 构造
- *
- * @param keys 键列表
+ *
+ * @param keys 键列表
* @param values 值列表
*/
public TableMap(K[] keys, V[] values) {
@@ -89,10 +90,10 @@ public class TableMap implements Map, Serializable {
* @return 值列表
* @since 5.2.5
*/
- public List getValues(K key){
+ public List getValues(K key) {
return CollUtil.getAny(
this.values,
- ListUtil.indexOfAll(this.keys, (ele)-> ObjectUtil.equal(ele, key))
+ ListUtil.indexOfAll(this.keys, (ele) -> ObjectUtil.equal(ele, key))
);
}
@@ -103,10 +104,10 @@ public class TableMap implements Map, Serializable {
* @return 值列表
* @since 5.2.5
*/
- public List getKeys(V value){
+ public List getKeys(V value) {
return CollUtil.getAny(
this.keys,
- ListUtil.indexOfAll(this.values, (ele)-> ObjectUtil.equal(ele, value))
+ ListUtil.indexOfAll(this.values, (ele) -> ObjectUtil.equal(ele, value))
);
}
@@ -189,12 +190,13 @@ public class TableMap implements Map, Serializable {
public V setValue(V value) {
throw new UnsupportedOperationException("setValue not supported.");
}
+
@Override
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
- Map.Entry,?> e = (Map.Entry,?>)o;
+ Map.Entry, ?> e = (Map.Entry, ?>) o;
return Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue());
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/map/multi/CollectionValueMap.java b/hutool-core/src/main/java/cn/hutool/core/map/multi/CollectionValueMap.java
index dab043fd2..64d1a47fe 100644
--- a/hutool-core/src/main/java/cn/hutool/core/map/multi/CollectionValueMap.java
+++ b/hutool-core/src/main/java/cn/hutool/core/map/multi/CollectionValueMap.java
@@ -1,12 +1,12 @@
package cn.hutool.core.map.multi;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.map.MapWrapper;
+
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.map.MapWrapper;
-
/**
* 值作为集合的Map实现,通过调用putValue可以在相同key时加入多个值,多个值用集合表示
*
@@ -67,7 +67,7 @@ public abstract class CollectionValueMap extends MapWrapper>(initialCapacity, loadFactor));
+ super(new HashMap<>(initialCapacity, loadFactor));
}
// ------------------------------------------------------------------------- Constructor end
@@ -81,7 +81,7 @@ public abstract class CollectionValueMap extends MapWrapper collection = this.get(key);
if (null == collection) {
- collection = createCollction();
+ collection = createCollection();
this.put(key, collection);
}
collection.add(value);
@@ -105,5 +105,5 @@ public abstract class CollectionValueMap extends MapWrapper createCollction();
+ protected abstract Collection createCollection();
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/map/multi/ListValueMap.java b/hutool-core/src/main/java/cn/hutool/core/map/multi/ListValueMap.java
index 72b705bbd..b7e908353 100644
--- a/hutool-core/src/main/java/cn/hutool/core/map/multi/ListValueMap.java
+++ b/hutool-core/src/main/java/cn/hutool/core/map/multi/ListValueMap.java
@@ -62,7 +62,7 @@ public class ListValueMap extends CollectionValueMap {
* @param loadFactor 加载因子
*/
public ListValueMap(int initialCapacity, float loadFactor) {
- super(new HashMap>(initialCapacity, loadFactor));
+ super(new HashMap<>(initialCapacity, loadFactor));
}
// ------------------------------------------------------------------------- Constructor end
@@ -72,7 +72,7 @@ public class ListValueMap extends CollectionValueMap {
}
@Override
- protected Collection createCollction() {
+ protected Collection createCollection() {
return new ArrayList<>(DEFAULT_COLLCTION_INITIAL_CAPACITY);
}
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/map/multi/SetValueMap.java b/hutool-core/src/main/java/cn/hutool/core/map/multi/SetValueMap.java
index 52efdc4dc..a1e814bb4 100644
--- a/hutool-core/src/main/java/cn/hutool/core/map/multi/SetValueMap.java
+++ b/hutool-core/src/main/java/cn/hutool/core/map/multi/SetValueMap.java
@@ -62,7 +62,7 @@ public class SetValueMap extends CollectionValueMap {
* @param loadFactor 加载因子
*/
public SetValueMap(int initialCapacity, float loadFactor) {
- super(new HashMap>(initialCapacity, loadFactor));
+ super(new HashMap<>(initialCapacity, loadFactor));
}
// ------------------------------------------------------------------------- Constructor end
@@ -72,7 +72,7 @@ public class SetValueMap extends CollectionValueMap {
}
@Override
- protected Collection createCollction() {
+ protected Collection createCollection() {
return new LinkedHashSet<>(DEFAULT_COLLCTION_INITIAL_CAPACITY);
}
}
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/MultipartFormData.java b/hutool-core/src/main/java/cn/hutool/core/net/multipart/MultipartFormData.java
similarity index 86%
rename from hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/MultipartFormData.java
rename to hutool-core/src/main/java/cn/hutool/core/net/multipart/MultipartFormData.java
index a7e32fe57..45f003980 100644
--- a/hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/MultipartFormData.java
+++ b/hutool-core/src/main/java/cn/hutool/core/net/multipart/MultipartFormData.java
@@ -1,17 +1,16 @@
-package cn.hutool.extra.servlet.multipart;
+package cn.hutool.core.net.multipart;
+
+import cn.hutool.core.util.ArrayUtil;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.charset.Charset;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
-import javax.servlet.ServletRequest;
-
-import cn.hutool.core.util.ArrayUtil;
-
/**
* HttpRequest解析器
* 来自Jodd
@@ -21,9 +20,9 @@ import cn.hutool.core.util.ArrayUtil;
public class MultipartFormData {
/** 请求参数 */
- private Map requestParameters = new HashMap();
+ private Map requestParameters = new HashMap<>();
/** 请求文件 */
- private Map requestFiles = new HashMap();
+ private Map requestFiles = new HashMap<>();
/** 是否解析完毕 */
private boolean loaded;
@@ -48,16 +47,6 @@ public class MultipartFormData {
}
// --------------------------------------------------------------------- Constructor end
- /**
- * 解析上传文件和表单数据
- *
- * @param request Http请求
- * @throws IOException IO异常
- */
- public void parseRequest(ServletRequest request) throws IOException {
- parseRequestStream(request.getInputStream(), request.getCharacterEncoding());
- }
-
/**
* 提取上传的文件和表单数据
*
@@ -65,7 +54,7 @@ public class MultipartFormData {
* @param charset 编码
* @throws IOException IO异常
*/
- public void parseRequestStream(InputStream inputStream, String charset) throws IOException {
+ public void parseRequestStream(InputStream inputStream, Charset charset) throws IOException {
setLoaded();
MultipartRequestInputStream input = new MultipartRequestInputStream(inputStream);
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/MultipartRequestInputStream.java b/hutool-core/src/main/java/cn/hutool/core/net/multipart/MultipartRequestInputStream.java
similarity index 84%
rename from hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/MultipartRequestInputStream.java
rename to hutool-core/src/main/java/cn/hutool/core/net/multipart/MultipartRequestInputStream.java
index 65b35b648..8dc5df6b0 100644
--- a/hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/MultipartRequestInputStream.java
+++ b/hutool-core/src/main/java/cn/hutool/core/net/multipart/MultipartRequestInputStream.java
@@ -1,15 +1,16 @@
-package cn.hutool.extra.servlet.multipart;
+package cn.hutool.core.net.multipart;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.nio.charset.Charset;
/**
* Http请求解析流,提供了专门针对带文件的form表单的解析
* 来自Jodd
- *
+ *
* @author jodd.org
*/
public class MultipartRequestInputStream extends BufferedInputStream {
@@ -20,7 +21,7 @@ public class MultipartRequestInputStream extends BufferedInputStream {
/**
* 读取byte字节流,在末尾抛出异常
- *
+ *
* @return byte
* @throws IOException 读取异常
*/
@@ -34,7 +35,7 @@ public class MultipartRequestInputStream extends BufferedInputStream {
/**
* 跳过指定位数的 bytes.
- *
+ *
* @param i 跳过的byte数
* @throws IOException IO异常
*/
@@ -47,12 +48,14 @@ public class MultipartRequestInputStream extends BufferedInputStream {
// ---------------------------------------------------------------- boundary
- /** part部分边界 */
+ /**
+ * part部分边界
+ */
protected byte[] boundary;
/**
* 输入流中读取边界
- *
+ *
* @return 边界
* @throws IOException 读取异常
*/
@@ -60,6 +63,7 @@ public class MultipartRequestInputStream extends BufferedInputStream {
ByteArrayOutputStream boundaryOutput = new ByteArrayOutputStream(1024);
byte b;
// skip optional whitespaces
+ //noinspection StatementWithEmptyBody
while ((b = readByte()) <= ' ') {
}
boundaryOutput.write(b);
@@ -89,12 +93,12 @@ public class MultipartRequestInputStream extends BufferedInputStream {
/**
* 从流中读取文件头部信息, 如果达到末尾则返回null
- *
+ *
* @param encoding 字符集
* @return 头部信息, 如果达到末尾则返回null
* @throws IOException 读取异常
*/
- public UploadFileHeader readDataHeader(String encoding) throws IOException {
+ public UploadFileHeader readDataHeader(Charset encoding) throws IOException {
String dataHeader = readDataHeaderString(encoding);
if (dataHeader != null) {
lastHeader = new UploadFileHeader(dataHeader);
@@ -104,7 +108,14 @@ public class MultipartRequestInputStream extends BufferedInputStream {
return lastHeader;
}
- protected String readDataHeaderString(String encoding) throws IOException {
+ /**
+ * 读取数据头信息字符串
+ *
+ * @param charset 编码
+ * @return 数据头信息字符串
+ * @throws IOException IO异常
+ */
+ protected String readDataHeaderString(Charset charset) throws IOException {
ByteArrayOutputStream data = new ByteArrayOutputStream();
byte b;
while (true) {
@@ -128,13 +139,13 @@ public class MultipartRequestInputStream extends BufferedInputStream {
data.write(b);
}
skipBytes(3);
- return encoding == null ? data.toString() : data.toString(encoding);
+ return charset == null ? data.toString() : data.toString(charset.name());
}
// ---------------------------------------------------------------- copy
/**
* 全部字节流复制到out
- *
+ *
* @param out 输出流
* @return 复制的字节数
* @throws IOException 读取异常
@@ -154,8 +165,8 @@ public class MultipartRequestInputStream extends BufferedInputStream {
/**
* 复制字节流到out, 大于maxBytes或者文件末尾停止
- *
- * @param out 输出流
+ *
+ * @param out 输出流
* @param limit 最大字节数
* @return 复制的字节数
* @throws IOException 读取异常
@@ -178,7 +189,7 @@ public class MultipartRequestInputStream extends BufferedInputStream {
/**
* 跳过边界表示
- *
+ *
* @return 跳过的字节数
* @throws IOException 读取异常
*/
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/UploadFile.java b/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFile.java
similarity index 89%
rename from hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/UploadFile.java
rename to hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFile.java
index 43f4f3884..5e0386603 100644
--- a/hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/UploadFile.java
+++ b/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFile.java
@@ -1,4 +1,8 @@
-package cn.hutool.extra.servlet.multipart;
+package cn.hutool.core.net.multipart;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.StrUtil;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@@ -10,27 +14,18 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.log.Log;
-import cn.hutool.log.LogFactory;
-
/**
* 上传的文件对象
- *
+ *
* @author xiaoleilu
- *
*/
public class UploadFile {
- private static Log log = LogFactory.get();
-
private static final String TMP_FILE_PREFIX = "hutool-";
private static final String TMP_FILE_SUFFIX = ".upload.tmp";
private UploadFileHeader header;
private UploadSetting setting;
-
+
private int size = -1;
// 文件流(小文件位于内存中)
@@ -40,8 +35,8 @@ public class UploadFile {
/**
* 构造
- *
- * @param header 头部信息
+ *
+ * @param header 头部信息
* @param setting 上传设置
*/
public UploadFile(UploadFileHeader header, UploadSetting setting) {
@@ -56,6 +51,7 @@ public class UploadFile {
*/
public void delete() {
if (tempFile != null) {
+ //noinspection ResultOfMethodCallIgnored
tempFile.delete();
}
if (data != null) {
@@ -66,17 +62,18 @@ public class UploadFile {
/**
* 将上传的文件写入指定的目标文件路径,自动创建文件
* 写入后原临时文件会被删除
+ *
* @param destPath 目标文件路径
* @return 目标文件
* @throws IOException IO异常
*/
public File write(String destPath) throws IOException {
- if(data != null || tempFile != null) {
+ if (data != null || tempFile != null) {
return write(FileUtil.touch(destPath));
}
return null;
}
-
+
/**
* 将上传的文件写入目标文件
* 写入后原临时文件会被删除
@@ -87,7 +84,7 @@ public class UploadFile {
*/
public File write(File destination) throws IOException {
assertValid();
-
+
if (destination.isDirectory() == true) {
destination = new File(destination, this.header.getFileName());
}
@@ -101,14 +98,14 @@ public class UploadFile {
}
return destination;
}
-
+
/**
* @return 获得文件字节流
* @throws IOException IO异常
*/
public byte[] getFileContent() throws IOException {
assertValid();
-
+
if (data != null) {
return data;
}
@@ -124,7 +121,7 @@ public class UploadFile {
*/
public InputStream getFileInputStream() throws IOException {
assertValid();
-
+
if (data != null) {
return new BufferedInputStream(new ByteArrayInputStream(data));
}
@@ -174,9 +171,10 @@ public class UploadFile {
}
// ---------------------------------------------------------------- process
+
/**
* 处理上传表单流,提取出文件
- *
+ *
* @param input 上传表单的流
* @return 是否成功
* @throws IOException IO异常
@@ -184,7 +182,6 @@ public class UploadFile {
protected boolean processStream(MultipartRequestInputStream input) throws IOException {
if (!isAllowedExtension()) {
// 非允许的扩展名
- log.debug("Forbidden uploaded file [{}]", this.getFileName());
size = input.skipToBoundary();
return false;
}
@@ -220,9 +217,9 @@ public class UploadFile {
size += input.copy(out, maxFileSize - size + 1); // one more byte to detect larger files
if (size > maxFileSize) {
// 超出上传大小限制
+ //noinspection ResultOfMethodCallIgnored
tempFile.delete();
tempFile = null;
- log.debug("Upload file [{}] too big, file size > [{}]", this.getFileName(), maxFileSize);
input.skipToBoundary();
return false;
}
@@ -236,6 +233,7 @@ public class UploadFile {
}
// ---------------------------------------------------------------------------- Private method start
+
/**
* @return 是否为允许的扩展名
*/
@@ -257,13 +255,14 @@ public class UploadFile {
// 未匹配到扩展名,如果为允许列表,返回false, 否则true
return !isAllow;
}
-
+
/**
* 断言是否文件流可用
+ *
* @throws IOException IO异常
*/
private void assertValid() throws IOException {
- if(! isUploaded()) {
+ if (!isUploaded()) {
throw new IOException(StrUtil.format("File [{}] upload fail", getFileName()));
}
}
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/UploadFileHeader.java b/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFileHeader.java
similarity index 94%
rename from hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/UploadFileHeader.java
rename to hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFileHeader.java
index b8b1a86ef..5c1770d9b 100644
--- a/hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/UploadFileHeader.java
+++ b/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFileHeader.java
@@ -1,4 +1,4 @@
-package cn.hutool.extra.servlet.multipart;
+package cn.hutool.core.net.multipart;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/UploadSetting.java b/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadSetting.java
similarity index 94%
rename from hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/UploadSetting.java
rename to hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadSetting.java
index c75116c65..08e4dae05 100644
--- a/hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/UploadSetting.java
+++ b/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadSetting.java
@@ -1,4 +1,4 @@
-package cn.hutool.extra.servlet.multipart;
+package cn.hutool.core.net.multipart;
import cn.hutool.core.util.URLUtil;
import cn.hutool.log.Log;
@@ -8,7 +8,7 @@ import java.net.URL;
/**
* 上传文件设定文件
- *
+ *
* @author xiaoleilu
*
*/
@@ -42,7 +42,7 @@ public class UploadSetting {
/**
* 设定最大文件大小,-1表示无限制
- *
+ *
* @param maxFileSize 最大文件大小
*/
public void setMaxFileSize(int maxFileSize) {
@@ -59,7 +59,7 @@ public class UploadSetting {
/**
* 设定文件保存到内存的边界
* 如果文件大小小于这个边界,将保存于内存中,否则保存至临时目录中
- *
+ *
* @param memoryThreshold 文件保存到内存的边界
*/
public void setMemoryThreshold(int memoryThreshold) {
@@ -75,7 +75,7 @@ public class UploadSetting {
/**
* 设定上传文件的临时目录,null表示使用系统临时目录
- *
+ *
* @param tmpUploadPath 临时目录,绝对路径
*/
public void setTmpUploadPath(String tmpUploadPath) {
@@ -92,7 +92,7 @@ public class UploadSetting {
/**
* 设定文件扩展名限定里列表
* 禁止列表还是允许列表取决于isAllowFileExts
- *
+ *
* @param fileExts 文件扩展名列表
*/
public void setFileExts(String[] fileExts) {
@@ -101,7 +101,7 @@ public class UploadSetting {
/**
* 是否允许文件扩展名
- *
+ *
* @return 若true表示只允许列表里的扩展名,否则是禁止列表里的扩展名
*/
public boolean isAllowFileExts() {
@@ -110,7 +110,7 @@ public class UploadSetting {
/**
* 设定是否允许扩展名
- *
+ *
* @param isAllowFileExts 若true表示只允许列表里的扩展名,否则是禁止列表里的扩展名
*/
public void setAllowFileExts(boolean isAllowFileExts) {
@@ -128,7 +128,7 @@ public class UploadSetting {
/**
* 加载全局设定
- *
+ *
* @param settingPath 设定文件路径,相对Classpath
*/
synchronized public void load(String settingPath) {
diff --git a/hutool-core/src/main/java/cn/hutool/core/net/multipart/package-info.java b/hutool-core/src/main/java/cn/hutool/core/net/multipart/package-info.java
new file mode 100644
index 000000000..1056d3767
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/net/multipart/package-info.java
@@ -0,0 +1,7 @@
+/**
+ * 文件上传封装
+ *
+ * @author looly
+ *
+ */
+package cn.hutool.core.net.multipart;
\ No newline at end of file
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/CharsetUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/CharsetUtil.java
index c19de5d01..c6478af57 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/CharsetUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/CharsetUtil.java
@@ -62,6 +62,17 @@ public class CharsetUtil {
return StrUtil.isBlank(charsetName) ? Charset.defaultCharset() : Charset.forName(charsetName);
}
+ /**
+ * 解析字符串编码为Charset对象,解析失败返回系统默认编码
+ *
+ * @param charsetName 字符集,为空则返回默认字符集
+ * @return Charset
+ * @since 5.2.6
+ */
+ public static Charset parse(String charsetName) {
+ return parse(charsetName, Charset.defaultCharset());
+ }
+
/**
* 解析字符串编码为Charset对象,解析失败返回默认编码
*
@@ -70,7 +81,7 @@ public class CharsetUtil {
* @return Charset
* @since 5.2.6
*/
- public static Charset parse(String charsetName, Charset defaultCharset) throws UnsupportedCharsetException {
+ public static Charset parse(String charsetName, Charset defaultCharset) {
if (StrUtil.isBlank(charsetName)) {
return defaultCharset;
}
diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml
index d7e2134a8..549c8c6da 100644
--- a/hutool-cron/pom.xml
+++ b/hutool-cron/pom.xml
@@ -7,7 +7,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-cron
diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml
index ccdd83b22..35777df68 100644
--- a/hutool-crypto/pom.xml
+++ b/hutool-crypto/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-crypto
diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml
index 9860ff4a6..c378809a7 100644
--- a/hutool-db/pom.xml
+++ b/hutool-db/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-db
diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml
index 82e7f9473..eaa01abd2 100644
--- a/hutool-dfa/pom.xml
+++ b/hutool-dfa/pom.xml
@@ -7,7 +7,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-dfa
diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml
index 8f42d3959..0ab3cece5 100644
--- a/hutool-extra/pom.xml
+++ b/hutool-extra/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-extra
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/servlet/ServletUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/servlet/ServletUtil.java
index f91530be4..7004f45f3 100644
--- a/hutool-extra/src/main/java/cn/hutool/extra/servlet/ServletUtil.java
+++ b/hutool-extra/src/main/java/cn/hutool/extra/servlet/ServletUtil.java
@@ -11,14 +11,14 @@ 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.net.multipart.MultipartFormData;
+import cn.hutool.core.net.multipart.UploadSetting;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
-import cn.hutool.extra.servlet.multipart.MultipartFormData;
-import cn.hutool.extra.servlet.multipart.UploadSetting;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
@@ -265,7 +265,7 @@ public class ServletUtil {
public static MultipartFormData getMultipart(ServletRequest request, UploadSetting uploadSetting) throws IORuntimeException {
final MultipartFormData formData = new MultipartFormData(uploadSetting);
try {
- formData.parseRequest(request);
+ formData.parseRequestStream(request.getInputStream(), request.getCharacterEncoding());
} catch (IOException e) {
throw new IORuntimeException(e);
}
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/package-info.java b/hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/package-info.java
deleted file mode 100644
index 0328d88f6..000000000
--- a/hutool-extra/src/main/java/cn/hutool/extra/servlet/multipart/package-info.java
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * 基于Servlet的文件上传封装
- *
- * @author looly
- *
- */
-package cn.hutool.extra.servlet.multipart;
\ No newline at end of file
diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml
index 0086696a9..c0925f434 100644
--- a/hutool-http/pom.xml
+++ b/hutool-http/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-http
diff --git a/hutool-http/src/main/java/cn/hutool/http/ContentType.java b/hutool-http/src/main/java/cn/hutool/http/ContentType.java
index 759cd7d92..b7398cd39 100644
--- a/hutool-http/src/main/java/cn/hutool/http/ContentType.java
+++ b/hutool-http/src/main/java/cn/hutool/http/ContentType.java
@@ -28,10 +28,18 @@ public enum ContentType {
* Rest请求XML编码
*/
XML("application/xml"),
+ /**
+ * text/plain编码
+ */
+ TEXT_PLAIN("text/plain"),
/**
* Rest请求text/xml编码
*/
- TEXT_XML("text/xml");
+ TEXT_XML("text/xml"),
+ /**
+ * text/html编码
+ */
+ TEXT_HTML("text/html");
private String value;
@@ -39,9 +47,19 @@ public enum ContentType {
this.value = value;
}
+ /**
+ * 获取value值
+ *
+ * @return value值
+ * @since 5.2.6
+ */
+ public String getValue() {
+ return value;
+ }
+
@Override
public String toString() {
- return value;
+ return getValue();
}
/**
@@ -62,7 +80,7 @@ public enum ContentType {
* @since 4.1.5
*/
public static boolean isDefault(String contentType) {
- return null == contentType || isFormUrlEncoed(contentType);
+ return null == contentType || isFormUrlEncode(contentType);
}
/**
@@ -71,7 +89,7 @@ public enum ContentType {
* @param contentType 内容类型
* @return 是否为application/x-www-form-urlencoded
*/
- public static boolean isFormUrlEncoed(String contentType) {
+ public static boolean isFormUrlEncode(String contentType) {
return StrUtil.startWithIgnoreCase(contentType, FORM_URLENCODED.toString());
}
diff --git a/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java b/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java
index 264e9c233..07bb0b8af 100644
--- a/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java
+++ b/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java
@@ -2,6 +2,7 @@ package cn.hutool.http;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FastByteArrayOutputStream;
import cn.hutool.core.io.FileUtil;
@@ -416,7 +417,7 @@ public class HttpUtil {
if (value instanceof Iterable) {
value = CollUtil.join((Iterable>) value, ",");
} else if (value instanceof Iterator) {
- value = CollUtil.join((Iterator>) value, ",");
+ value = IterUtil.join((Iterator>) value, ",");
}
valueStr = Convert.toStr(value);
if (StrUtil.isNotEmpty(key)) {
@@ -435,30 +436,33 @@ public class HttpUtil {
*
* 注意,此方法只能标准化整个URL,并不适合于单独编码参数值
*
- * @param paramsStr url参数,可以包含url本身
+ * @param urlWithParams url和参数,可以包含url本身,也可以单独参数
* @param charset 编码
* @return 编码后的url和参数
* @since 4.0.1
*/
- public static String encodeParams(String paramsStr, Charset charset) {
- if (StrUtil.isBlank(paramsStr)) {
+ public static String encodeParams(String urlWithParams, Charset charset) {
+ if (StrUtil.isBlank(urlWithParams)) {
return StrUtil.EMPTY;
}
String urlPart = null; // url部分,不包括问号
String paramPart; // 参数部分
- int pathEndPos = paramsStr.indexOf('?');
+ final int pathEndPos = urlWithParams.indexOf('?');
if (pathEndPos > -1) {
// url + 参数
- urlPart = StrUtil.subPre(paramsStr, pathEndPos);
- paramPart = StrUtil.subSuf(paramsStr, pathEndPos + 1);
+ urlPart = StrUtil.subPre(urlWithParams, pathEndPos);
+ paramPart = StrUtil.subSuf(urlWithParams, pathEndPos + 1);
if (StrUtil.isBlank(paramPart)) {
// 无参数,返回url
return urlPart;
}
- } else {
- // 无URL
- paramPart = paramsStr;
+ } else if(false == StrUtil.contains(urlWithParams, '=')){
+ // 无参数的URL
+ return urlWithParams;
+ }else {
+ // 无URL的参数
+ paramPart = urlWithParams;
}
paramPart = normalizeParams(paramPart, charset);
@@ -534,6 +538,18 @@ public class HttpUtil {
* @since 4.0.2
*/
public static HashMap decodeParamMap(String paramsStr, String charset) {
+ return decodeParamMap(paramsStr, CharsetUtil.charset(charset));
+ }
+
+ /**
+ * 将URL参数解析为Map(也可以解析Post中的键值对参数)
+ *
+ * @param paramsStr 参数字符串(或者带参数的Path)
+ * @param charset 字符集
+ * @return 参数Map
+ * @since 5.2.6
+ */
+ public static HashMap decodeParamMap(String paramsStr, Charset charset) {
final Map> paramsMap = decodeParams(paramsStr, charset);
final HashMap result = MapUtil.newHashMap(paramsMap.size());
List valueList;
@@ -552,6 +568,18 @@ public class HttpUtil {
* @return 参数Map
*/
public static Map> decodeParams(String paramsStr, String charset) {
+ return decodeParams(paramsStr, CharsetUtil.charset(charset));
+ }
+
+ /**
+ * 将URL参数解析为Map(也可以解析Post中的键值对参数)
+ *
+ * @param paramsStr 参数字符串(或者带参数的Path)
+ * @param charset 字符集
+ * @return 参数Map
+ * @since 5.2.6
+ */
+ public static Map> decodeParams(String paramsStr, Charset charset) {
if (StrUtil.isBlank(paramsStr)) {
return Collections.emptyMap();
}
@@ -811,7 +839,7 @@ public class HttpUtil {
* @param value value
* @param charset 编码
*/
- private static void addParam(Map> params, String name, String value, String charset) {
+ private static void addParam(Map> params, String name, String value, Charset charset) {
name = URLUtil.decode(name, charset);
value = URLUtil.decode(value, charset);
final List values = params.computeIfAbsent(name, k -> new ArrayList<>(1));
diff --git a/hutool-http/src/main/java/cn/hutool/http/server/HttpServerBase.java b/hutool-http/src/main/java/cn/hutool/http/server/HttpServerBase.java
index 5cf8ecb81..ff146ff89 100644
--- a/hutool-http/src/main/java/cn/hutool/http/server/HttpServerBase.java
+++ b/hutool-http/src/main/java/cn/hutool/http/server/HttpServerBase.java
@@ -1,7 +1,10 @@
package cn.hutool.http.server;
+import cn.hutool.core.util.CharsetUtil;
import com.sun.net.httpserver.HttpExchange;
+import java.nio.charset.Charset;
+
/**
* HttpServer公用对象,提供HttpExchange包装和公用方法
*
@@ -10,6 +13,8 @@ import com.sun.net.httpserver.HttpExchange;
*/
public class HttpServerBase {
+ final static Charset DEFAULT_CHARSET = CharsetUtil.CHARSET_UTF_8;
+
final HttpExchange httpExchange;
/**
diff --git a/hutool-http/src/main/java/cn/hutool/http/server/HttpServerRequest.java b/hutool-http/src/main/java/cn/hutool/http/server/HttpServerRequest.java
index 1239b18cb..f7b14d5fd 100644
--- a/hutool-http/src/main/java/cn/hutool/http/server/HttpServerRequest.java
+++ b/hutool-http/src/main/java/cn/hutool/http/server/HttpServerRequest.java
@@ -1,9 +1,13 @@
package cn.hutool.http.server;
import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.CaseInsensitiveMap;
+import cn.hutool.core.map.multi.ListValueMap;
import cn.hutool.core.net.NetUtil;
+import cn.hutool.core.net.multipart.MultipartFormData;
+import cn.hutool.core.net.multipart.UploadSetting;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
@@ -15,6 +19,7 @@ import cn.hutool.http.useragent.UserAgentUtil;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
+import java.io.IOException;
import java.io.InputStream;
import java.net.HttpCookie;
import java.net.URI;
@@ -32,6 +37,9 @@ import java.util.Map;
public class HttpServerRequest extends HttpServerBase {
private Map cookieCache;
+ private ListValueMap paramsCache;
+ private Charset charsetCache;
+ private byte[] bodyCache;
/**
* 构造
@@ -159,9 +167,13 @@ public class HttpServerRequest extends HttpServerBase {
* @return 编码,默认UTF-8
*/
public Charset getCharset() {
- final String contentType = getContentType();
- final String charsetStr = HttpUtil.getCharset(contentType);
- return CharsetUtil.parse(charsetStr, CharsetUtil.CHARSET_UTF_8);
+ if(null == this.charsetCache){
+ final String contentType = getContentType();
+ final String charsetStr = HttpUtil.getCharset(contentType);
+ this.charsetCache = CharsetUtil.parse(charsetStr, DEFAULT_CHARSET);
+ }
+
+ return this.charsetCache;
}
/**
@@ -226,12 +238,20 @@ public class HttpServerRequest extends HttpServerBase {
}
/**
- * 获取请求体的流,流中可以读取请求内容,包括请求表单数据或文件上传数据
+ * 是否为Multipart类型表单,此类型表单用于文件上传
*
- * @return 流
+ * @return 是否为Multipart类型表单,此类型表单用于文件上传
*/
- public InputStream getBodyStream() {
- return this.httpExchange.getRequestBody();
+ public boolean isMultipart() {
+ if (false == isPostMethod()) {
+ return false;
+ }
+
+ final String contentType = getContentType();
+ if (StrUtil.isBlank(contentType)) {
+ return false;
+ }
+ return contentType.toLowerCase().startsWith("multipart/");
}
/**
@@ -251,31 +271,49 @@ public class HttpServerRequest extends HttpServerBase {
* @return 请求
*/
public String getBody(Charset charset) {
- InputStream in = null;
- try {
- in = getBodyStream();
- return IoUtil.read(in, charset);
- } finally {
- IoUtil.close(in);
- }
+ return StrUtil.str(getBodyBytes(), charset);
}
/**
- * 是否为Multipart类型表单,此类型表单用于文件上传
+ * 获取body的bytes数组
*
- * @return 是否为Multipart类型表单,此类型表单用于文件上传
+ * @return body的bytes数组
*/
- public boolean isMultipart() {
- if (false == isPostMethod()) {
- return false;
+ public byte[] getBodyBytes(){
+ if(null == this.bodyCache){
+ this.bodyCache = IoUtil.readBytes(getBodyStream(), true);
+ }
+ return this.bodyCache;
+ }
+
+ /**
+ * 获取请求体的流,流中可以读取请求内容,包括请求表单数据或文件上传数据
+ *
+ * @return 流
+ */
+ public InputStream getBodyStream() {
+ return this.httpExchange.getRequestBody();
+ }
+
+ public ListValueMap getParams() {
+ if (null == this.paramsCache) {
+ this.paramsCache = new ListValueMap<>();
+ final Charset charset = getCharset();
+
+ //解析URL中的参数
+ final String query = getQuery();
+ if(StrUtil.isNotBlank(query)){
+ this.paramsCache.putAll(HttpUtil.decodeParams(query, charset));
+ }
+
+ // 解析body中的参数
+ final String body = getBody();
+ if(StrUtil.isNotBlank(body)){
+ this.paramsCache.putAll(HttpUtil.decodeParams(body, charset));
+ }
}
- final String contentType = getContentType();
- if (StrUtil.isBlank(contentType)) {
- return false;
- }
-
- return contentType.toLowerCase().startsWith("multipart/");
+ return this.paramsCache;
}
/**
@@ -332,4 +370,36 @@ public class HttpServerRequest extends HttpServerBase {
ip = this.httpExchange.getRemoteAddress().getHostName();
return NetUtil.getMultistageReverseProxyIp(ip);
}
+
+ /**
+ * 获得MultiPart表单内容,多用于获得上传的文件 在同一次请求中,此方法只能被执行一次!
+ *
+ * @return MultipartFormData
+ * @throws IORuntimeException IO异常
+ * @since 5.3.0
+ */
+ public MultipartFormData getMultipart() throws IORuntimeException {
+ return getMultipart(new UploadSetting());
+ }
+
+ /**
+ * 获得multipart/form-data 表单内容
+ * 包括文件和普通表单数据
+ * 在同一次请求中,此方法只能被执行一次!
+ *
+ * @param uploadSetting 上传文件的设定,包括最大文件大小、保存在内存的边界大小、临时目录、扩展名限定等
+ * @return MultiPart表单
+ * @throws IORuntimeException IO异常
+ * @since 5.3.0
+ */
+ public MultipartFormData getMultipart(UploadSetting uploadSetting) throws IORuntimeException {
+ final MultipartFormData formData = new MultipartFormData(uploadSetting);
+ try {
+ formData.parseRequestStream(getBodyStream(), getCharset());
+ } catch (IOException e) {
+ throw new IORuntimeException(e);
+ }
+
+ return formData;
+ }
}
diff --git a/hutool-http/src/main/java/cn/hutool/http/server/HttpServerResponse.java b/hutool-http/src/main/java/cn/hutool/http/server/HttpServerResponse.java
index 879c30475..85966760a 100644
--- a/hutool-http/src/main/java/cn/hutool/http/server/HttpServerResponse.java
+++ b/hutool-http/src/main/java/cn/hutool/http/server/HttpServerResponse.java
@@ -3,12 +3,14 @@ package cn.hutool.http.server;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
+import cn.hutool.http.ContentType;
import cn.hutool.http.Header;
+import cn.hutool.http.HttpStatus;
import cn.hutool.http.HttpUtil;
+
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
@@ -18,6 +20,8 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
@@ -28,6 +32,10 @@ import java.util.Map;
public class HttpServerResponse extends HttpServerBase {
private Charset charset;
+ /**
+ * 是否已经发送了Http状态码,如果没有,提前写出状态码
+ */
+ private boolean isSendCode;
/**
* 构造
@@ -48,6 +56,38 @@ public class HttpServerResponse extends HttpServerBase {
return send(httpStatusCode, 0);
}
+ /**
+ * 发送成功状态码
+ *
+ * @return this
+ */
+ public HttpServerResponse sendOk() {
+ return send(HttpStatus.HTTP_OK);
+ }
+
+ /**
+ * 发送404错误页
+ *
+ * @param content 错误页页面内容,默认text/html类型
+ * @return this
+ */
+ public HttpServerResponse send404(String content) {
+ return sendError(HttpStatus.HTTP_NOT_FOUND, content);
+ }
+
+ /**
+ * 发送错误页
+ *
+ * @param errorCode HTTP错误状态码,见HttpStatus
+ * @param content 错误页页面内容,默认text/html类型
+ * @return this
+ */
+ public HttpServerResponse sendError(int errorCode, String content) {
+ send(errorCode);
+ setContentType(ContentType.TEXT_HTML.toString());
+ return write(content);
+ }
+
/**
* 发送HTTP状态码
*
@@ -56,11 +96,17 @@ public class HttpServerResponse extends HttpServerBase {
* @return this
*/
public HttpServerResponse send(int httpStatusCode, long bodyLength) {
+ if (this.isSendCode) {
+ throw new IORuntimeException("Http status code has been send!");
+ }
+
try {
this.httpExchange.sendResponseHeaders(httpStatusCode, bodyLength);
} catch (IOException e) {
throw new IORuntimeException(e);
}
+
+ this.isSendCode = true;
return this;
}
@@ -70,6 +116,9 @@ public class HttpServerResponse extends HttpServerBase {
* @return 响应头
*/
public Headers getHeaders() {
+ if (false == this.isSendCode) {
+ sendOk();
+ }
return this.httpExchange.getResponseHeaders();
}
@@ -141,7 +190,7 @@ public class HttpServerResponse extends HttpServerBase {
public HttpServerResponse setContentType(String contentType) {
if (null != contentType && null != this.charset) {
if (false == contentType.contains(";charset=")) {
- contentType += ";charset=" + this.charset;
+ contentType = ContentType.build(contentType, this.charset);
}
}
@@ -169,12 +218,27 @@ public class HttpServerResponse extends HttpServerBase {
return this;
}
+ /**
+ * 设置属性
+ *
+ * @param name 属性名
+ * @param value 属性值
+ * @return this
+ */
+ public HttpServerResponse setAttr(String name, Object value) {
+ this.httpExchange.setAttribute(name, value);
+ return this;
+ }
+
/**
* 获取响应数据流
*
* @return 响应数据流
*/
public OutputStream getOut() {
+ if (false == this.isSendCode) {
+ sendOk();
+ }
return this.httpExchange.getResponseBody();
}
@@ -183,8 +247,43 @@ public class HttpServerResponse extends HttpServerBase {
*
* @return 响应数据流
*/
- public OutputStream getWriter() {
- return this.httpExchange.getResponseBody();
+ public PrintWriter getWriter() {
+ final Charset charset = ObjectUtil.defaultIfNull(this.charset, DEFAULT_CHARSET);
+ return new PrintWriter(new OutputStreamWriter(getOut(), charset));
+ }
+
+ /**
+ * 写出数据到客户端
+ *
+ * @param data 数据
+ * @return this
+ */
+ public HttpServerResponse write(String data, String contentType) {
+ setContentType(contentType);
+ return write(data);
+ }
+
+ /**
+ * 写出数据到客户端
+ *
+ * @param data 数据
+ * @return this
+ */
+ public HttpServerResponse write(String data) {
+ final Charset charset = ObjectUtil.defaultIfNull(this.charset, DEFAULT_CHARSET);
+ return write(StrUtil.bytes(data, charset));
+ }
+
+ /**
+ * 写出数据到客户端
+ *
+ * @param data 数据
+ * @param contentType 返回的类型
+ * @return this
+ */
+ public HttpServerResponse write(byte[] data, String contentType) {
+ setContentType(contentType);
+ return write(data);
}
/**
@@ -194,8 +293,19 @@ public class HttpServerResponse extends HttpServerBase {
* @return this
*/
public HttpServerResponse write(byte[] data) {
- write(new ByteArrayInputStream(data));
- return this;
+ return write(new ByteArrayInputStream(data));
+ }
+
+ /**
+ * 返回数据给客户端
+ *
+ * @param in 需要返回客户端的内容
+ * @param contentType 返回的类型
+ * @since 5.2.6
+ */
+ public HttpServerResponse write(InputStream in, String contentType) {
+ setContentType(contentType);
+ return write(in);
}
/**
@@ -236,7 +346,7 @@ public class HttpServerResponse extends HttpServerBase {
}
/**
- * 返回数据给客户端
+ * 返回文件数据给客户端(文件下载)
*
* @param in 需要返回客户端的内容
* @param contentType 返回的类型
@@ -244,7 +354,7 @@ public class HttpServerResponse extends HttpServerBase {
* @since 5.2.6
*/
public void write(InputStream in, String contentType, String fileName) {
- final Charset charset = ObjectUtil.defaultIfNull(this.charset, CharsetUtil.CHARSET_UTF_8);
+ final Charset charset = ObjectUtil.defaultIfNull(this.charset, DEFAULT_CHARSET);
setHeader("Content-Disposition", StrUtil.format("attachment;filename={}", URLUtil.encode(fileName, charset)));
setContentType(contentType);
write(in);
diff --git a/hutool-http/src/main/java/cn/hutool/http/server/SimpleServer.java b/hutool-http/src/main/java/cn/hutool/http/server/SimpleServer.java
index 21d62fd1f..aa1377963 100644
--- a/hutool-http/src/main/java/cn/hutool/http/server/SimpleServer.java
+++ b/hutool-http/src/main/java/cn/hutool/http/server/SimpleServer.java
@@ -1,9 +1,10 @@
package cn.hutool.http.server;
import cn.hutool.core.io.IORuntimeException;
+import cn.hutool.core.lang.Console;
import cn.hutool.http.server.action.Action;
+import cn.hutool.http.server.action.RootAction;
import cn.hutool.http.server.handler.ActionHandler;
-import cn.hutool.http.server.handler.RootHandler;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
@@ -72,7 +73,7 @@ public class SimpleServer {
* @return this
*/
public SimpleServer setRoot(String root) {
- return addHandler("/", new RootHandler(root));
+ return addAction("/", new RootAction(root));
}
/**
@@ -119,6 +120,8 @@ public class SimpleServer {
* 启动Http服务器,启动后会阻塞当前线程
*/
public void start() {
+ final InetSocketAddress address = getAddress();
+ Console.log("Hutool Simple Http Server listen on 【{}:{}】", address.getHostName(), address.getPort());
this.server.start();
}
}
diff --git a/hutool-http/src/main/java/cn/hutool/http/server/action/RootAction.java b/hutool-http/src/main/java/cn/hutool/http/server/action/RootAction.java
new file mode 100644
index 000000000..1444cdbb6
--- /dev/null
+++ b/hutool-http/src/main/java/cn/hutool/http/server/action/RootAction.java
@@ -0,0 +1,62 @@
+package cn.hutool.http.server.action;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.http.server.HttpServerRequest;
+import cn.hutool.http.server.HttpServerResponse;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * 默认的处理器,通过解析用户传入的path,找到网页根目录下对应文件后返回
+ *
+ * @author looly
+ * @since 5.2.6
+ */
+public class RootAction implements Action {
+
+ public static final String DEFAULT_INDEX_FILE_NAME = "index.html";
+
+ private final String rootDir;
+ private List indexFileNames;
+
+ /**
+ * 构造
+ *
+ * @param rootDir 网页根目录
+ */
+ public RootAction(String rootDir) {
+ this(rootDir, DEFAULT_INDEX_FILE_NAME);
+ }
+
+ /**
+ * 构造
+ *
+ * @param rootDir 网页根目录
+ * @param indexFileNames 主页文件名列表
+ */
+ public RootAction(String rootDir, String... indexFileNames) {
+ this.rootDir = rootDir;
+ this.indexFileNames = CollUtil.toList(indexFileNames);
+ }
+
+ @Override
+ public void doAction(HttpServerRequest request, HttpServerResponse response) {
+ final String path = request.getPath();
+ File file = FileUtil.file(rootDir, path);
+ if (file.exists()) {
+ if (file.isDirectory()) {
+ for (String indexFileName : indexFileNames) {
+ //默认读取主页
+ file = FileUtil.file(file, indexFileName);
+ if (file.exists() && file.isFile()) {
+ response.write(file);
+ }
+ }
+ }
+ }
+
+ response.send404("404 Not Found !");
+ }
+}
diff --git a/hutool-http/src/main/java/cn/hutool/http/server/handler/ActionHandler.java b/hutool-http/src/main/java/cn/hutool/http/server/handler/ActionHandler.java
index 94a51d004..e469ad3d0 100644
--- a/hutool-http/src/main/java/cn/hutool/http/server/handler/ActionHandler.java
+++ b/hutool-http/src/main/java/cn/hutool/http/server/handler/ActionHandler.java
@@ -27,6 +27,9 @@ public class ActionHandler implements HttpHandler {
@Override
public void handle(HttpExchange httpExchange) {
- action.doAction(new HttpServerRequest(httpExchange), new HttpServerResponse(httpExchange));
+ action.doAction(
+ new HttpServerRequest(httpExchange),
+ new HttpServerResponse(httpExchange)
+ );
}
}
diff --git a/hutool-http/src/main/java/cn/hutool/http/server/handler/HandlerUtil.java b/hutool-http/src/main/java/cn/hutool/http/server/handler/HandlerUtil.java
deleted file mode 100644
index a3fe4d0b8..000000000
--- a/hutool-http/src/main/java/cn/hutool/http/server/handler/HandlerUtil.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package cn.hutool.http.server.handler;
-
-import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.http.Header;
-import cn.hutool.http.HttpStatus;
-import cn.hutool.http.HttpUtil;
-import com.sun.net.httpserver.HttpExchange;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * 请求处理器相关工具类
- *
- * @since 5.2.6
- */
-public class HandlerUtil {
-
- /**
- * 返回404页面
- *
- * @param httpExchange HttpExchange
- * @param content 要发送的404页面内容
- * @throws IOException IO异常
- */
- public static void send404(HttpExchange httpExchange, String content) throws IOException {
- if (null == httpExchange) {
- return;
- }
-
- if (null == content) {
- content = "404 Not Found !";
- }
-
- httpExchange.sendResponseHeaders(HttpStatus.HTTP_NOT_FOUND, 0);
- try (OutputStream out = httpExchange.getResponseBody()) {
- IoUtil.writeUtf8(out, false, content);
- }
- }
-
- /**
- * 返回文件
- *
- * @param httpExchange HttpExchange
- * @param file 要发送的文件
- * @throws IOException IO异常
- */
- public static void sendFile(HttpExchange httpExchange, File file) throws IOException {
- if (ArrayUtil.hasNull(httpExchange, file)) {
- return;
- }
- addHeader(httpExchange,
- Header.CONTENT_TYPE.toString(),
- HttpUtil.getMimeType(file.getName(), "text/html"));
- httpExchange.sendResponseHeaders(HttpStatus.HTTP_OK, 0);
- try (OutputStream out = httpExchange.getResponseBody()) {
- FileUtil.writeToStream(file, out);
- }
- }
-
- /**
- * 增加响应头信息
- *
- * @param httpExchange HttpExchange
- * @param header 头名
- * @param value 头值
- */
- public static void addHeader(HttpExchange httpExchange, String header, String value) {
- if (ArrayUtil.hasEmpty(httpExchange, header)) {
- return;
- }
- httpExchange.getResponseHeaders().add(header, value);
- }
-
- /**
- * 获取响应头信息
- *
- * @param httpExchange HttpExchange
- * @param header 头名
- * @return 值,不存在返回null
- */
- public static String getHeader(HttpExchange httpExchange, String header) {
- if (ArrayUtil.hasEmpty(httpExchange, header)) {
- return null;
- }
- return httpExchange.getRequestHeaders().getFirst(header);
- }
-}
diff --git a/hutool-http/src/main/java/cn/hutool/http/server/handler/RootHandler.java b/hutool-http/src/main/java/cn/hutool/http/server/handler/RootHandler.java
deleted file mode 100644
index 8e10274ee..000000000
--- a/hutool-http/src/main/java/cn/hutool/http/server/handler/RootHandler.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package cn.hutool.http.server.handler;
-
-import cn.hutool.core.io.FileUtil;
-import com.sun.net.httpserver.HttpExchange;
-import com.sun.net.httpserver.HttpHandler;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URI;
-
-/**
- * 默认的处理器,通过解析用户传入的path,找到网页根目录下对应文件后返回
- *
- * @author looly
- * @since 5.2.6
- */
-public class RootHandler implements HttpHandler {
-
- private final String rootDir;
-
- /**
- * 构造
- *
- * @param rootDir 网页根目录
- */
- public RootHandler(String rootDir) {
- this.rootDir = rootDir;
- }
-
- @Override
- public void handle(HttpExchange httpExchange) throws IOException {
- final URI uri = httpExchange.getRequestURI();
- File file = FileUtil.file(rootDir, uri.getPath());
- if (file.exists()) {
- if (file.isDirectory()) {
- //默认读取主页
- file = FileUtil.file(file, "index.html");
- }
- HandlerUtil.sendFile(httpExchange, file);
- }
-
- // 文件未找到
- HandlerUtil.send404(httpExchange, null);
- }
-}
diff --git a/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java b/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java
index 70a70a510..afb3657ae 100644
--- a/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java
+++ b/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java
@@ -1,13 +1,23 @@
package cn.hutool.http.server;
+import cn.hutool.http.ContentType;
import cn.hutool.http.HttpUtil;
-import cn.hutool.http.server.handler.RootHandler;
public class SimpleServerTest {
public static void main(String[] args) {
HttpUtil.createServer(8888)
- .addHandler("/", new RootHandler("D:\\test"))
+ // 设置默认根目录,
+ .setRoot("d:/test")
+ // 返回JSON数据测试
+ .addAction("/restTest", (request, response) ->
+ response.write("{\"id\": 1, \"msg\": \"OK\"}", ContentType.JSON.toString())
+ )
+ // 获取表单数据测试
+ // http://localhost:8888/formTest?a=1&a=2&b=3
+ .addAction("/formTest", (request, response) ->
+ response.write(request.getParams().toString(), ContentType.TEXT_PLAIN.toString())
+ )
.start();
}
}
diff --git a/hutool-http/src/test/java/cn/hutool/http/test/HttpUtilTest.java b/hutool-http/src/test/java/cn/hutool/http/test/HttpUtilTest.java
index 58ea75870..59afded99 100644
--- a/hutool-http/src/test/java/cn/hutool/http/test/HttpUtilTest.java
+++ b/hutool-http/src/test/java/cn/hutool/http/test/HttpUtilTest.java
@@ -1,13 +1,5 @@
package cn.hutool.http.test;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.junit.Assert;
-import org.junit.Ignore;
-import org.junit.Test;
-
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.CharsetUtil;
@@ -15,6 +7,13 @@ import cn.hutool.core.util.ReUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
public class HttpUtilTest {
@@ -164,6 +163,16 @@ public class HttpUtilTest {
paramsStr = "a=bbb&c=你好&哈喽&";
encode = HttpUtil.encodeParams(paramsStr, CharsetUtil.CHARSET_UTF_8);
Assert.assertEquals("a=bbb&c=%E4%BD%A0%E5%A5%BD&%E5%93%88%E5%96%BD=", encode);
+
+ // URL原样输出
+ paramsStr = "https://www.hutool.cn/";
+ encode = HttpUtil.encodeParams(paramsStr, CharsetUtil.CHARSET_UTF_8);
+ Assert.assertEquals(paramsStr, encode);
+
+ // URL原样输出
+ paramsStr = "https://www.hutool.cn/?";
+ encode = HttpUtil.encodeParams(paramsStr, CharsetUtil.CHARSET_UTF_8);
+ Assert.assertEquals("https://www.hutool.cn/", encode);
}
@Test
diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml
index af66a23a4..6b4058a92 100644
--- a/hutool-json/pom.xml
+++ b/hutool-json/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-json
diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml
index 98f927ac6..29dad09b7 100644
--- a/hutool-log/pom.xml
+++ b/hutool-log/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-log
diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml
index 379315af5..42eee9aa1 100644
--- a/hutool-poi/pom.xml
+++ b/hutool-poi/pom.xml
@@ -8,7 +8,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-poi
diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml
index 05cf7bf27..dc77c1722 100644
--- a/hutool-script/pom.xml
+++ b/hutool-script/pom.xml
@@ -8,7 +8,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-script
diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml
index eb777bc49..e1b72b92a 100644
--- a/hutool-setting/pom.xml
+++ b/hutool-setting/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-setting
diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml
index 011ef7557..f87b3cab0 100644
--- a/hutool-socket/pom.xml
+++ b/hutool-socket/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-socket
diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml
index a89067307..0a7c45ab4 100644
--- a/hutool-system/pom.xml
+++ b/hutool-system/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool-system
diff --git a/pom.xml b/pom.xml
index e443672b0..0c7c027be 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,7 +8,7 @@
cn.hutool
hutool-parent
- 5.2.6-SNAPSHOT
+ 5.3.0-SNAPSHOT
hutool
提供丰富的Java工具方法
https://github.com/looly/hutool