20230628 java.net.http.HttpClient
介绍
- java.net.http.HttpClient
- public abstract class HttpClient
API
Builder
-
cookieHandler
CookieHandler
- Cookie 处理器
-
connectTimeout
- 连接超时
-
sslContext
-
sslParameters
- SSL 设置
-
followRedirects
- 设置重定向策略
-
version
- HTTP 版本
-
priority
- 设置从此客户端发送的任何 HTTP/2 请求的默认优先级
-
proxy
- 代理
-
authenticator
- 认证
-
executor
- 设置用于异步请求的执行器
-
build
static
- newBuilder
- 返回
Builder
- 返回
- newHttpClient
- 默认配置创建
HttpClient
- 返回
newBuilder().build()
- 默认配置创建
public
- send, sendAsync
- 产生一个同步或异步的请求,并使用给定的处理器来处理响应体
- newWebSocketBuilder
返回 Builder 中方法设置
- cookieHandler
- connectTimeout
- sslParameters
- sslContext
- executor
- followRedirects
- version
- proxy
- authenticator
代码示例
import java.io.IOException;
import java.io.Reader;
import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublisher;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
class MoreBodyPublishers {
public static BodyPublisher ofFormData(Map<Object, Object> data) {
boolean first = true;
var builder = new StringBuilder();
for (Map.Entry<Object, Object> entry : data.entrySet()) {
if (first) {
first = false;
} else {
builder.append("&");
}
builder.append(URLEncoder.encode(entry.getKey().toString(), StandardCharsets.UTF_8));
builder.append("=");
builder.append(URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8));
}
return BodyPublishers.ofString(builder.toString());
}
private static byte[] bytes(String s) {
return s.getBytes(StandardCharsets.UTF_8);
}
public static BodyPublisher ofMimeMultipartData(Map<Object, Object> data, String boundary) throws IOException {
var byteArrays = new ArrayList<byte[]>();
byte[] separator = bytes("--" + boundary + "\nContent-Disposition: form-data; name=");
for (Map.Entry<Object, Object> entry : data.entrySet()) {
byteArrays.add(separator);
if (entry.getValue() instanceof Path path) {
String mimeType = Files.probeContentType(path);
byteArrays.add(
bytes("\"" + entry.getKey() + "\"; filename=\"" + path.getFileName() + "\"\nContent-Type: "
+ mimeType + "\n\n"));
byteArrays.add(Files.readAllBytes(path));
} else {
byteArrays.add(bytes("\"" + entry.getKey() + "\"\n\n" + entry.getValue() + "\n"));
}
}
byteArrays.add(bytes("--" + boundary + "--"));
return BodyPublishers.ofByteArrays(byteArrays);
}
public static BodyPublisher ofSimpleJSON(Map<Object, Object> data) {
var builder = new StringBuilder();
builder.append("{");
var first = true;
for (Map.Entry<Object, Object> entry : data.entrySet()) {
if (first) {
first = false;
} else {
builder.append(",");
}
builder.append(jsonEscape(entry.getKey().toString())).append(": ")
.append(jsonEscape(entry.getValue().toString()));
}
builder.append("}");
return BodyPublishers.ofString(builder.toString());
}
private static Map<Character, String> replacements =
Map.of('\b', "\\b", '\f', "\\f", '\n', "\\n", '\r', "\\r", '\t', "\\t", '"', "\\\"", '\\', "\\\\");
private static StringBuilder jsonEscape(String str) {
var result = new StringBuilder("\"");
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
String replacement = replacements.get(ch);
if (replacement == null) {
result.append(ch);
} else {
result.append(replacement);
}
}
result.append("\"");
return result;
}
}
public class HttpClientTest {
public static void main(String[] args) throws IOException, URISyntaxException, InterruptedException {
System.setProperty("jdk.httpclient.HttpClient.log", "headers,errors");
String propsFilename = args.length > 0 ? args[0] : "D:\\My\\Study\\专业书\\Java核心技术17\\corejava\\a_study\\src"
+ "\\main\\java\\study\\hwj\\v2p3\\client\\post.properties";
Path propsPath = Path.of(propsFilename);
var props = new Properties();
try (Reader in = Files.newBufferedReader(propsPath, StandardCharsets.UTF_8)) {
props.load(in);
}
String urlString = "" + props.remove("url");
String contentType = "" + props.remove("Content-Type");
if (contentType.equals("multipart/form-data")) {
var generator = new Random();
String boundary = new BigInteger(256, generator).toString();
contentType += ";boundary=" + boundary;
props.replaceAll((k, v) -> v.toString().startsWith("file://") ?
propsPath.getParent().resolve(Path.of(v.toString().substring(7))) : v);
}
String result = doPost(urlString, contentType, props);
System.out.println(result);
}
public static String doPost(String url, String contentType, Map<Object, Object> data)
throws IOException, URISyntaxException, InterruptedException {
HttpClient client = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.ALWAYS).build();
BodyPublisher publisher = null;
if (contentType.startsWith("multipart/form-data")) {
String boundary = contentType.substring(contentType.lastIndexOf("=") + 1);
publisher = MoreBodyPublishers.ofMimeMultipartData(data, boundary);
} else if (contentType.equals("application/x-www-form-urlencoded")) {
publisher = MoreBodyPublishers.ofFormData(data);
} else {
contentType = "application/json";
publisher = MoreBodyPublishers.ofSimpleJSON(data);
}
HttpRequest request =
HttpRequest.newBuilder().uri(new URI(url)).header("Content-Type", contentType).POST(publisher).build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
return response.body();
}
}