From 1218a5150914f4b77b53eeae9c9d289bc8642610 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 2 Apr 2020 11:59:58 +0800 Subject: [PATCH] add Request --- .../main/java/cn/hutool/core/io/IoUtil.java | 16 +- .../java/cn/hutool/core/util/CharsetUtil.java | 119 +++++++---- .../src/main/java/cn/hutool/http/Header.java | 11 +- .../main/java/cn/hutool/http/HttpUtil.java | 17 +- .../cn/hutool/http/server/HttpRequest.java | 199 ++++++++++++++++++ .../http/useragent/UserAgentParser.java | 4 + 6 files changed, 315 insertions(+), 51 deletions(-) create mode 100644 hutool-http/src/main/java/cn/hutool/http/server/HttpRequest.java diff --git a/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java index 72a073ca6..6d1d44dae 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java @@ -1,5 +1,12 @@ package cn.hutool.core.io; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.exceptions.UtilException; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.HexUtil; +import cn.hutool.core.util.StrUtil; + import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; @@ -36,13 +43,6 @@ import java.util.zip.CRC32; import java.util.zip.CheckedInputStream; import java.util.zip.Checksum; -import cn.hutool.core.convert.Convert; -import cn.hutool.core.exceptions.UtilException; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.CharsetUtil; -import cn.hutool.core.util.HexUtil; -import cn.hutool.core.util.StrUtil; - /** * IO工具类
* IO工具类只是辅助流的读写,并不负责关闭流。原因是流可能被多次读写,读写关闭后容易造成问题。 @@ -453,7 +453,7 @@ public class IoUtil { } /** - * 从流中读取内容,读到输出流中 + * 从流中读取内容,读到输出流中,读取完毕后并不关闭流 * * @param in 输入流 * @return 输出流 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 5d21c0b05..c19de5d01 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 @@ -1,65 +1,102 @@ package cn.hutool.core.util; +import cn.hutool.core.io.FileUtil; + import java.io.File; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; -import cn.hutool.core.io.FileUtil; - /** * 字符集工具类 - * @author xiaoleilu * + * @author xiaoleilu */ public class CharsetUtil { - - /** ISO-8859-1 */ + + /** + * ISO-8859-1 + */ public static final String ISO_8859_1 = "ISO-8859-1"; - /** UTF-8 */ + /** + * UTF-8 + */ public static final String UTF_8 = "UTF-8"; - /** GBK */ + /** + * GBK + */ public static final String GBK = "GBK"; - - /** ISO-8859-1 */ + + /** + * ISO-8859-1 + */ public static final Charset CHARSET_ISO_8859_1 = StandardCharsets.ISO_8859_1; - /** UTF-8 */ + /** + * UTF-8 + */ public static final Charset CHARSET_UTF_8 = StandardCharsets.UTF_8; - /** GBK */ + /** + * GBK + */ public static final Charset CHARSET_GBK; - static{ + static { //避免不支持GBK的系统中运行报错 issue#731 Charset _CHARSET_GBK = null; - try{ + try { _CHARSET_GBK = Charset.forName(GBK); - } catch (UnsupportedCharsetException e){ + } catch (UnsupportedCharsetException e) { //ignore } CHARSET_GBK = _CHARSET_GBK; } - + /** * 转换为Charset对象 + * * @param charsetName 字符集,为空则返回默认字符集 * @return Charset * @throws UnsupportedCharsetException 编码不支持 */ - public static Charset charset(String charsetName) throws UnsupportedCharsetException{ + public static Charset charset(String charsetName) throws UnsupportedCharsetException { return StrUtil.isBlank(charsetName) ? Charset.defaultCharset() : Charset.forName(charsetName); } - + + /** + * 解析字符串编码为Charset对象,解析失败返回默认编码 + * + * @param charsetName 字符集,为空则返回默认字符集 + * @param defaultCharset 解析失败使用的默认编码 + * @return Charset + * @since 5.2.6 + */ + public static Charset parse(String charsetName, Charset defaultCharset) throws UnsupportedCharsetException { + if (StrUtil.isBlank(charsetName)) { + return defaultCharset; + } + + Charset result; + try { + result = Charset.forName(charsetName); + } catch (UnsupportedCharsetException e) { + result = defaultCharset; + } + + return result; + } + /** * 转换字符串的字符集编码 - * @param source 字符串 - * @param srcCharset 源字符集,默认ISO-8859-1 + * + * @param source 字符串 + * @param srcCharset 源字符集,默认ISO-8859-1 * @param destCharset 目标字符集,默认UTF-8 * @return 转换后的字符集 */ public static String convert(String source, String srcCharset, String destCharset) { return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset)); } - + /** * 转换字符串的字符集编码
* 当以错误的编码读取为字符串时,打印字符串将出现乱码。
@@ -69,33 +106,33 @@ public class CharsetUtil { * 客户端 -》 GBK编码 -》 Servlet容器 -》 UTF-8解码 -》 乱码 * 乱码 -》 UTF-8编码 -》 GBK解码 -》 正确内容 * - * - * @param source 字符串 - * @param srcCharset 源字符集,默认ISO-8859-1 + * + * @param source 字符串 + * @param srcCharset 源字符集,默认ISO-8859-1 * @param destCharset 目标字符集,默认UTF-8 * @return 转换后的字符集 */ public static String convert(String source, Charset srcCharset, Charset destCharset) { - if(null == srcCharset) { + if (null == srcCharset) { srcCharset = StandardCharsets.ISO_8859_1; } - - if(null == destCharset) { + + if (null == destCharset) { destCharset = StandardCharsets.UTF_8; } - + if (StrUtil.isBlank(source) || srcCharset.equals(destCharset)) { return source; } return new String(source.getBytes(srcCharset), destCharset); } - + /** * 转换文件编码
* 此方法用于转换文件编码,读取的文件实际编码必须与指定的srcCharset编码一致,否则导致乱码 - * - * @param file 文件 - * @param srcCharset 原文件的编码,必须与文件内容的编码保持一致 + * + * @param file 文件 + * @param srcCharset 原文件的编码,必须与文件内容的编码保持一致 * @param destCharset 转码后的编码 * @return 被转换编码的文件 * @since 3.1.0 @@ -104,41 +141,41 @@ public class CharsetUtil { final String str = FileUtil.readString(file, srcCharset); return FileUtil.writeString(str, file, destCharset); } - + /** * 系统字符集编码,如果是Windows,则默认为GBK编码,否则取 {@link CharsetUtil#defaultCharsetName()} - * - * @see CharsetUtil#defaultCharsetName() + * * @return 系统字符集编码 + * @see CharsetUtil#defaultCharsetName() * @since 3.1.2 */ public static String systemCharsetName() { return systemCharset().name(); } - + /** * 系统字符集编码,如果是Windows,则默认为GBK编码,否则取 {@link CharsetUtil#defaultCharsetName()} - * - * @see CharsetUtil#defaultCharsetName() + * * @return 系统字符集编码 + * @see CharsetUtil#defaultCharsetName() * @since 3.1.2 */ public static Charset systemCharset() { return FileUtil.isWindows() ? CHARSET_GBK : defaultCharset(); } - + /** * 系统默认字符集编码 - * + * * @return 系统字符集编码 */ public static String defaultCharsetName() { return defaultCharset().name(); } - + /** * 系统默认字符集编码 - * + * * @return 系统字符集编码 */ public static Charset defaultCharset() { diff --git a/hutool-http/src/main/java/cn/hutool/http/Header.java b/hutool-http/src/main/java/cn/hutool/http/Header.java index 3ff1ef0f3..a9385d37d 100644 --- a/hutool-http/src/main/java/cn/hutool/http/Header.java +++ b/hutool-http/src/main/java/cn/hutool/http/Header.java @@ -127,8 +127,17 @@ public enum Header { this.value = value; } + /** + * 获取值 + * + * @return 值 + */ + public String getValue(){ + return this.value; + } + @Override public String toString() { - return value; + return getValue(); } } 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 dca6c0daa..264e9c233 100644 --- a/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java +++ b/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java @@ -677,7 +677,22 @@ public class HttpUtil { if (conn == null) { return null; } - return ReUtil.get(CHARSET_PATTERN, conn.getContentType(), 1); + return getCharset(conn.getContentType()); + } + + /** + * 从Http连接的头信息中获得字符集
+ * 从ContentType中获取 + * + * @param contentType Content-Type + * @return 字符集 + * @since 5.2.6 + */ + public static String getCharset(String contentType) { + if (StrUtil.isBlank(contentType)) { + return null; + } + return ReUtil.get(CHARSET_PATTERN, contentType, 1); } /** diff --git a/hutool-http/src/main/java/cn/hutool/http/server/HttpRequest.java b/hutool-http/src/main/java/cn/hutool/http/server/HttpRequest.java new file mode 100644 index 000000000..e10b50507 --- /dev/null +++ b/hutool-http/src/main/java/cn/hutool/http/server/HttpRequest.java @@ -0,0 +1,199 @@ +package cn.hutool.http.server; + +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.Header; +import cn.hutool.http.HttpUtil; +import cn.hutool.http.Method; +import cn.hutool.http.useragent.UserAgent; +import cn.hutool.http.useragent.UserAgentUtil; +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpExchange; + +import java.io.InputStream; +import java.net.URI; +import java.nio.charset.Charset; + +/** + * Http请求对象,对{@link HttpExchange}封装 + * + * @author looly + * @since 5.2.6 + */ +public class HttpRequest { + + private final HttpExchange httpExchange; + + /** + * 构造 + * + * @param httpExchange {@link HttpExchange} + */ + public HttpRequest(HttpExchange httpExchange) { + this.httpExchange = httpExchange; + } + + /** + * 获得Http Method + * + * @return Http Method + */ + public String getMethod() { + return this.httpExchange.getRequestMethod(); + } + + /** + * 是否为GET请求 + * + * @return 是否为GET请求 + */ + public boolean isGetMethod() { + return Method.GET.name().equalsIgnoreCase(getMethod()); + } + + /** + * 是否为POST请求 + * + * @return 是否为POST请求 + */ + public boolean isPostMethod() { + return Method.POST.name().equalsIgnoreCase(getMethod()); + } + + /** + * 获得请求URI + * + * @return 请求URI + */ + public URI getURI() { + return this.httpExchange.getRequestURI(); + } + + /** + * 获得请求路径Path + * + * @return 请求路径 + */ + public String getPath() { + return getURI().getPath(); + } + + /** + * 获取请求参数 + * + * @return 参数字符串 + */ + public String getQuery() { + return getURI().getQuery(); + } + + /** + * 获得请求header中的信息 + * + * @return header值 + */ + public Headers getHeaders() { + return this.httpExchange.getRequestHeaders(); + } + + /** + * 获得请求header中的信息 + * + * @param headerKey 头信息的KEY + * @return header值 + */ + public String getHeader(String headerKey) { + return getHeaders().getFirst(headerKey); + } + + /** + * 获得请求header中的信息 + * + * @param headerKey 头信息的KEY + * @param charset 字符集 + * @return header值 + */ + public String getHeader(String headerKey, Charset charset) { + final String header = getHeader(headerKey); + if (null != header) { + return CharsetUtil.convert(header, CharsetUtil.CHARSET_ISO_8859_1, charset); + } + return null; + } + + /** + * 获得User-Agent + * + * @return User-Agent字符串 + */ + public String getUserAgentStr() { + return getHeader("User-Agent"); + } + + /** + * 获得User-Agent,未识别返回null + * + * @return User-Agent字符串,未识别返回null + */ + public UserAgent getUserAgent() { + return UserAgentUtil.parse(getUserAgentStr()); + } + + /** + * 获取请求体的流,流中可以读取请求内容,包括请求表单数据或文件上传数据 + * + * @return 流 + */ + public InputStream getBodyStream() { + return this.httpExchange.getRequestBody(); + } + + /** + * 获取请求体文本,可以是form表单、json、xml等任意内容
+ * 根据请求的Content-Type判断编码,判断失败使用UTF-8编码 + * + * @return 请求 + */ + public String getBody() { + final String contentType = getHeader(Header.CONTENT_TYPE.toString()); + final String charsetStr = HttpUtil.getCharset(contentType); + final Charset charset = CharsetUtil.parse(charsetStr, CharsetUtil.CHARSET_UTF_8); + + return getBody(charset); + } + + /** + * 获取请求体文本,可以是form表单、json、xml等任意内容 + * + * @param charset 编码 + * @return 请求 + */ + public String getBody(Charset charset) { + InputStream in = null; + try { + in = getBodyStream(); + return IoUtil.read(in, charset); + } finally { + IoUtil.close(in); + } + } + + /** + * 是否为Multipart类型表单,此类型表单用于文件上传 + * + * @return 是否为Multipart类型表单,此类型表单用于文件上传 + */ + public boolean isMultipart() { + if (false == isPostMethod()) { + return false; + } + + final String contentType = getHeader(Header.CONTENT_TYPE.toString()); + if (StrUtil.isBlank(contentType)) { + return false; + } + + return contentType.toLowerCase().startsWith("multipart/"); + } +} diff --git a/hutool-http/src/main/java/cn/hutool/http/useragent/UserAgentParser.java b/hutool-http/src/main/java/cn/hutool/http/useragent/UserAgentParser.java index 6f95ddeed..99cc63938 100644 --- a/hutool-http/src/main/java/cn/hutool/http/useragent/UserAgentParser.java +++ b/hutool-http/src/main/java/cn/hutool/http/useragent/UserAgentParser.java @@ -1,6 +1,7 @@ package cn.hutool.http.useragent; import cn.hutool.core.util.ReUtil; +import cn.hutool.core.util.StrUtil; import java.util.regex.Pattern; @@ -19,6 +20,9 @@ public class UserAgentParser { * @return {@link UserAgent} */ public static UserAgent parse(String userAgentString) { + if(StrUtil.isBlank(userAgentString)){ + return null; + } final UserAgent userAgent = new UserAgent(); final Browser browser = parseBrowser(userAgentString);