diff --git a/README.md b/README.md index e092649..b6a2617 100644 --- a/README.md +++ b/README.md @@ -21,10 +21,5 @@ ## 特点 -- 默认会按照下面的优先级自行寻找底层实现,`OkHttp3 -> httpclient -> hutool-http` +- 默认会按照下面的优先级自行寻找底层实现,java 11 HttpClient -> OkHttp3 -> apache HttpClient -> hutool-http - 也可以自行实现 `com.xkcoding.http.support.Http` 接口,通过 `HttpUtil.setHttp(new MyHttpImpl())` 设置进来 - -## TODO - -- [ ] 集成 JDK11 的 HTTPClient - diff --git a/pom.xml b/pom.xml index 189076c..21a1356 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,6 @@ UTF-8 1.8 1.8 - 4.2.2 4.5.10 5.1.0 @@ -85,6 +84,49 @@ + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.0.0 + + + add-source + generate-sources + + add-source + + + + src/main/java11 + + + + + + + maven-jar-plugin + + + default-jar + package + + jar + + + + + + + java + java/net + java/net/http + java/net/http/* + + + + diff --git a/src/main/java/com/xkcoding/http/HttpUtil.java b/src/main/java/com/xkcoding/http/HttpUtil.java index aa7cd0d..94b1f18 100644 --- a/src/main/java/com/xkcoding/http/HttpUtil.java +++ b/src/main/java/com/xkcoding/http/HttpUtil.java @@ -40,16 +40,21 @@ public class HttpUtil { static { Http defaultProxy = null; + ClassLoader classLoader = HttpUtil.class.getClassLoader(); + // java 11 HttpClient + if (ClassUtil.isPresent("java.net.http.HttpClient", classLoader)) { + defaultProxy = new com.xkcoding.http.support.java11.HttpClientImpl(); + } // 基于 okhttp3 - if (ClassUtil.isPresent("okhttp3.OkHttpClient", HttpUtil.class.getClassLoader())) { + if (ClassUtil.isPresent("okhttp3.OkHttpClient", classLoader)) { defaultProxy = new OkHttp3Impl(); } // 基于 httpclient - else if (ClassUtil.isPresent("org.apache.http.impl.client.HttpClients", HttpUtil.class.getClassLoader())) { + else if (ClassUtil.isPresent("org.apache.http.impl.client.HttpClients", classLoader)) { defaultProxy = new HttpClientImpl(); } // 基于 hutool - else if (ClassUtil.isPresent("cn.hutool.http.HttpRequest", HttpUtil.class.getClassLoader())) { + else if (ClassUtil.isPresent("cn.hutool.http.HttpRequest", classLoader)) { defaultProxy = new HutoolImpl(); } proxy = defaultProxy; diff --git a/src/main/java/com/xkcoding/http/constants/Constants.java b/src/main/java/com/xkcoding/http/constants/Constants.java index 163db35..932afc1 100644 --- a/src/main/java/com/xkcoding/http/constants/Constants.java +++ b/src/main/java/com/xkcoding/http/constants/Constants.java @@ -43,6 +43,16 @@ public interface Constants { */ String CONTENT_TYPE_JSON = "application/json; charset=utf-8"; + /** + * Content-Type + */ + String CONTENT_TYPE = "Content-Type"; + + /** + * Content-Encoding + */ + String CONTENT_ENCODING = "Content-Encoding"; + /** * 空字符串 */ diff --git a/src/main/java/com/xkcoding/http/support/httpclient/HttpClientImpl.java b/src/main/java/com/xkcoding/http/support/httpclient/HttpClientImpl.java index 8d60eb7..71e9652 100644 --- a/src/main/java/com/xkcoding/http/support/httpclient/HttpClientImpl.java +++ b/src/main/java/com/xkcoding/http/support/httpclient/HttpClientImpl.java @@ -54,6 +54,10 @@ public HttpClientImpl() { this.httpClient = HttpClients.createDefault(); } + public HttpClientImpl(CloseableHttpClient httpClient) { + this.httpClient = httpClient; + } + private String exec(HttpRequestBase request) { // 设置超时时长 request.setConfig(RequestConfig.custom() diff --git a/src/main/java/com/xkcoding/http/support/java11/HttpClientImpl.java b/src/main/java/com/xkcoding/http/support/java11/HttpClientImpl.java new file mode 100644 index 0000000..f46ae27 --- /dev/null +++ b/src/main/java/com/xkcoding/http/support/java11/HttpClientImpl.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net). + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.xkcoding.http.support.java11; + +import com.xkcoding.http.constants.Constants; +import com.xkcoding.http.support.Http; +import com.xkcoding.http.support.HttpHeader; +import com.xkcoding.http.util.MapUtil; +import com.xkcoding.http.util.StringUtil; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.Map; + +/** + * java 11 HttpClient + * + * @author L.cm + */ +public class HttpClientImpl implements Http { + private final HttpClient client; + + public HttpClientImpl() { + this(HttpClient.newBuilder().connectTimeout(Duration.ofMillis(Constants.TIMEOUT)).build()); + } + + public HttpClientImpl(HttpClient client) { + this.client = client; + } + + private String exec(HttpRequest request) { + try { + return client.send(request, HttpResponse.BodyHandlers.ofString()).body(); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } + } + + /** + * GET 请求 + * + * @param url URL + * @return 结果 + */ + @Override + public String get(String url) { + return this.get(url, null, false); + } + + /** + * GET 请求 + * + * @param url URL + * @param params 参数 + * @param encode 是否需要 url encode + * @return 结果 + */ + @Override + public String get(String url, Map params, boolean encode) { + return this.get(url, params, null, encode); + } + + /** + * GET 请求 + * + * @param url URL + * @param params 参数 + * @param header 请求头 + * @param encode 是否需要 url encode + * @return 结果 + */ + @Override + public String get(String url, Map params, HttpHeader header, boolean encode) { + String baseUrl = StringUtil.appendIfNotContain(url, "?", "&"); + String reqUrl = baseUrl + MapUtil.parseMapToString(params, encode); + + HttpRequest.Builder builder = HttpRequest.newBuilder() + .uri(URI.create(reqUrl)) + .GET() + .timeout(Duration.ofMillis(Constants.TIMEOUT)); + + if (header != null) { + MapUtil.forEach(header.getHeaders(), builder::header); + } + + return exec(builder.build()); + } + + /** + * POST 请求 + * + * @param url URL + * @return 结果 + */ + @Override + public String post(String url) { + return this.post(url, null); + } + + /** + * POST 请求 + * + * @param url URL + * @param data JSON 参数 + * @return 结果 + */ + @Override + public String post(String url, String data) { + return this.post(url, data, null); + } + + /** + * POST 请求 + * + * @param url URL + * @param data JSON 参数 + * @param header 请求头 + * @return 结果 + */ + @Override + public String post(String url, String data, HttpHeader header) { + HttpRequest.Builder builder = HttpRequest.newBuilder() + .uri(URI.create(url)) + .POST(HttpRequest.BodyPublishers.noBody()) + .timeout(Duration.ofMillis(Constants.TIMEOUT)); + + if (StringUtil.isNotEmpty(data)) { + builder.POST(HttpRequest.BodyPublishers.ofString(data, Constants.DEFAULT_ENCODING)); + builder.header(Constants.CONTENT_ENCODING, Constants.DEFAULT_ENCODING.displayName()); + builder.header(Constants.CONTENT_TYPE, Constants.CONTENT_TYPE_JSON); + } else { + builder.POST(HttpRequest.BodyPublishers.noBody()); + } + + if (header != null) { + MapUtil.forEach(header.getHeaders(), builder::header); + } + + return this.exec(builder.build()); + } + + /** + * POST 请求 + * + * @param url URL + * @param params form 参数 + * @param encode 是否需要 url encode + * @return 结果 + */ + @Override + public String post(String url, Map params, boolean encode) { + return this.post(url, params, null, encode); + } + + /** + * POST 请求 + * + * @param url URL + * @param params form 参数 + * @param header 请求头 + * @param encode 是否需要 url encode + * @return 结果 + */ + @Override + public String post(String url, Map params, HttpHeader header, boolean encode) { + String baseUrl = StringUtil.appendIfNotContain(url, "?", "&"); + String reqUrl = baseUrl + MapUtil.parseMapToString(params, encode); + return this.post(reqUrl, null, header); + } +} diff --git a/src/main/java/com/xkcoding/http/support/okhttp3/OkHttp3Impl.java b/src/main/java/com/xkcoding/http/support/okhttp3/OkHttp3Impl.java index ea64fbb..48f048d 100644 --- a/src/main/java/com/xkcoding/http/support/okhttp3/OkHttp3Impl.java +++ b/src/main/java/com/xkcoding/http/support/okhttp3/OkHttp3Impl.java @@ -39,12 +39,17 @@ public class OkHttp3Impl implements Http { private final OkHttpClient httpClient; public static final MediaType CONTENT_TYPE_JSON = MediaType.get(Constants.CONTENT_TYPE_JSON); + public OkHttp3Impl() { - this.httpClient = new OkHttpClient().newBuilder() + this(new OkHttpClient().newBuilder() .connectTimeout(Duration.ofMillis(Constants.TIMEOUT)) .writeTimeout(Duration.ofMillis(Constants.TIMEOUT)) .readTimeout(Duration.ofMillis(Constants.TIMEOUT)) - .build(); + .build()); + } + + public OkHttp3Impl(OkHttpClient httpClient) { + this.httpClient = httpClient; } private String exec(Request request) { diff --git a/src/main/java11/java.net.http/HttpClient.java b/src/main/java11/java.net.http/HttpClient.java new file mode 100644 index 0000000..727833a --- /dev/null +++ b/src/main/java11/java.net.http/HttpClient.java @@ -0,0 +1,24 @@ +package java.net.http; + +import java.io.IOException; +import java.time.Duration; + +/** + * For the Java 8 compatibility when compiled with JDK 11+. + * + * @author L.cm + */ +public abstract class HttpClient { + + public static HttpClient.Builder newBuilder() { + return null; + } + + public abstract HttpResponse send(HttpRequest request, HttpResponse.BodyHandler responseBodyHandler) throws IOException, InterruptedException; + + public interface Builder { + Builder connectTimeout(Duration duration); + + HttpClient build(); + } +} diff --git a/src/main/java11/java.net.http/HttpRequest.java b/src/main/java11/java.net.http/HttpRequest.java new file mode 100644 index 0000000..196ae98 --- /dev/null +++ b/src/main/java11/java.net.http/HttpRequest.java @@ -0,0 +1,48 @@ +package java.net.http; + +import java.net.URI; +import java.nio.charset.Charset; +import java.time.Duration; + +/** + * For the Java 8 compatibility when compiled with JDK 11+. + * + * @author L.cm + */ +public class HttpRequest { + + public static HttpRequest.Builder newBuilder() { + return null; + } + + public interface BodyPublisher { + } + + public static class BodyPublishers { + public static BodyPublisher ofString(String body) { + return null; + } + + public static BodyPublisher ofString(String s, Charset charset) { + return null; + } + + public static BodyPublisher noBody() { + return null; + } + } + + public interface Builder { + Builder uri(URI uri); + + Builder header(String name, String value); + + Builder timeout(Duration duration); + + Builder GET(); + + Builder POST(HttpRequest.BodyPublisher bodyPublisher); + + HttpRequest build(); + } +} diff --git a/src/main/java11/java.net.http/HttpResponse.java b/src/main/java11/java.net.http/HttpResponse.java new file mode 100644 index 0000000..21f7a2e --- /dev/null +++ b/src/main/java11/java.net.http/HttpResponse.java @@ -0,0 +1,21 @@ +package java.net.http; + +/** + * For the Java 8 compatibility when compiled with JDK 11+. + * + * @author L.cm + */ +public interface HttpResponse { + + T body(); + + interface BodyHandler { + + } + + class BodyHandlers { + public static BodyHandler ofString() { + return null; + } + } +}