diff --git a/hutool-extra/src/main/java/cn/hutool/extra/pinyin/PinyinEngine.java b/hutool-extra/src/main/java/cn/hutool/extra/pinyin/PinyinEngine.java index 74e40bb3e..9ffc2c8bf 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/pinyin/PinyinEngine.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/pinyin/PinyinEngine.java @@ -21,6 +21,17 @@ public interface PinyinEngine { */ String getPinyin(char c); + /** + * 如果c为汉字,则返回大写拼音;如果c不是汉字,则返回String.valueOf(c) + * + * @param c 任意字符,汉字返回拼音,非汉字原样返回 + * @param tone 是否返回声调 + * @return 汉字返回拼音,非汉字原样返回 + */ + default String getPinyin(char c, boolean tone){ + return getPinyin(c); + } + /** * 获取字符串对应的完整拼音,非中文返回原字符 * @@ -30,6 +41,19 @@ public interface PinyinEngine { */ String getPinyin(String str, String separator); + /** + * 获取字符串对应的完整拼音,非中文返回原字符 + * + * @param str 字符串 + * @param separator 拼音之间的分隔符 + * @param tone 是否返回声调 + * @return 拼音 + */ + default String getPinyin(String str, String separator,boolean tone){ + return getPinyin(str, separator); + } + + /** * 将输入字符串转为拼音首字母,其它字符原样返回 * diff --git a/hutool-extra/src/main/java/cn/hutool/extra/pinyin/PinyinUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/pinyin/PinyinUtil.java index e1f618ac1..d6ac1497f 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/pinyin/PinyinUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/pinyin/PinyinUtil.java @@ -31,6 +31,17 @@ public class PinyinUtil { return getEngine().getPinyin(c); } + /** + * 如果c为汉字,则返回大写拼音;如果c不是汉字,则返回String.valueOf(c) + * + * @param c 任意字符,汉字返回拼音,非汉字原样返回 + * @param tone 是否返回声调 + * @return 汉字返回拼音,非汉字原样返回 + */ + public static String getPinyin(final char c, boolean tone) { + return getEngine().getPinyin(c,tone); + } + /** * 将输入字符串转为拼音,每个字之间的拼音使用空格分隔 * @@ -41,6 +52,17 @@ public class PinyinUtil { return getPinyin(str, StrUtil.SPACE); } + /** + * 将输入字符串转为拼音,每个字之间的拼音使用空格分隔 + * + * @param str 任意字符,汉字返回拼音,非汉字原样返回 + * @param tone 是否返回声调 + * @return 汉字返回拼音,非汉字原样返回 + */ + public static String getPinyin(final String str, boolean tone) { + return getPinyin(str, StrUtil.SPACE, tone); + } + /** * 将输入字符串转为拼音,以字符为单位插入分隔符 * @@ -52,6 +74,18 @@ public class PinyinUtil { return getEngine().getPinyin(str, separator); } + /** + * 将输入字符串转为拼音,以字符为单位插入分隔符 + * + * @param str 任意字符,汉字返回拼音,非汉字原样返回 + * @param separator 每个字拼音之间的分隔符 + * @param tone 是否返回声调 + * @return 汉字返回拼音,非汉字原样返回 + */ + public static String getPinyin(final String str, final String separator, boolean tone) { + return getEngine().getPinyin(str, separator, tone); + } + /** * 将输入字符串转为拼音首字母,其它字符原样返回 * diff --git a/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/bopomofo4j/Bopomofo4jEngine.java b/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/bopomofo4j/Bopomofo4jEngine.java index 433f5d30b..7980704c7 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/bopomofo4j/Bopomofo4jEngine.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/bopomofo4j/Bopomofo4jEngine.java @@ -36,8 +36,26 @@ public class Bopomofo4jEngine implements PinyinEngine { return Bopomofo4j.pinyin(String.valueOf(c), ToneType.WITHOUT_TONE, false, false, StrUtil.EMPTY); } + @Override + public String getPinyin(char c, boolean tone) { + if (tone) { + return Bopomofo4j.pinyin(String.valueOf(c), ToneType.WITH_VOWEL_TONE, false, false, StrUtil.EMPTY); + }else{ + return getPinyin(c); + } + } + @Override public String getPinyin(String str, String separator) { return Bopomofo4j.pinyin(str, ToneType.WITHOUT_TONE, false, false, separator); } + + @Override + public String getPinyin(String str, String separator, boolean tone) { + if (tone) { + return Bopomofo4j.pinyin(str, ToneType.WITH_VOWEL_TONE, false, false, separator); + }else{ + return getPinyin(str, separator); + } + } } diff --git a/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/houbbpinyin/HoubbPinyinEngine.java b/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/houbbpinyin/HoubbPinyinEngine.java index 323ef1718..c3f8dee04 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/houbbpinyin/HoubbPinyinEngine.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/houbbpinyin/HoubbPinyinEngine.java @@ -65,10 +65,28 @@ public class HoubbPinyinEngine implements PinyinEngine { return result; } + @Override + public String getPinyin(char c, boolean tone) { + if (tone){ + return PinyinHelper.toPinyin(String.valueOf(c), PinyinStyleEnum.DEFAULT); + }else { + return getPinyin(c); + } + } + @Override public String getPinyin(String str, String separator) { String result; result = PinyinHelper.toPinyin(str, format, separator); return result; } + + @Override + public String getPinyin(String str, String separator, boolean tone) { + if(tone){ + return PinyinHelper.toPinyin(str, PinyinStyleEnum.DEFAULT, separator); + }else { + return getPinyin(str,separator); + } + } } diff --git a/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/jpinyin/JPinyinEngine.java b/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/jpinyin/JPinyinEngine.java index c0a247ad2..f52722dbc 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/jpinyin/JPinyinEngine.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/jpinyin/JPinyinEngine.java @@ -53,6 +53,16 @@ public class JPinyinEngine implements PinyinEngine { return ArrayUtil.isEmpty(results) ? String.valueOf(c) : results[0]; } + @Override + public String getPinyin(char c, boolean tone) { + if (tone) { + String[] results = PinyinHelper.convertToPinyinArray(c, PinyinFormat.WITH_TONE_MARK); + return ArrayUtil.isEmpty(results) ? String.valueOf(c) : results[0]; + }else { + return getPinyin(c); + } + } + @Override public String getPinyin(String str, String separator) { try { @@ -61,4 +71,19 @@ public class JPinyinEngine implements PinyinEngine { throw new cn.hutool.extra.pinyin.PinyinException(e); } } + + @Override + public String getPinyin(String str, String separator, boolean tone) { + if (tone) { + try { + return PinyinHelper.convertToPinyinString(str, separator, PinyinFormat.WITH_TONE_MARK); + } catch (PinyinException e) { + throw new cn.hutool.extra.pinyin.PinyinException(e); + } + }else { + return getPinyin(str, separator); + } + + } + } diff --git a/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/pinyin4j/Pinyin4jEngine.java b/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/pinyin4j/Pinyin4jEngine.java index 241d12bdc..de332ea4a 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/pinyin4j/Pinyin4jEngine.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/pinyin4j/Pinyin4jEngine.java @@ -82,6 +82,31 @@ public class Pinyin4jEngine implements PinyinEngine { return result; } + @Override + public String getPinyin(char c, boolean tone) { + String result; + if(tone){ + try { + //增加声调 + HanyuPinyinOutputFormat formatTemp = new HanyuPinyinOutputFormat(); + // 小写 + formatTemp.setCaseType(HanyuPinyinCaseType.LOWERCASE); + // 加声调 + formatTemp.setToneType(HanyuPinyinToneType.WITH_TONE_MARK); + // + formatTemp.setVCharType(HanyuPinyinVCharType.WITH_U_UNICODE); + String[] results = PinyinHelper.toHanyuPinyinStringArray(c, formatTemp); + result = ArrayUtil.isEmpty(results) ? String.valueOf(c) : results[0]; + } catch (BadHanyuPinyinOutputFormatCombination e) { + result = String.valueOf(c); + } + }else { + result = getPinyin(c); + } + return result; + + } + @Override public String getPinyin(String str, String separator) { final StrBuilder result = StrUtil.strBuilder(); @@ -107,4 +132,41 @@ public class Pinyin4jEngine implements PinyinEngine { return result.toString(); } + + @Override + public String getPinyin(String str, String separator, boolean tone) { + if(tone){ + final StrBuilder result = StrUtil.strBuilder(); + boolean isFirst = true; + final int strLen = str.length(); + try { + for(int i = 0; i < strLen; i++){ + if(isFirst){ + isFirst = false; + } else{ + result.append(separator); + } + //增加声调 + HanyuPinyinOutputFormat formatTemp = new HanyuPinyinOutputFormat(); + // 小写 + formatTemp.setCaseType(HanyuPinyinCaseType.LOWERCASE); + // 加声调 + formatTemp.setToneType(HanyuPinyinToneType.WITH_TONE_MARK); + // + formatTemp.setVCharType(HanyuPinyinVCharType.WITH_U_UNICODE); + final String[] pinyinStringArray = PinyinHelper.toHanyuPinyinStringArray(str.charAt(i), formatTemp); + if(ArrayUtil.isEmpty(pinyinStringArray)){ + result.append(str.charAt(i)); + } else{ + result.append(pinyinStringArray[0]); + } + } + } catch (BadHanyuPinyinOutputFormatCombination e) { + throw new PinyinException(e); + } + return result.toString(); + }else { + return getPinyin(str, separator); + } + } } diff --git a/hutool-http/src/main/java/cn/hutool/http/HttpBase.java b/hutool-http/src/main/java/cn/hutool/http/HttpBase.java index 982c0bbad..8877962d7 100644 --- a/hutool-http/src/main/java/cn/hutool/http/HttpBase.java +++ b/hutool-http/src/main/java/cn/hutool/http/HttpBase.java @@ -39,6 +39,10 @@ public abstract class HttpBase { */ public static final String HTTP_1_1 = "HTTP/1.1"; + /** + * 是否聚合重复请求头 + */ + protected boolean isHeaderAggregated = false; /** * 存储头信息 */ @@ -276,6 +280,26 @@ public abstract class HttpBase { this.headers.clear(); return (T) this; } + + /** + * 设置是否需要聚合重复的请求头,将重复的请求头聚合为,拼接 + * + * @param aggregate 是否需要聚合 + * @return this + */ + public T headerAggregation(boolean aggregate) { + this.isHeaderAggregated = aggregate; + return (T) this; + } + + /** + * 获取是否需要聚合请求头状态 + * + * @return isHeaderAggregated 请求头聚合状态 + */ + public boolean isHeaderAggregated() { + return isHeaderAggregated; + } // ---------------------------------------------------------------- Headers end /** diff --git a/hutool-http/src/main/java/cn/hutool/http/HttpConnection.java b/hutool-http/src/main/java/cn/hutool/http/HttpConnection.java index 8a7761f57..456714f76 100644 --- a/hutool-http/src/main/java/cn/hutool/http/HttpConnection.java +++ b/hutool-http/src/main/java/cn/hutool/http/HttpConnection.java @@ -229,6 +229,31 @@ public class HttpConnection { return this; } + /** + * 设置请求头
+ * 不覆盖原有请求头并判断是否需要聚合请求头 + * + * @param headerMap 请求头 + * @param isOverride 是否覆盖 + * @param isHeaderAggregated 是否聚合 + * @return this + */ + public HttpConnection header(Map> headerMap, boolean isOverride, boolean isHeaderAggregated) { + if (!isHeaderAggregated){ + return header(headerMap,isOverride); + } + if (MapUtil.isNotEmpty(headerMap)) { + String name; + for (Entry> entry : headerMap.entrySet()) { + name = entry.getKey(); + List values = entry.getValue(); + String headValues = StrUtil.join(",", values); + this.header(name, StrUtil.nullToEmpty(headValues), true); + } + } + return this; + } + /** * 获取Http请求头 * diff --git a/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java b/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java index ef67dec10..a896fdade 100755 --- a/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java +++ b/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java @@ -1247,7 +1247,7 @@ public class HttpRequest extends HttpBase { // issue#3462 自定义body长度 .setFixedLengthStreamingMode(this.fixedContentLength) // 覆盖默认Header - .header(this.headers, false); + .header(this.headers, false, this.isHeaderAggregated); if (null != this.cookie) { // 当用户自定义Cookie时,全局Cookie自动失效 diff --git a/hutool-http/src/test/java/cn/hutool/http/HttpRequestTest.java b/hutool-http/src/test/java/cn/hutool/http/HttpRequestTest.java index 1334302a5..eec10a075 100644 --- a/hutool-http/src/test/java/cn/hutool/http/HttpRequestTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/HttpRequestTest.java @@ -270,4 +270,17 @@ public class HttpRequestTest { HttpRequest request = HttpRequest.get("http://localhost:9999/qms/bus/qmsBusReportCenterData/getReportDataList?reportProcessNo=A00&goodsName=工业硫酸98%&conReportTypeId=1010100000000000007&measureDateStr=2024-07-01"); request.execute(); } + + @Test + public void testHttpHead(){ + Map map = new HashMap<>(); + map.put("test","test"); + HttpRequest httpRequest = HttpRequest.post("http://127.0.0.1:8080/testHttpHead") + .header("test","test1") + .headerMap(map,false) + .headerAggregation(true); + System.out.println(httpRequest.headers()); + HttpResponse execute = httpRequest.execute(); + System.out.println(execute.body()); + } } diff --git a/hutool-http/src/test/java/cn/hutool/http/SimpleHttpServer.java b/hutool-http/src/test/java/cn/hutool/http/SimpleHttpServer.java new file mode 100644 index 000000000..8c0dc95ad --- /dev/null +++ b/hutool-http/src/test/java/cn/hutool/http/SimpleHttpServer.java @@ -0,0 +1,81 @@ +package cn.hutool.http; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.ServerSocket; +import java.net.Socket; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +/** + * 一个简单的http服务器示例代码; + * 用于打印出接收到的请求头和简单的post-json的请求体数据来测试 + * + * @author ZhangWeinan + * @date 2025/2/23 15:32 + */ +public class SimpleHttpServer { + + public static void main(String[] args) throws IOException { + int port = 8080; + ServerSocket serverSocket = new ServerSocket(port); + System.out.println("Server started on port " + port); + + while (true) { + Socket clientSocket = serverSocket.accept(); + new Thread(() -> handleClient(clientSocket)).start(); + } + } + + private static void handleClient(Socket clientSocket) { + try (BufferedReader in = new BufferedReader( + new InputStreamReader(clientSocket.getInputStream())); + OutputStream out = clientSocket.getOutputStream()) { + String requestLine = in.readLine(); + if (requestLine == null) return; + + String[] parts = requestLine.split(" "); + String method = parts[0]; + + Map headers = new HashMap<>(); + String line; + System.out.println("\n=== Headers ==="); + while (!(line = in.readLine()).isEmpty()) { + int colonIndex = line.indexOf(':'); + if (colonIndex > 0) { + String key = line.substring(0, colonIndex).trim(); + String value = line.substring(colonIndex + 1).trim(); + headers.put(key, value); + System.out.println(key + ": " + value); + } + } + if ("POST".equalsIgnoreCase(method)) { + int contentLength = Integer.parseInt(headers.getOrDefault("Content-Length", "0")); + if (contentLength > 0) { + char[] body = new char[contentLength]; + in.read(body, 0, contentLength); + String jsonBody = new String(body); + System.out.println("\n=== JSON Body ==="); + System.out.println(jsonBody); + } + } + String response = "HTTP/1.1 200 OK\r\n" + + "Content-Type: text/plain\r\n" + + "Content-Length: 16\r\n\r\n" + + "Request received"; + out.write(response.getBytes(StandardCharsets.UTF_8)); + + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + clientSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } +}