diff --git a/docs/docs/user_docs/other/issue.md b/docs/docs/user_docs/other/issue.md index d50d924c..11f48a12 100644 --- a/docs/docs/user_docs/other/issue.md +++ b/docs/docs/user_docs/other/issue.md @@ -8,7 +8,6 @@ sidebar_position: 2 - 控制台线程池管理和线程池实例的区别 - 示例项目为什么会有跨域请求 - 更新代码后运行时服务端SQL报错 -- okHttp3 call.timeout() 方法不存在 - 生产环境如何不启用动态线程池 - Server 端宕机会影响 Client 运行么 - Hippo4J 的发布方式是怎样的?如何选择正确的版本 @@ -48,18 +47,6 @@ Hippo4J 按照租户、项目、线程池的维度划分。 > 友情提示:每次执行数据库表或数据变更时,一定要保持提前备份的好习惯。 -## okHttp3 call.timeout() 方法不存在 - -请确保 okHttp3 依赖版本号 >= 3.12.0 - -```xml - - com.squareup.okhttp3 - okhttp - 3.12.0 - -``` - ## 生产环境如何不启用动态线程池 测试环境已经引入 Hippo4J,暂时不打算上线生产环境。 diff --git a/hippo4j-common/pom.xml b/hippo4j-common/pom.xml index b127ba64..36d6d3b1 100644 --- a/hippo4j-common/pom.xml +++ b/hippo4j-common/pom.xml @@ -62,9 +62,5 @@ com.github.dozermapper dozer-core - - com.squareup.okhttp3 - okhttp - diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/api/JsonFacade.java b/hippo4j-common/src/main/java/cn/hippo4j/common/api/JsonFacade.java index c5f3213f..374d3f32 100644 --- a/hippo4j-common/src/main/java/cn/hippo4j/common/api/JsonFacade.java +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/api/JsonFacade.java @@ -63,4 +63,11 @@ public interface JsonFacade { * @return */ List parseArray(String text, Class clazz); + + /** + * validate Json. + * @param text + * @return + */ + boolean isJson(String text); } diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/constant/Constants.java b/hippo4j-common/src/main/java/cn/hippo4j/common/constant/Constants.java index 12e9ef5a..8c225e33 100644 --- a/hippo4j-common/src/main/java/cn/hippo4j/common/constant/Constants.java +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/constant/Constants.java @@ -38,11 +38,13 @@ public class Constants { public static final String DEFAULT_NAMESPACE_ID = "public"; + public static final String ENCODE = "UTF-8"; + public static final String NULL = ""; public static final String UP = "UP"; - public static final String ENCODE = "UTF-8"; + public static final String CONTENT_TYPE = "Content-Type"; public static final int CONFIG_LONG_POLL_TIMEOUT = 30000; diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpHeaderConsts.java b/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpHeaderConsts.java new file mode 100644 index 00000000..d75246f4 --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpHeaderConsts.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 cn.hippo4j.common.constant; + +/** + * header constants. + */ +public interface HttpHeaderConsts { + + String CLIENT_VERSION_HEADER = "Client-Version"; + String USER_AGENT_HEADER = "User-Agent"; + String REQUEST_SOURCE_HEADER = "Request-Source"; + String CONTENT_TYPE = "Content-Type"; + String CONTENT_LENGTH = "Content-Length"; + String ACCEPT_CHARSET = "Accept-Charset"; + String ACCEPT_ENCODING = "Accept-Encoding"; + String CONTENT_ENCODING = "Content-Encoding"; + String CONNECTION = "Requester"; + String REQUEST_ID = "RequestId"; + String REQUEST_MODULE = "Request-Module"; + +} diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpMediaType.java b/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpMediaType.java new file mode 100644 index 00000000..0b0d9843 --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpMediaType.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 cn.hippo4j.common.constant; + +import cn.hippo4j.common.toolkit.StringUtil; + +/** + * Http Media types. + * + * @author Rongzhen Yan + */ +public final class HttpMediaType { + + public static final String APPLICATION_ATOM_XML = "application/atom+xml"; + + public static final String APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded;charset=UTF-8"; + + public static final String APPLICATION_OCTET_STREAM = "application/octet-stream"; + + public static final String APPLICATION_SVG_XML = "application/svg+xml"; + + public static final String APPLICATION_XHTML_XML = "application/xhtml+xml"; + + public static final String APPLICATION_XML = "application/xml;charset=UTF-8"; + + public static final String APPLICATION_JSON = "application/json;charset=UTF-8"; + + public static final String MULTIPART_FORM_DATA = "multipart/form-data;charset=UTF-8"; + + public static final String TEXT_HTML = "text/html;charset=UTF-8"; + + public static final String TEXT_PLAIN = "text/plain;charset=UTF-8"; + + private HttpMediaType(String type, String charset) { + this.type = type; + this.charset = charset; + } + + /** + * content type. + */ + private final String type; + + /** + * content type charset. + */ + private final String charset; + + /** + * Parse the given String contentType into a {@code MediaType} object. + * + * @param contentType mediaType + * @return MediaType + */ + public static HttpMediaType valueOf(String contentType) { + if (StringUtil.isEmpty(contentType)) { + throw new IllegalArgumentException("MediaType must not be empty"); + } + String[] values = contentType.split(";"); + String charset = Constants.ENCODE; + for (String value : values) { + if (value.startsWith("charset=")) { + charset = value.substring("charset=".length()); + } + } + return new HttpMediaType(values[0], charset); + } + + /** + * Use the given contentType and charset to assemble into a {@code MediaType} object. + * + * @param contentType contentType + * @param charset charset + * @return MediaType + */ + public static HttpMediaType valueOf(String contentType, String charset) { + if (StringUtil.isEmpty(contentType)) { + throw new IllegalArgumentException("MediaType must not be empty"); + } + String[] values = contentType.split(";"); + return new HttpMediaType(values[0], StringUtil.isEmpty(charset) ? Constants.ENCODE : charset); + } + + public String getType() { + return type; + } + + public String getCharset() { + return charset; + } + + @Override + public String toString() { + return type + ";charset=" + charset; + } +} diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpMethod.java b/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpMethod.java new file mode 100644 index 00000000..fde14dfe --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpMethod.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 cn.hippo4j.common.constant; + +/** + * Http method constants. + * + * @author Rongzhen Yan + */ +public class HttpMethod { + + public static final String GET = "GET"; + + public static final String HEAD = "HEAD"; + + public static final String POST = "POST"; + + public static final String PUT = "PUT"; + + public static final String PATCH = "PATCH"; + + public static final String DELETE = "DELETE"; + + public static final String OPTIONS = "OPTIONS"; + + public static final String TRACE = "TRACE"; +} diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpResponseCode.java b/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpResponseCode.java new file mode 100644 index 00000000..28bc4d95 --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpResponseCode.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 cn.hippo4j.common.constant; + +/** + * Http状态码常量 + * @author Rongzhen Yan + */ +public interface HttpResponseCode { + + int SC_CONTINUE = 100; + int SC_SWITCHING_PROTOCOLS = 101; + int SC_OK = 200; + int SC_CREATED = 201; + int SC_ACCEPTED = 202; + int SC_NON_AUTHORITATIVE_INFORMATION = 203; + int SC_NO_CONTENT = 204; + int SC_RESET_CONTENT = 205; + int SC_PARTIAL_CONTENT = 206; + int SC_MULTIPLE_CHOICES = 300; + int SC_MOVED_PERMANENTLY = 301; + int SC_MOVED_TEMPORARILY = 302; + int SC_FOUND = 302; + int SC_SEE_OTHER = 303; + int SC_NOT_MODIFIED = 304; + int SC_USE_PROXY = 305; + int SC_TEMPORARY_REDIRECT = 307; + int SC_BAD_REQUEST = 400; + int SC_UNAUTHORIZED = 401; + int SC_PAYMENT_REQUIRED = 402; + int SC_FORBIDDEN = 403; + int SC_NOT_FOUND = 404; + int SC_METHOD_NOT_ALLOWED = 405; + int SC_NOT_ACCEPTABLE = 406; + int SC_PROXY_AUTHENTICATION_REQUIRED = 407; + int SC_REQUEST_TIMEOUT = 408; + int SC_CONFLICT = 409; + int SC_GONE = 410; + int SC_LENGTH_REQUIRED = 411; + int SC_PRECONDITION_FAILED = 412; + int SC_REQUEST_ENTITY_TOO_LARGE = 413; + int SC_REQUEST_URI_TOO_LONG = 414; + int SC_UNSUPPORTED_MEDIA_TYPE = 415; + int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416; + int SC_EXPECTATION_FAILED = 417; + int SC_INTERNAL_SERVER_ERROR = 500; + int SC_NOT_IMPLEMENTED = 501; + int SC_BAD_GATEWAY = 502; + int SC_SERVICE_UNAVAILABLE = 503; + int SC_GATEWAY_TIMEOUT = 504; + int SC_HTTP_VERSION_NOT_SUPPORTED = 505; +} diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/HttpClientUtil.java b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/HttpClientUtil.java deleted file mode 100644 index 98914223..00000000 --- a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/HttpClientUtil.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 cn.hippo4j.common.toolkit; - -import cn.hippo4j.common.web.exception.ServiceException; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import okhttp3.*; -import org.springframework.util.CollectionUtils; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -/** - * HttpClient util. - */ -@Slf4j -public class HttpClientUtil { - - private OkHttpClient hippo4JOkHttpClient; - - private static AtomicReference reference = new AtomicReference<>(); - - private MediaType jsonMediaType = MediaType.parse("application/json; charset=utf-8"); - - private static int HTTP_OK_CODE = 200; - - private HttpClientUtil() { - OkHttpClient.Builder build = new OkHttpClient.Builder(); - build.connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(30, TimeUnit.SECONDS) - .build(); - supportHttps(build); - this.hippo4JOkHttpClient = build.build(); - } - - public static HttpClientUtil build() { - if (reference.get() == null) { - reference.compareAndSet(null, new HttpClientUtil()); - } - return reference.get(); - } - - /** - * Get. - * - * @param url - * @return - */ - @SneakyThrows - public String get(String url) { - try { - return new String(doGet(url), "utf-8"); - } catch (Exception e) { - log.error("HttpGet call failed. {}", url, e); - throw e; - } - } - - /** - * Get request, supports adding query string. - * - * @param url - * @param queryString - * @return - */ - public String get(String url, Map queryString) { - String fullUrl = buildUrl(url, queryString); - return get(fullUrl); - } - - /** - * Deserialize directly after getting Json. - * - * @param url - * @param clazz - * @return - */ - public T restApiGet(String url, Class clazz) { - String resp = get(url); - return JSONUtil.parseObject(resp, clazz); - } - - /** - * Call health check. - * - * @param url - * @param clazz - * @param - * @return - */ - @SneakyThrows - public T restApiGetHealth(String url, Class clazz) { - String resp = new String(doGet(url), "utf-8"); - return JSONUtil.parseObject(resp, clazz); - } - - /** - * Get request, supports query string. - * - * @param url - * @param queryString - * @param clazz - * @param - * @return - */ - public T restApiGet(String url, Map queryString, Class clazz) { - String fullUrl = buildUrl(url, queryString); - String resp = get(fullUrl); - return JSONUtil.parseObject(resp, clazz); - } - - /** - * Rest interface Post call. - * - * @param url - * @param body - * @return - */ - public String restApiPost(String url, Object body) { - try { - return doPost(url, body); - } catch (Exception e) { - log.error("HttpPost call failed. {} message: {}", url, e.getMessage()); - throw e; - } - } - - /** - * Rest interface Post call. Deserialize the return value directly. - * - * @param url - * @param body - * @return - */ - public T restApiPost(String url, Object body, Class clazz) { - String resp = restApiPost(url, body); - return JSONUtil.parseObject(resp, clazz); - } - - /** - * Constructs a complete Url from the query string. - * - * @param url - * @param queryString - * @return - */ - public String buildUrl(String url, Map queryString) { - if (null == queryString) { - return url; - } - StringBuilder builder = new StringBuilder(url); - boolean isFirst = true; - for (Map.Entry entry : queryString.entrySet()) { - String key = entry.getKey(); - if (key != null && entry.getValue() != null) { - if (isFirst) { - isFirst = false; - builder.append("?"); - } else { - builder.append("&"); - } - builder.append(key) - .append("=") - .append(queryString.get(key)); - } - } - return builder.toString(); - } - - @SneakyThrows - private String doPost(String url, Object body) { - String bodyContent; - if (body instanceof String) { - bodyContent = (String) body; - } else { - bodyContent = JSONUtil.toJSONString(body); - } - RequestBody requestBody = RequestBody.create(jsonMediaType, bodyContent); - Request request = new Request.Builder() - .url(url) - .post(requestBody) - .build(); - try (Response resp = hippo4JOkHttpClient.newCall(request).execute()) { - try (ResponseBody responseBody = resp.body()) { - if (resp.code() != HTTP_OK_CODE) { - String msg = String.format("HttpPost response code error. [code] %s [url] %s [body] %s", resp.code(), url, bodyContent); - throw new ServiceException(msg); - } - return responseBody.string(); - } - } - } - - @SneakyThrows - private byte[] doGet(String url) { - Request request = new Request.Builder().get().url(url).build(); - try (Response resp = hippo4JOkHttpClient.newCall(request).execute()) { - try (ResponseBody responseBody = resp.body()) { - if (resp.code() != HTTP_OK_CODE) { - String msg = String.format("HttpGet response code error. [code] %s [url] %s", resp.code(), url); - throw new ServiceException(msg); - } - return responseBody.bytes(); - } - } - } - - @SneakyThrows - public T restApiGetByThreadPool(String url, Map headers, Map paramValues, Long readTimeoutMs, Class clazz) { - String buildUrl = buildUrl(url, paramValues); - Request.Builder builder = new Request.Builder().get(); - if (!CollectionUtils.isEmpty(headers)) { - builder.headers(Headers.of(headers)); - } - Request request = builder.url(buildUrl).build(); - Call call = hippo4JOkHttpClient.newCall(request); - // TODO Plan to optimize the timout api because its version is too high. - call.timeout().timeout(readTimeoutMs, TimeUnit.MILLISECONDS); - try (Response resp = call.execute()) { - try (ResponseBody responseBody = resp.body()) { - if (resp.code() != HTTP_OK_CODE) { - String msg = String.format("HttpGet response code error. [code] %s [url] %s", resp.code(), url); - log.error(msg); - throw new ServiceException(msg); - } - return JSONUtil.parseObject(responseBody.string(), clazz); - } - } - } - - @SneakyThrows - public T restApiPostByThreadPool(String url, Map headers, Map paramValues, Long readTimeoutMs, Class clazz) { - String buildUrl = buildUrl(url, paramValues); - Request request = new Request.Builder() - .url(buildUrl) - .headers(Headers.of(headers)) - .post(RequestBody.create(jsonMediaType, "")) - .build(); - Call call = hippo4JOkHttpClient.newCall(request); - // TODO Plan to optimize the timout api because its version is too high. - call.timeout().timeout(readTimeoutMs, TimeUnit.MILLISECONDS); - try (Response resp = call.execute()) { - try (ResponseBody responseBody = resp.body()) { - if (resp.code() != HTTP_OK_CODE) { - String msg = String.format("HttpPost response code error. [code] %s [url] %s.", resp.code(), url); - log.error(msg); - throw new ServiceException(msg); - } - return JSONUtil.parseObject(responseBody.string(), clazz); - } - } - } - - @SneakyThrows - private void supportHttps(OkHttpClient.Builder builder) { - final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { - - @Override - public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) { - } - - @Override - public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) { - } - - @Override - public java.security.cert.X509Certificate[] getAcceptedIssuers() { - return new java.security.cert.X509Certificate[]{}; - } - }}; - - final SSLContext sslContext = SSLContext.getInstance("SSL"); - sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); - final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); - builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]); - builder.hostnameVerifier((hostname, session) -> true); - } -} diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/IoUtils.java b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/IoUtils.java new file mode 100644 index 00000000..c32125d6 --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/IoUtils.java @@ -0,0 +1,341 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 cn.hippo4j.common.toolkit; + +import cn.hippo4j.common.constant.Constants; +import lombok.SneakyThrows; + +import java.io.*; +import java.net.HttpURLConnection; +import java.nio.channels.FileChannel; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +/** + * IO related tool methods. + * + * @author nacos + */ +public class IoUtils { + + /** + * Try decompress by GZIP from stream. + * + * @param raw compress stream + * @return byte array after decompress + */ + public static byte[] tryDecompress(InputStream raw) throws IOException { + try ( + GZIPInputStream gis = new GZIPInputStream(raw); + ByteArrayOutputStream out = new ByteArrayOutputStream()) { + copy(gis, out); + return out.toByteArray(); + } + } + + /** + * Try decompress by GZIP from byte array. + * + * @param raw compressed byte array + * @return byte array after decompress + * @throws Exception exception + */ + public static byte[] tryDecompress(byte[] raw) throws Exception { + if (!isGzipStream(raw)) { + return raw; + } + try ( + GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(raw)); + ByteArrayOutputStream out = new ByteArrayOutputStream()) { + copy(gis, out); + return out.toByteArray(); + } + } + + /** + * Try compress by GZIP for string. + * + * @param str strings to be compressed. + * @param encoding encoding. + * @return byte[] + */ + public static byte[] tryCompress(String str, String encoding) { + if (str == null || str.length() == 0) { + return new byte[0]; + } + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try (GZIPOutputStream gzip = new GZIPOutputStream(out)) { + gzip.write(str.getBytes(encoding)); + } catch (Exception e) { + e.printStackTrace(); + } + return out.toByteArray(); + } + + private static BufferedReader toBufferedReader(Reader reader) { + return reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader); + } + + /** + * Write string to a file. + * + * @param file file + * @param data string + * @param encoding encoding of string + * @throws IOException io exception + */ + public static void writeStringToFile(File file, String data, String encoding) throws IOException { + try (OutputStream os = new FileOutputStream(file)) { + os.write(data.getBytes(encoding)); + os.flush(); + } + } + + /** + * Read lines. + * + * @param input reader + * @return list of line + * @throws IOException io exception + */ + public static List readLines(Reader input) throws IOException { + BufferedReader reader = toBufferedReader(input); + List list = new ArrayList<>(); + while (true) { + String line = reader.readLine(); + if (null != line) { + if (StringUtil.isNotEmpty(line)) { + list.add(line.trim()); + } + } else { + break; + } + } + return list; + } + + /** + * To string from stream. + * + * @param input stream + * @param encoding charset of stream + * @return string + * @throws IOException io exception + */ + @SneakyThrows + public static String toString(InputStream input, String encoding) { + if (input == null) { + return StringUtil.EMPTY; + } + return (null == encoding) ? toString(new InputStreamReader(input, Constants.ENCODE)) + : toString(new InputStreamReader(input, encoding)); + } + + /** + * To string from reader. + * + * @param reader reader + * @return string + * @throws IOException io exception + */ + public static String toString(Reader reader) throws IOException { + CharArrayWriter sw = new CharArrayWriter(); + copy(reader, sw); + return sw.toString(); + } + + /** + * Copy data. + * + * @param input source + * @param output target + * @return copy size + * @throws IOException io exception + */ + public static long copy(Reader input, Writer output) throws IOException { + char[] buffer = new char[1 << 12]; + long count = 0; + for (int n = 0; (n = input.read(buffer)) >= 0;) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + /** + * Copy data. + * + * @param input source + * @param output target + * @return copy size + * @throws IOException io exception + */ + public static long copy(InputStream input, OutputStream output) throws IOException { + byte[] buffer = new byte[1024]; + int bytesRead; + int totalBytes = 0; + while ((bytesRead = input.read(buffer)) != -1) { + output.write(buffer, 0, bytesRead); + + totalBytes += bytesRead; + } + + return totalBytes; + } + + /** + * Delete file or dir. + * + *

If is dir, clean directory, do not delete dir. + * + *

If is file, delete file. + * + * @param fileOrDir file or dir + * @throws IOException io exception + */ + public static void delete(File fileOrDir) throws IOException { + if (fileOrDir == null) { + return; + } + + if (fileOrDir.isDirectory()) { + cleanDirectory(fileOrDir); + } else { + if (fileOrDir.exists()) { + boolean isDeleteOk = fileOrDir.delete(); + if (!isDeleteOk) { + throw new IOException("delete fail"); + } + } + } + } + + /** + * 清理目录下的内容. Clean content under directory. + * + * @param directory directory + * @throws IOException io exception + */ + public static void cleanDirectory(File directory) throws IOException { + if (!directory.exists()) { + String message = directory + " does not exist"; + throw new IllegalArgumentException(message); + } + + if (!directory.isDirectory()) { + String message = directory + " is not a directory"; + throw new IllegalArgumentException(message); + } + + File[] files = directory.listFiles(); + // null if security restricted + if (files == null) { + throw new IOException("Failed to list contents of " + directory); + } + + IOException exception = null; + for (File file : files) { + try { + delete(file); + } catch (IOException ioe) { + exception = ioe; + } + } + + if (null != exception) { + throw exception; + } + } + + /** + * Copy File. + * + * @param source source file path + * @param target target file path + * @throws IOException io exception + */ + public static void copyFile(String source, String target) throws IOException { + File sf = new File(source); + if (!sf.exists()) { + throw new IllegalArgumentException("source file does not exist."); + } + File tf = new File(target); + if (!tf.getParentFile().mkdirs()) { + throw new RuntimeException("failed to create parent directory."); + } + if (!tf.exists() && !tf.createNewFile()) { + throw new RuntimeException("failed to create target file."); + } + try ( + FileChannel sc = new FileInputStream(sf).getChannel(); + FileChannel tc = new FileOutputStream(tf).getChannel()) { + sc.transferTo(0, sc.size(), tc); + } + } + + /** + * Judge whether is Gzip stream. + * + * @param bytes byte array + * @return true if is gzip, otherwise false + */ + public static boolean isGzipStream(byte[] bytes) { + + int minByteArraySize = 2; + if (bytes == null || bytes.length < minByteArraySize) { + return false; + } + + return GZIPInputStream.GZIP_MAGIC == ((bytes[1] << 8 | bytes[0]) & 0xFFFF); + } + + /** + * Close http connection quietly. + * + * @param connection http connection + */ + public static void closeQuietly(HttpURLConnection connection) { + if (connection != null) { + try { + closeQuietly(connection.getInputStream()); + } catch (Exception ignore) { + } + } + } + + /** + * Close closable object quietly. + * + * @param closeable http connection + */ + public static void closeQuietly(Closeable closeable) { + try { + if (closeable != null) { + closeable.close(); + } + } catch (IOException ignored) { + } + } + + public static void closeQuietly(Closeable... closeable) { + Arrays.stream(closeable).forEach(IoUtils::closeQuietly); + } +} diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/JSONUtil.java b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/JSONUtil.java index 56af7f81..a4392891 100644 --- a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/JSONUtil.java +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/JSONUtil.java @@ -56,4 +56,11 @@ public class JSONUtil { } return JSON_FACADE.parseArray(text, clazz); } + + public static boolean isJson(String json) { + if (StringUtil.isBlank(json)) { + return false; + } + return JSON_FACADE.isJson(json); + } } diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/JacksonHandler.java b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/JacksonHandler.java index 1ba3d273..b5e34d32 100644 --- a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/JacksonHandler.java +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/JacksonHandler.java @@ -20,11 +20,9 @@ package cn.hippo4j.common.toolkit; import cn.hippo4j.common.api.JsonFacade; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.type.CollectionType; import lombok.SneakyThrows; @@ -74,4 +72,14 @@ public class JacksonHandler implements JsonFacade { CollectionType collectionType = MAPPER.getTypeFactory().constructCollectionType(ArrayList.class, clazz); return MAPPER.readValue(text, collectionType); } + + @Override + public boolean isJson(String text) { + try { + MAPPER.readTree(text); + return true; + } catch (JsonProcessingException jpe) { + return false; + } + } } diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/MapUtil.java b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/MapUtil.java new file mode 100644 index 00000000..63108237 --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/MapUtil.java @@ -0,0 +1,169 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 cn.hippo4j.common.toolkit; + +import java.util.Collection; +import java.util.Dictionary; +import java.util.Map; +import java.util.Objects; +import java.util.function.BiFunction; +import java.util.function.Predicate; + +/** + * Map utils. + */ +public class MapUtil { + + /** + * Null-safe check if the specified Dictionary is empty. + * + *

Null returns true. + * + * @param map the collection to check, may be null + * @return true if empty or null + */ + public static boolean isEmpty(Map map) { + return (map == null || map.isEmpty()); + } + + /** + * Null-safe check if the specified Dictionary is empty. + * + *

Null returns true. + * + * @param coll the collection to check, may be null + * @return true if empty or null + */ + public static boolean isEmpty(Dictionary coll) { + return (coll == null || coll.isEmpty()); + } + + /** + * Null-safe check if the specified Dictionary is not empty. + * + *

Null returns false. + * + * @param map the collection to check, may be null + * @return true if non-null and non-empty + */ + public static boolean isNotEmpty(Map map) { + return !isEmpty(map); + } + + /** + * Null-safe check if the specified Dictionary is not empty. + * + *

Null returns false. + * + * @param coll the collection to check, may be null + * @return true if non-null and non-empty + */ + public static boolean isNotEmpty(Dictionary coll) { + return !isEmpty(coll); + } + + /** + * Put into map if value is not null. + * + * @param target target map + * @param key key + * @param value value + */ + public static void putIfValNoNull(Map target, Object key, Object value) { + Objects.requireNonNull(key, "key"); + if (value != null) { + target.put(key, value); + } + } + + /** + * Put into map if value is not empty. + * + * @param target target map + * @param key key + * @param value value + */ + public static void putIfValNoEmpty(Map target, Object key, Object value) { + Objects.requireNonNull(key, "key"); + if (value instanceof String) { + if (StringUtil.isNotEmpty((String) value)) { + target.put(key, value); + } + return; + } + if (value instanceof Collection) { + if (CollectionUtil.isNotEmpty((Collection) value)) { + target.put(key, value); + } + return; + } + if (value instanceof Map) { + if (isNotEmpty((Map) value)) { + target.put(key, value); + } + return; + } + if (value instanceof Dictionary) { + if (isNotEmpty((Dictionary) value)) { + target.put(key, value); + } + } + } + + /** + * ComputeIfAbsent lazy load. + * + * @param target target Map data. + * @param key map key. + * @param mappingFunction function which is need to be executed. + * @param param1 function's parameter value1. + * @param param2 function's parameter value1. + * @return + */ + public static V computeIfAbsent(Map target, K key, BiFunction mappingFunction, C param1, + T param2) { + + Objects.requireNonNull(target, "target"); + Objects.requireNonNull(key, "key"); + Objects.requireNonNull(mappingFunction, "mappingFunction"); + Objects.requireNonNull(param1, "param1"); + Objects.requireNonNull(param2, "param2"); + + V val = target.get(key); + if (val == null) { + V ret = mappingFunction.apply(param1, param2); + target.put(key, ret); + return ret; + } + return val; + } + + /** + * remove value, Thread safety depends on whether the Map is a thread-safe Map. + * + * @param map map + * @param key key + * @param removeJudge judge this key can be remove + * @param key type + * @param value type + * @return value + */ + public static V removeKey(Map map, K key, Predicate removeJudge) { + return map.computeIfPresent(key, (k, v) -> removeJudge.test(v) ? null : v); + } +} diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/Header.java b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/Header.java new file mode 100644 index 00000000..ad155a9f --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/Header.java @@ -0,0 +1,200 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 cn.hippo4j.common.toolkit.http; + +import cn.hippo4j.common.constant.Constants; +import cn.hippo4j.common.constant.HttpHeaderConsts; +import cn.hippo4j.common.constant.HttpMediaType; +import cn.hippo4j.common.toolkit.MapUtil; +import cn.hippo4j.common.toolkit.StringUtil; + +import java.util.*; + +/** + * Http header. + * + * @author liaochuntao + */ +public class Header { + + public static final Header EMPTY = Header.newInstance(); + + private final Map header; + + private final Map> originalResponseHeader; + + private static final String DEFAULT_CHARSET = "UTF-8"; + + private static final String DEFAULT_ENCODING = "gzip"; + + private Header() { + header = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + originalResponseHeader = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + addParam(HttpHeaderConsts.CONTENT_TYPE, HttpMediaType.APPLICATION_JSON); + addParam(HttpHeaderConsts.ACCEPT_CHARSET, DEFAULT_CHARSET); + // addParam(HttpHeaderConsts.ACCEPT_ENCODING, DEFAULT_ENCODING); + } + + public static Header newInstance() { + return new Header(); + } + + /** + * Add the key and value to the header. + * + * @param key the key + * @param value the value + * @return header + */ + public Header addParam(String key, String value) { + if (StringUtil.isNotEmpty(key)) { + header.put(key, value); + } + return this; + } + + public Header setContentType(String contentType) { + if (contentType == null) { + contentType = HttpMediaType.APPLICATION_JSON; + } + return addParam(HttpHeaderConsts.CONTENT_TYPE, contentType); + } + + public Header build() { + return this; + } + + public String getValue(String key) { + return header.get(key); + } + + public Map getHeader() { + return header; + } + + public Iterator> iterator() { + return header.entrySet().iterator(); + } + + /** + * Transfer to KV part list. The odd index is key and the even index is value. + * + * @return KV string list + */ + public List toList() { + List list = new ArrayList<>(header.size() * 2); + Iterator> iterator = iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + list.add(entry.getKey()); + list.add(entry.getValue()); + } + return list; + } + + /** + * Add all KV list to header. The odd index is key and the even index is value. + * + * @param list KV list + * @return header + */ + public Header addAll(List list) { + if ((list.size() & 1) != 0) { + throw new IllegalArgumentException("list size must be a multiple of 2"); + } + for (int i = 0; i < list.size();) { + String key = list.get(i++); + if (StringUtil.isNotEmpty(key)) { + header.put(key, list.get(i++)); + } + } + return this; + } + + /** + * Add all parameters to header. + * + * @param params parameters + */ + public void addAll(Map params) { + if (MapUtil.isNotEmpty(params)) { + for (Map.Entry entry : params.entrySet()) { + addParam(entry.getKey(), entry.getValue()); + } + } + } + + /** + * set original format response header. + * + *

Currently only corresponds to the response header of JDK. + * + * @param key original response header key + * @param values original response header values + */ + public void addOriginalResponseHeader(String key, List values) { + if (StringUtil.isNotEmpty(key)) { + this.originalResponseHeader.put(key, values); + addParam(key, values.get(0)); + } + } + + /** + * get original format response header. + * + *

Currently only corresponds to the response header of JDK. + * + * @return Map original response header + */ + public Map> getOriginalResponseHeader() { + return this.originalResponseHeader; + } + + public String getCharset() { + String acceptCharset = getValue(HttpHeaderConsts.ACCEPT_CHARSET); + if (acceptCharset == null) { + String contentType = getValue(HttpHeaderConsts.CONTENT_TYPE); + acceptCharset = StringUtil.isNotBlank(contentType) ? analysisCharset(contentType) : Constants.ENCODE; + } + return acceptCharset; + } + + private String analysisCharset(String contentType) { + String[] values = contentType.split(";"); + String charset = Constants.ENCODE; + if (values.length == 0) { + return charset; + } + for (String value : values) { + if (value.startsWith("charset=")) { + charset = value.substring("charset=".length()); + } + } + return charset; + } + + public void clear() { + header.clear(); + originalResponseHeader.clear(); + } + + @Override + public String toString() { + return "Header{" + "headerToMap=" + header + '}'; + } +} diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/HttpClientResponse.java b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/HttpClientResponse.java new file mode 100644 index 00000000..0afe2cd8 --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/HttpClientResponse.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 cn.hippo4j.common.toolkit.http; + +import java.io.Closeable; +import java.io.InputStream; + +/** + * Represents a client-side HTTP response. + * + * @author mai.jh + */ +public interface HttpClientResponse extends Closeable { + + /** + * Return the headers of this message. + * + * @return a corresponding HttpHeaders object (never {@code null}) + */ + Header getHeaders(); + + /** + * Return the body of the message as an input stream. + * + * @return String response body + */ + InputStream getBody(); + + /** + * Return the HTTP status code. + * + * @return the HTTP status as an integer + */ + int getStatusCode(); + + /** + * Return the HTTP status text of the response. + * + * @return the HTTP status text + */ + String getStatusText(); + + /** + * Return the body As string. + * @return + */ + String getBodyString(); + + /** + * close response InputStream. + */ + @Override + void close(); +} diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/HttpUtils.java b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/HttpUtils.java new file mode 100644 index 00000000..ac063e1c --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/HttpUtils.java @@ -0,0 +1,228 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 cn.hippo4j.common.toolkit.http; + +import cn.hippo4j.common.constant.Constants; +import cn.hippo4j.common.constant.HttpMediaType; +import cn.hippo4j.common.constant.HttpMethod; +import cn.hippo4j.common.constant.HttpResponseCode; +import cn.hippo4j.common.toolkit.IoUtils; +import cn.hippo4j.common.toolkit.JSONUtil; +import cn.hippo4j.common.toolkit.StringUtil; +import cn.hippo4j.common.toolkit.logtracing.LogMessage; +import cn.hippo4j.common.web.exception.ServiceException; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.util.Map; + +import static cn.hippo4j.common.constant.HttpHeaderConsts.CONTENT_LENGTH; + +/** + * Http request utilities. + * @author Rongzhen Yan + */ +@Slf4j +public class HttpUtils { + + private static final int CONNECT_TIMEOUT = 10000; + + private static final int READ_TIMEOUT = 300000; + + private HttpUtils() { + } + + public static T post(String url, Object body, Class clazz) { + String result = post(url, body); + return JSONUtil.parseObject(result, clazz); + } + + public static T post(String url, Object body, long timeoutMillis, Class clazz) { + String result = post(url, body, timeoutMillis); + return JSONUtil.parseObject(result, clazz); + } + + public static T post(String url, Map headers, Map params, long timeoutMillis, Class clazz) { + String result = execute(buildUrl(url, params), HttpMethod.POST, null, headers, timeoutMillis).getBodyString(); + return JSONUtil.parseObject(result, clazz); + } + + public static T post(String url, Map headers, Object body, long timeoutMillis, Class clazz) { + String result = execute(url, HttpMethod.POST, body, headers, timeoutMillis).getBodyString(); + return JSONUtil.parseObject(result, clazz); + } + + public static String post(String url, Object body) { + return execute(url, HttpMethod.POST, body, null).getBodyString(); + } + + public static String post(String url, Object body, long timeoutMillis) { + return execute(url, HttpMethod.POST, body, null, timeoutMillis).getBodyString(); + } + + public static String postJson(String url, String json) { + return executeJson(url, HttpMethod.POST, json, null).getBodyString(); + } + + public static String put(String url, Object body) { + return execute(url, HttpMethod.PUT, body, null).getBodyString(); + } + + public static String put(String url, Object body, Map headers) { + return execute(url, HttpMethod.PUT, body, headers).getBodyString(); + } + + public static T get(String url, Map headers, Map params, long readTimeoutMillis, Class clazz) { + String result = execute(buildUrl(url, params), HttpMethod.GET, null, headers, readTimeoutMillis).getBodyString(); + return JSONUtil.parseObject(result, clazz); + } + + public static String get(String url, Map params) { + return execute(buildUrl(url, params), HttpMethod.GET, null, null).getBodyString(); + } + + public static String get(String url) { + return execute(url, HttpMethod.GET, null, null).getBodyString(); + } + + public static T get(String url, Class clazz) { + return JSONUtil.parseObject(get(url), clazz); + } + + /** + * Constructs a complete Url from the query string. + * @param url + * @param queryString + * @return + */ + @SneakyThrows + public static String buildUrl(String url, Map queryString) { + if (null == queryString) { + return url; + } + StringBuilder builder = new StringBuilder(url); + boolean isFirst = true; + for (Map.Entry entry : queryString.entrySet()) { + String key = entry.getKey(); + if (key != null && entry.getValue() != null) { + if (isFirst) { + isFirst = false; + builder.append("?"); + } else { + builder.append("&"); + } + String value = URLEncoder.encode(queryString.get(key), Constants.ENCODE) + .replaceAll("\\+", "%20"); + builder.append(key) + .append("=") + .append(value); + } + } + return builder.toString(); + } + + public static HttpClientResponse execute(String url, String method, Object param, Map headers) { + HttpURLConnection connection = createConnection(url, method); + return doExecute(connection, param, headers); + } + + @SneakyThrows + public static HttpClientResponse doExecute(HttpURLConnection connection, Object body, Map headers) { + try { + if (headers != null) { + for (String key : headers.keySet()) { + connection.setRequestProperty(key, headers.get(key)); + } + } + String bodyString; + if (body instanceof String) { + bodyString = (String) body; + } else { + bodyString = JSONUtil.toJSONString(body); + } + if (!StringUtil.isEmpty(bodyString)) { + connection.setDoOutput(true); + byte[] b = bodyString.getBytes(); + connection.setRequestProperty(CONTENT_LENGTH, String.valueOf(b.length)); + OutputStream outputStream = connection.getOutputStream(); + outputStream.write(b, 0, b.length); + outputStream.flush(); + IoUtils.closeQuietly(outputStream); + } + connection.connect(); + JdkHttpClientResponse response = new JdkHttpClientResponse(connection); + if (HttpResponseCode.SC_OK != response.getStatusCode()) { + String msg = String.format("HttpPost response code error. [code] %s [url] %s [body] %s", response.getStatusCode(), connection.getURL(), response.getBodyString()); + throw new ServiceException(msg); + } + return response; + } catch (Throwable e) { + log.error(LogMessage.getInstance().setMsg("Http Call error.") + .kv("url", connection.getURL()) + .kv("method", connection.getRequestMethod()) + .kv("body", JSONUtil.toJSONString(body)) + .kv2String("headers", JSONUtil.toJSONString(headers)), e); + throw e; + } + } + + public static HttpClientResponse execute(String url, String method, Object body, Map headers, long timeout) { + HttpURLConnection connection = createConnection(url, method, timeout); + return doExecute(connection, body, headers); + } + + public static HttpClientResponse executeJson(String url, String method, String json, Map headers) { + if (!JSONUtil.isJson(json)) { + log.error(LogMessage.getInstance().setMsg("Http Call error.") + .kv("url", url) + .kv("method", method) + .kv("json", json) + .kv2String("headers", JSONUtil.toJSONString(headers))); + throw new ServiceException("invalid http json body, please check it again."); + } + return execute(url, method, json, headers); + } + + @SneakyThrows + private static HttpURLConnection createConnection(String url, String method) { + HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); + connection.setDoInput(true); + connection.setDoOutput(true); + connection.setConnectTimeout(CONNECT_TIMEOUT); + connection.setReadTimeout(READ_TIMEOUT); + connection.setRequestMethod(method); + connection.setRequestProperty(Constants.CONTENT_TYPE, HttpMediaType.APPLICATION_JSON); + return connection; + } + + @SneakyThrows + private static HttpURLConnection createConnection(String url, String method, long timeout) { + HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); + + connection.setDoInput(true); + connection.setDoOutput(true); + connection.setConnectTimeout(Integer.parseInt(String.valueOf(timeout))); + connection.setReadTimeout(Integer.parseInt(String.valueOf(timeout))); + connection.setRequestMethod(method); + connection.setRequestProperty(Constants.CONTENT_TYPE, HttpMediaType.APPLICATION_JSON); + return connection; + } +} diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/JdkHttpClientResponse.java b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/JdkHttpClientResponse.java new file mode 100644 index 00000000..6a55b245 --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/JdkHttpClientResponse.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 cn.hippo4j.common.toolkit.http; + +import cn.hippo4j.common.constant.Constants; +import cn.hippo4j.common.constant.HttpHeaderConsts; +import cn.hippo4j.common.toolkit.IoUtils; +import lombok.SneakyThrows; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.util.List; +import java.util.Map; + +/** + * Represents a client-side HTTP response with JDK implementation + * + * @author Rongzhen Yan + */ +public class JdkHttpClientResponse implements HttpClientResponse { + + private final HttpURLConnection conn; + + private InputStream responseStream; + + private Header responseHeader; + + private static final String CONTENT_ENCODING = "gzip"; + + public JdkHttpClientResponse(HttpURLConnection conn) { + this.conn = conn; + } + + @Override + public Header getHeaders() { + if (this.responseHeader == null) { + this.responseHeader = Header.newInstance(); + } + for (Map.Entry> entry : conn.getHeaderFields().entrySet()) { + this.responseHeader.addOriginalResponseHeader(entry.getKey(), entry.getValue()); + } + return this.responseHeader; + } + + @Override + @SneakyThrows + public InputStream getBody() { + Header headers = getHeaders(); + InputStream errorStream = this.conn.getErrorStream(); + this.responseStream = (errorStream != null ? errorStream : this.conn.getInputStream()); + String contentEncoding = headers.getValue(HttpHeaderConsts.CONTENT_ENCODING); + // Used to process http content_encoding, when content_encoding is GZIP, use GZIPInputStream + if (CONTENT_ENCODING.equals(contentEncoding)) { + byte[] bytes = IoUtils.tryDecompress(this.responseStream); + return new ByteArrayInputStream(bytes); + } + return this.responseStream; + } + + @Override + @SneakyThrows + public int getStatusCode() { + return this.conn.getResponseCode(); + } + + @Override + @SneakyThrows + public String getStatusText() { + return this.conn.getResponseMessage(); + } + + @Override + public String getBodyString() { + return IoUtils.toString(this.getBody(), Constants.ENCODE); + } + + @Override + public void close() { + IoUtils.closeQuietly(this.responseStream); + } +} diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/logtracing/LogMessage.java b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/logtracing/LogMessage.java new file mode 100644 index 00000000..bacbada2 --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/logtracing/LogMessage.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 cn.hippo4j.common.toolkit.logtracing; + +import org.slf4j.helpers.FormattingTuple; +import org.slf4j.helpers.MessageFormatter; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 日志KV打印框架 + * @author Rongzhen Yan + */ +public class LogMessage { + + private Map kvs = new ConcurrentHashMap<>(); + private String msg = ""; + + private LogMessage() { + } + + public static LogMessage getInstance() { + return new LogMessage(); + } + + public LogMessage setMsg(String msg) { + this.msg = msg; + return this; + } + + public String msg(String msg, Object... args) { + LogMessage l = new LogMessage(); + l.kvs = this.kvs; + return l.setMsgString(msg, args); + } + + public LogMessage setMsg(String msg, Object... args) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, args); + this.msg = ft.getThrowable() == null ? ft.getMessage() : ft.getMessage() + "||_fmt_throw=" + ft.getThrowable(); + return this; + } + + public String setMsgString(String msg, Object... args) { + FormattingTuple ft = MessageFormatter.arrayFormat(msg, args); + this.msg = ft.getThrowable() == null ? ft.getMessage() : ft.getMessage() + "||_fmt_throw=" + ft.getThrowable(); + return toString(); + } + + public LogMessage kv(String k, Object v) { + this.kvs.put(k, v == null ? "" : v); + return this; + } + + public String kv2String(String k, Object v) { + this.kvs.put(k, v == null ? "" : v); + return toString(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + if (msg != null && !msg.isEmpty()) { + sb.append("||_msg=").append(msg); + } + + for (Map.Entry kv : kvs.entrySet()) { + sb.append("||" + kv.getKey() + "=").append(kv.getValue()); + } + + return sb.toString(); + } + +} diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/HttpClientUtilTest.java b/hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/http/HttpUtilsTest.java similarity index 78% rename from hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/HttpClientUtilTest.java rename to hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/http/HttpUtilsTest.java index 72db07f6..d181e362 100644 --- a/hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/HttpClientUtilTest.java +++ b/hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/http/HttpUtilsTest.java @@ -15,17 +15,19 @@ * limitations under the License. */ -package cn.hippo4j.common.toolkit; +package cn.hippo4j.common.toolkit.http; +import cn.hippo4j.common.toolkit.JSONUtil; import lombok.Getter; import lombok.Setter; import org.junit.Assert; import org.junit.Test; +import java.net.SocketTimeoutException; import java.util.HashMap; import java.util.Map; -public class HttpClientUtilTest { +public class HttpUtilsTest { /** * test post url @@ -37,11 +39,9 @@ public class HttpClientUtilTest { */ static String getUrl = "https://hippo4j.cn/"; - HttpClientUtil httpClientUtil = HttpClientUtil.build(); - @Test public void get() { - String s = httpClientUtil.get(getUrl); + String s = HttpUtils.get(getUrl); Assert.assertNotNull(s); } @@ -52,7 +52,7 @@ public class HttpClientUtilTest { loginInfo.setPassword("hippo4j"); loginInfo.setUsername("hippo4j"); loginInfo.setRememberMe(1); - String s = httpClientUtil.restApiPost(loginUrl, loginInfo); + String s = HttpUtils.post(loginUrl, loginInfo); Result result = JSONUtil.parseObject(s, Result.class); Assert.assertNotNull(result); String data = result.getData().getData(); @@ -66,18 +66,28 @@ public class HttpClientUtilTest { loginInfo.setPassword("hippo4j"); loginInfo.setUsername("hippo4j"); loginInfo.setRememberMe(1); - Result result = httpClientUtil.restApiPost(loginUrl, loginInfo, Result.class); + Result result = HttpUtils.post(loginUrl, loginInfo, Result.class); Assert.assertNotNull(result); String data = result.getData().getData(); Assert.assertNotNull(data); } + @Test + public void testRestApiPostTimeout() { + String loginUrl = postUrl + "auth/login"; + LoginInfo loginInfo = new LoginInfo(); + loginInfo.setPassword("hippo4j"); + loginInfo.setUsername("hippo4j"); + loginInfo.setRememberMe(1); + Assert.assertThrows(SocketTimeoutException.class, () -> HttpUtils.post(loginUrl, loginInfo, 1, Result.class)); + } + @Test public void buildUrl() { Map map = new HashMap<>(); map.put("password", "hippo4j"); map.put("username", "hippo4j"); - String s = httpClientUtil.buildUrl(getUrl, map); + String s = HttpUtils.buildUrl(getUrl, map); Assert.assertEquals(getUrl + "?password=hippo4j&username=hippo4j", s); } diff --git a/hippo4j-config/src/main/java/cn/hippo4j/config/service/ThreadPoolAdapterService.java b/hippo4j-config/src/main/java/cn/hippo4j/config/service/ThreadPoolAdapterService.java index 4334b19d..4a92876d 100644 --- a/hippo4j-config/src/main/java/cn/hippo4j/config/service/ThreadPoolAdapterService.java +++ b/hippo4j-config/src/main/java/cn/hippo4j/config/service/ThreadPoolAdapterService.java @@ -23,9 +23,9 @@ import cn.hippo4j.common.design.observer.AbstractSubjectCenter; import cn.hippo4j.common.design.observer.Observer; import cn.hippo4j.common.design.observer.ObserverMessage; import cn.hippo4j.common.toolkit.CollectionUtil; -import cn.hippo4j.common.toolkit.HttpClientUtil; import cn.hippo4j.common.toolkit.JSONUtil; import cn.hippo4j.common.toolkit.StringUtil; +import cn.hippo4j.common.toolkit.http.HttpUtils; import cn.hippo4j.common.web.base.Result; import cn.hippo4j.config.model.biz.adapter.ThreadPoolAdapterReqDTO; import cn.hippo4j.config.model.biz.adapter.ThreadPoolAdapterRespDTO; @@ -46,8 +46,6 @@ import static cn.hippo4j.common.constant.Constants.IDENTIFY_SLICER_SYMBOL; @Service public class ThreadPoolAdapterService { - private HttpClientUtil httpClientUtil = HttpClientUtil.build(); - /** * Map<mark, Map<tenantItem, Map<threadPoolKey, List<ThreadPoolAdapterState>>>> */ @@ -103,7 +101,7 @@ public class ThreadPoolAdapterService { param.put("mark", requestParameter.getMark()); param.put("threadPoolKey", requestParameter.getThreadPoolKey()); try { - String resultStr = httpClientUtil.get(url, param); + String resultStr = HttpUtils.get(url, param); if (StringUtil.isNotBlank(resultStr)) { Result restResult = JSONUtil.parseObject(resultStr, new TypeReference>() { }); diff --git a/hippo4j-config/src/main/java/cn/hippo4j/config/service/biz/impl/AdapterThreadPoolConfigModificationVerifyServiceImpl.java b/hippo4j-config/src/main/java/cn/hippo4j/config/service/biz/impl/AdapterThreadPoolConfigModificationVerifyServiceImpl.java index 03869c70..3b0be334 100644 --- a/hippo4j-config/src/main/java/cn/hippo4j/config/service/biz/impl/AdapterThreadPoolConfigModificationVerifyServiceImpl.java +++ b/hippo4j-config/src/main/java/cn/hippo4j/config/service/biz/impl/AdapterThreadPoolConfigModificationVerifyServiceImpl.java @@ -18,8 +18,8 @@ package cn.hippo4j.config.service.biz.impl; import cn.hippo4j.common.constant.ConfigModifyTypeConstants; -import cn.hippo4j.common.toolkit.HttpClientUtil; import cn.hippo4j.common.toolkit.StringUtil; +import cn.hippo4j.common.toolkit.http.HttpUtils; import cn.hippo4j.config.model.biz.threadpool.ConfigModifyVerifyReqDTO; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -31,8 +31,6 @@ import org.springframework.stereotype.Service; @Service public class AdapterThreadPoolConfigModificationVerifyServiceImpl extends AbstractConfigModificationVerifyService { - private final HttpClientUtil httpClientUtil = HttpClientUtil.build(); - @Override public Integer type() { return ConfigModifyTypeConstants.ADAPTER_THREAD_POOL; @@ -42,7 +40,7 @@ public class AdapterThreadPoolConfigModificationVerifyServiceImpl extends Abstra protected void updateThreadPoolParameter(ConfigModifyVerifyReqDTO reqDTO) { for (String each : getClientAddress(reqDTO)) { String urlString = StringUtil.newBuilder("http://", each, "/adapter/thread-pool/update"); - httpClientUtil.restApiPost(urlString, reqDTO, Object.class); + HttpUtils.post(urlString, reqDTO); } } } diff --git a/hippo4j-config/src/main/java/cn/hippo4j/config/service/biz/impl/WebThreadPoolConfigModificationVerifyServiceImpl.java b/hippo4j-config/src/main/java/cn/hippo4j/config/service/biz/impl/WebThreadPoolConfigModificationVerifyServiceImpl.java index 377fff6e..9ede76a6 100644 --- a/hippo4j-config/src/main/java/cn/hippo4j/config/service/biz/impl/WebThreadPoolConfigModificationVerifyServiceImpl.java +++ b/hippo4j-config/src/main/java/cn/hippo4j/config/service/biz/impl/WebThreadPoolConfigModificationVerifyServiceImpl.java @@ -18,8 +18,8 @@ package cn.hippo4j.config.service.biz.impl; import cn.hippo4j.common.constant.ConfigModifyTypeConstants; -import cn.hippo4j.common.toolkit.HttpClientUtil; import cn.hippo4j.common.toolkit.StringUtil; +import cn.hippo4j.common.toolkit.http.HttpUtils; import cn.hippo4j.config.model.biz.threadpool.ConfigModifyVerifyReqDTO; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -31,8 +31,6 @@ import org.springframework.stereotype.Service; @Service public class WebThreadPoolConfigModificationVerifyServiceImpl extends AbstractConfigModificationVerifyService { - private final HttpClientUtil httpClientUtil = HttpClientUtil.build(); - @Override public Integer type() { return ConfigModifyTypeConstants.WEB_THREAD_POOL; @@ -42,7 +40,7 @@ public class WebThreadPoolConfigModificationVerifyServiceImpl extends AbstractCo protected void updateThreadPoolParameter(ConfigModifyVerifyReqDTO reqDTO) { for (String each : getClientAddress(reqDTO)) { String urlString = StringUtil.newBuilder("http://", each, "/web/update/pool"); - httpClientUtil.restApiPost(urlString, reqDTO, Object.class); + HttpUtils.post(urlString, reqDTO); } } } diff --git a/hippo4j-console/src/main/java/cn/hippo4j/console/controller/ThreadPoolAdapterController.java b/hippo4j-console/src/main/java/cn/hippo4j/console/controller/ThreadPoolAdapterController.java index 01fb8252..c01e628e 100644 --- a/hippo4j-console/src/main/java/cn/hippo4j/console/controller/ThreadPoolAdapterController.java +++ b/hippo4j-console/src/main/java/cn/hippo4j/console/controller/ThreadPoolAdapterController.java @@ -19,6 +19,7 @@ package cn.hippo4j.console.controller; import cn.hippo4j.common.constant.ConfigModifyTypeConstants; import cn.hippo4j.common.toolkit.*; +import cn.hippo4j.common.toolkit.http.HttpUtils; import cn.hippo4j.common.web.base.Result; import cn.hippo4j.common.web.base.Results; import cn.hippo4j.config.model.biz.adapter.ThreadPoolAdapterReqDTO; @@ -48,8 +49,6 @@ public class ThreadPoolAdapterController { private final ConfigModificationVerifyServiceChoose configModificationVerifyServiceChoose; - private HttpClientUtil httpClientUtil = HttpClientUtil.build(); - @GetMapping(REGISTER_ADAPTER_BASE_PATH + "/query") public Result> queryAdapterThreadPool(ThreadPoolAdapterReqDTO requestParameter) { List result = threadPoolAdapterService.query(requestParameter); @@ -67,7 +66,7 @@ public class ThreadPoolAdapterController { if (UserContext.getUserRole().equals("ROLE_ADMIN")) { for (String each : requestParameter.getClientAddressList()) { String urlString = StringUtil.newBuilder("http://", each, "/adapter/thread-pool/update"); - httpClientUtil.restApiPost(urlString, requestParameter, Object.class); + HttpUtils.post(urlString, requestParameter); } } else { ConfigModifySaveReqDTO modifySaveReqDTO = BeanUtil.convert(requestParameter, ConfigModifySaveReqDTO.class); diff --git a/hippo4j-console/src/main/java/cn/hippo4j/console/controller/ThreadPoolController.java b/hippo4j-console/src/main/java/cn/hippo4j/console/controller/ThreadPoolController.java index 8f90395e..305e6876 100644 --- a/hippo4j-console/src/main/java/cn/hippo4j/console/controller/ThreadPoolController.java +++ b/hippo4j-console/src/main/java/cn/hippo4j/console/controller/ThreadPoolController.java @@ -21,6 +21,7 @@ import cn.hippo4j.common.constant.ConfigModifyTypeConstants; import cn.hippo4j.common.constant.Constants; import cn.hippo4j.common.model.InstanceInfo; import cn.hippo4j.common.toolkit.*; +import cn.hippo4j.common.toolkit.http.HttpUtils; import cn.hippo4j.common.web.base.Result; import cn.hippo4j.common.web.base.Results; import cn.hippo4j.common.web.exception.ErrorCodeEnum; @@ -60,8 +61,6 @@ public class ThreadPoolController { private final ConfigModificationVerifyServiceChoose configModificationVerifyServiceChoose; - private HttpClientUtil httpClientUtil = HttpClientUtil.build(); - private static final String HTTP = "http://"; @PostMapping("/query/page") @@ -110,14 +109,14 @@ public class ThreadPoolController { public Result runState(@PathVariable("tpId") String tpId, @RequestParam(value = "clientAddress") String clientAddress) { String urlString = StringUtil.newBuilder(HTTP, clientAddress, "/run/state/", tpId); - return httpClientUtil.restApiGet(urlString, Result.class); + return HttpUtils.get(urlString, Result.class); } @GetMapping("/run/thread/state/{tpId}") public Result runThreadState(@PathVariable("tpId") String tpId, @RequestParam(value = "clientAddress") String clientAddress) { String urlString = StringUtil.newBuilder(HTTP, clientAddress, "/run/thread/state/", tpId); - return httpClientUtil.restApiGet(urlString, Result.class); + return HttpUtils.get(urlString, Result.class); } @GetMapping("/list/client/instance/{itemId}") @@ -153,13 +152,13 @@ public class ThreadPoolController { @GetMapping("/web/base/info") public Result getPoolBaseState(@RequestParam(value = "clientAddress") String clientAddress) { String urlString = StringUtil.newBuilder(HTTP, clientAddress, "/web/base/info"); - return httpClientUtil.restApiGet(urlString, Result.class); + return HttpUtils.get(urlString, Result.class); } @GetMapping("/web/run/state") public Result getPoolRunState(@RequestParam(value = "clientAddress") String clientAddress) { String urlString = StringUtil.newBuilder(HTTP, clientAddress, "/web/run/state"); - return httpClientUtil.restApiGet(urlString, Result.class); + return HttpUtils.get(urlString, Result.class); } @PostMapping("/web/update/pool") @@ -167,7 +166,7 @@ public class ThreadPoolController { if (UserContext.getUserRole().equals("ROLE_ADMIN")) { for (String each : requestParam.getClientAddressList()) { String urlString = StringUtil.newBuilder(HTTP, each, "/web/update/pool"); - httpClientUtil.restApiPost(urlString, requestParam, Object.class); + HttpUtils.post(urlString, requestParam); } } else { ConfigModifySaveReqDTO modifySaveReqDTO = BeanUtil.convert(requestParam, ConfigModifySaveReqDTO.class); diff --git a/hippo4j-message/src/main/java/cn/hippo4j/message/platform/LarkSendMessageHandler.java b/hippo4j-message/src/main/java/cn/hippo4j/message/platform/LarkSendMessageHandler.java index c7339f77..790af7d3 100644 --- a/hippo4j-message/src/main/java/cn/hippo4j/message/platform/LarkSendMessageHandler.java +++ b/hippo4j-message/src/main/java/cn/hippo4j/message/platform/LarkSendMessageHandler.java @@ -17,8 +17,8 @@ package cn.hippo4j.message.platform; -import cn.hippo4j.common.toolkit.HttpClientUtil; import cn.hippo4j.common.toolkit.Singleton; +import cn.hippo4j.common.toolkit.http.HttpUtils; import cn.hippo4j.message.dto.NotifyConfigDTO; import cn.hippo4j.message.enums.NotifyPlatformEnum; import cn.hippo4j.message.enums.NotifyTypeEnum; @@ -46,8 +46,6 @@ import static cn.hippo4j.message.platform.constant.LarkAlarmConstants.*; @RequiredArgsConstructor public class LarkSendMessageHandler implements SendMessageHandler { - private HttpClientUtil httpClientUtil = HttpClientUtil.build(); - @Override public String getType() { return NotifyPlatformEnum.LARK.name(); @@ -174,7 +172,7 @@ public class LarkSendMessageHandler implements SendMessageHandler headers, Map paramValues, long readTimeoutMs) { isHealthStatus(); injectSecurityInfo(paramValues); - return httpClientUtil.restApiGetByThreadPool(buildUrl(path), headers, paramValues, readTimeoutMs, Result.class); + return HttpUtils.get(buildUrl(path), headers, paramValues, readTimeoutMs, Result.class); } @Override public Result httpPostByConfig(String path, Map headers, Map paramValues, long readTimeoutMs) { isHealthStatus(); injectSecurityInfo(paramValues); - return httpClientUtil.restApiPostByThreadPool(buildUrl(path), headers, paramValues, readTimeoutMs, Result.class); + return HttpUtils.post(buildUrl(path), headers, paramValues, readTimeoutMs, Result.class); } @Override @@ -141,7 +138,7 @@ public class ServerHttpAgent implements HttpAgent { @Deprecated private String injectSecurityInfoByPath(String path) { - String resultPath = httpClientUtil.buildUrl(path, injectSecurityInfo(new HashMap<>())); + String resultPath = HttpUtils.buildUrl(path, injectSecurityInfo(new HashMap<>())); return resultPath; } } diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/security/SecurityProxy.java b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/security/SecurityProxy.java index 49f06385..e2ad35c7 100644 --- a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/security/SecurityProxy.java +++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/security/SecurityProxy.java @@ -21,9 +21,9 @@ import cn.hippo4j.common.constant.Constants; import cn.hippo4j.common.model.TokenInfo; import cn.hippo4j.common.toolkit.JSONUtil; import cn.hippo4j.common.toolkit.StringUtil; +import cn.hippo4j.common.toolkit.http.HttpUtils; import cn.hippo4j.common.web.base.Result; import cn.hippo4j.springboot.starter.config.BootstrapProperties; -import cn.hippo4j.common.toolkit.HttpClientUtil; import lombok.extern.slf4j.Slf4j; import java.util.HashMap; @@ -39,8 +39,6 @@ public class SecurityProxy { private static final String APPLY_TOKEN_URL = Constants.BASE_PATH + "/auth/users/apply/token"; - private final HttpClientUtil httpClientUtil; - private final String username; private final String password; @@ -53,10 +51,9 @@ public class SecurityProxy { private long tokenRefreshWindow; - public SecurityProxy(HttpClientUtil httpClientUtil, BootstrapProperties properties) { + public SecurityProxy(BootstrapProperties properties) { username = properties.getUsername(); password = properties.getPassword(); - this.httpClientUtil = httpClientUtil; } public boolean applyToken(List servers) { @@ -82,7 +79,7 @@ public class SecurityProxy { bodyMap.put("userName", username); bodyMap.put("password", password); try { - Result result = httpClientUtil.restApiPost(url, bodyMap, Result.class); + Result result = HttpUtils.post(url, bodyMap, Result.class); if (!result.isSuccess()) { log.error("Error getting access token. message: {}", result.getMessage()); return false; diff --git a/pom.xml b/pom.xml index 9d14c53b..32cfac06 100644 --- a/pom.xml +++ b/pom.xml @@ -56,7 +56,6 @@ 6.5.0 2.9.3 - 3.12.0 6.1.5.Final 2.12.1 0.9.0 @@ -111,11 +110,6 @@ pom import - - com.squareup.okhttp3 - okhttp - ${okhttp3.version} - cn.hippo4j hippo4j-message