From cb23f58b0f809f60ce1068d43ba64c6a0cba8579 Mon Sep 17 00:00:00 2001 From: richie Date: Fri, 16 Sep 2022 18:00:21 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=9B=E4=B8=80=E6=AD=A5=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 2 + .../datasource/server/Authentication.java | 53 +++ .../server/DatasourceOperation.java | 25 ++ .../datasource/server/ProjectConstants.java | 10 + .../datasource/server/ServerApplication.java | 3 +- .../datasource/server/http/HttpKits.java | 392 ++++++++++++++++++ .../http/rs/BaseHttpResponseHandle.java | 47 +++ .../server/http/rs/HttpRequest.java | 211 ++++++++++ .../server/http/rs/HttpRequestType.java | 109 +++++ .../server/http/rs/HttpResponseType.java | 98 +++++ .../server/http/rs/StreamResponseHandle.java | 49 +++ .../server/http/rs/TextResponseHandle.java | 33 ++ .../server/http/rs/UploadResponseHandle.java | 43 ++ 13 files changed, 1074 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/fanruan/hihidata/datasource/server/Authentication.java create mode 100644 src/main/java/com/fanruan/hihidata/datasource/server/DatasourceOperation.java create mode 100644 src/main/java/com/fanruan/hihidata/datasource/server/ProjectConstants.java create mode 100644 src/main/java/com/fanruan/hihidata/datasource/server/http/HttpKits.java create mode 100644 src/main/java/com/fanruan/hihidata/datasource/server/http/rs/BaseHttpResponseHandle.java create mode 100644 src/main/java/com/fanruan/hihidata/datasource/server/http/rs/HttpRequest.java create mode 100644 src/main/java/com/fanruan/hihidata/datasource/server/http/rs/HttpRequestType.java create mode 100644 src/main/java/com/fanruan/hihidata/datasource/server/http/rs/HttpResponseType.java create mode 100644 src/main/java/com/fanruan/hihidata/datasource/server/http/rs/StreamResponseHandle.java create mode 100644 src/main/java/com/fanruan/hihidata/datasource/server/http/rs/TextResponseHandle.java create mode 100644 src/main/java/com/fanruan/hihidata/datasource/server/http/rs/UploadResponseHandle.java diff --git a/build.gradle.kts b/build.gradle.kts index 74417bd..a7eef27 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,6 +24,8 @@ repositories { dependencies { implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) implementation("com.google.guava:guava:31.1-jre") + implementation("org.jetbrains:annotations:23.0.0") + implementation("org.json:json:20220320") implementation("org.apache.httpcomponents:httpclient:4.5.13") testImplementation("junit:junit:4.12") } diff --git a/src/main/java/com/fanruan/hihidata/datasource/server/Authentication.java b/src/main/java/com/fanruan/hihidata/datasource/server/Authentication.java new file mode 100644 index 0000000..4b32e39 --- /dev/null +++ b/src/main/java/com/fanruan/hihidata/datasource/server/Authentication.java @@ -0,0 +1,53 @@ +package com.fanruan.hihidata.datasource.server; + +import com.fanruan.hihidata.datasource.server.http.HttpKits; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import org.jetbrains.annotations.NotNull; +import org.json.JSONObject; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +/** + * @author richie + * Created by richie on 2022/9/16 + */ +public class Authentication { + + private final String accessKeyId; + private final String accessKeySecret; + + private final LoadingCache cache = CacheBuilder.newBuilder() + .expireAfterWrite(30, TimeUnit.MINUTES) + .build(new CacheLoader() { + + @Override + public String load(@NotNull String key) throws Exception { + return fetchAccessToken(); + } + }); + + public Authentication(String accessKeyId, String accessKeySecret) { + this.accessKeyId = accessKeyId; + this.accessKeySecret = accessKeySecret; + } + + private String fetchAccessToken() throws Exception { + String res = HttpKits.get(String.format("%s/api/v1/corp/oauth/token?accessKeyId=%s&accessKeySecret=%s", ProjectConstants.BASE_URI, accessKeyId, accessKeySecret)); + JSONObject jsonObject = new JSONObject(res); + if (jsonObject.optBoolean("success", false)) { + return jsonObject.getString("data"); + } + return null; + } + + public String getToken() { + try { + return cache.get("ticket"); + } catch (ExecutionException e) { + return null; + } + } +} diff --git a/src/main/java/com/fanruan/hihidata/datasource/server/DatasourceOperation.java b/src/main/java/com/fanruan/hihidata/datasource/server/DatasourceOperation.java new file mode 100644 index 0000000..b9cdac7 --- /dev/null +++ b/src/main/java/com/fanruan/hihidata/datasource/server/DatasourceOperation.java @@ -0,0 +1,25 @@ +package com.fanruan.hihidata.datasource.server; + +import com.fanruan.hihidata.datasource.server.http.HttpKits; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author richie + * Created by richie on 2022/9/16 + */ +public class DatasourceOperation { + + private Authentication auth; + + public DatasourceOperation(Authentication auth) { + this.auth = auth; + } + + public void open() throws Exception { + Map headers = new HashMap<>(); + headers.put("Authorization", auth.getToken()); + HttpKits.post(String.format("%s/api/v1/datasource/status/modify", ProjectConstants.BASE_URI), headers); + } +} diff --git a/src/main/java/com/fanruan/hihidata/datasource/server/ProjectConstants.java b/src/main/java/com/fanruan/hihidata/datasource/server/ProjectConstants.java new file mode 100644 index 0000000..af18b72 --- /dev/null +++ b/src/main/java/com/fanruan/hihidata/datasource/server/ProjectConstants.java @@ -0,0 +1,10 @@ +package com.fanruan.hihidata.datasource.server; + +/** + * @author richie + * Created by richie on 2022/9/16 + */ +public class ProjectConstants { + + public static final String BASE_URI = "https://work.jiushuyun.com/decision"; +} diff --git a/src/main/java/com/fanruan/hihidata/datasource/server/ServerApplication.java b/src/main/java/com/fanruan/hihidata/datasource/server/ServerApplication.java index f1e0840..3539aa1 100644 --- a/src/main/java/com/fanruan/hihidata/datasource/server/ServerApplication.java +++ b/src/main/java/com/fanruan/hihidata/datasource/server/ServerApplication.java @@ -7,6 +7,7 @@ package com.fanruan.hihidata.datasource.server; public class ServerApplication { public static void main(String... args) { - + Authentication authentication = new Authentication(args[0], args[1]); + DatasourceOperation operation = new DatasourceOperation(authentication); } } diff --git a/src/main/java/com/fanruan/hihidata/datasource/server/http/HttpKits.java b/src/main/java/com/fanruan/hihidata/datasource/server/http/HttpKits.java new file mode 100644 index 0000000..deb0a9c --- /dev/null +++ b/src/main/java/com/fanruan/hihidata/datasource/server/http/HttpKits.java @@ -0,0 +1,392 @@ +package com.fanruan.hihidata.datasource.server.http; + +import com.fanruan.hihidata.datasource.server.http.rs.BaseHttpResponseHandle; +import com.fanruan.hihidata.datasource.server.http.rs.HttpRequest; +import com.fanruan.hihidata.datasource.server.http.rs.HttpRequestType; +import com.fanruan.hihidata.datasource.server.http.rs.TextResponseHandle; +import com.fanruan.hihidata.datasource.server.http.rs.UploadResponseHandle; +import com.google.common.collect.Maps; +import org.apache.http.HttpEntity; +import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.HttpHost; +import org.apache.http.NameValuePair; +import org.apache.http.NoHttpResponseException; +import org.apache.http.client.HttpRequestRetryHandler; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.routing.HttpRoute; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.LayeredConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.FileEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.protocol.HttpContext; +import org.apache.http.ssl.SSLContexts; +import org.jetbrains.annotations.NotNull; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLHandshakeException; +import java.io.File; +import java.io.IOException; +import java.io.InterruptedIOException; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.net.UnknownHostException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * @author richie + * Created by richie on 2022/9/16 + */ +public class HttpKits { + + private static final int RETRY_TIMES = 5; + + private static CloseableHttpClient httpClient = null; + + private final static Object SYNC_LOCK = new Object(); + + /** + * 根据请求地址创建HttpClient对象 + * + * @param url 请求地址 + * @return HttpClient对象 + */ + public static CloseableHttpClient getHttpClient(String url) { + String hostname = url.split("/")[2]; + int port = 80; + if (hostname.contains(":")) { + String[] arr = hostname.split(":"); + hostname = arr[0]; + port = Integer.parseInt(arr[1]); + } + if (httpClient == null) { + synchronized (SYNC_LOCK) { + if (httpClient == null) { + httpClient = createHttpClient(hostname, port, SSLContexts.createDefault()); + } + } + } + return httpClient; + } + + + public static CloseableHttpClient createHttpClient(String hostname, int port, SSLContext sslContext) { + return createHttpClient(200, 40, 100, hostname, port, sslContext); + } + + private static CloseableHttpClient createHttpClient(int maxTotal, + int maxPerRoute, + int maxRoute, + String hostname, + int port, + SSLContext sslContext) { + ConnectionSocketFactory socketFactory = PlainConnectionSocketFactory.getSocketFactory(); + LayeredConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext); + Registry registry = RegistryBuilder + .create() + .register("http", socketFactory) + .register("https", sslConnectionSocketFactory) + .build(); + PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry); + // 将最大连接数增加 + cm.setMaxTotal(maxTotal); + // 将每个路由基础的连接增加 + cm.setDefaultMaxPerRoute(maxPerRoute); + HttpHost httpHost = new HttpHost(hostname, port); + // 将目标主机的最大连接数增加 + cm.setMaxPerRoute(new HttpRoute(httpHost), maxRoute); + + // 请求重试处理 + HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() { + @Override + public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { + if (executionCount >= RETRY_TIMES) {// 如果已经重试了5次,就放弃 + return false; + } + if (exception instanceof NoHttpResponseException) {// 如果服务器丢掉了连接,那么就重试 + return true; + } + if (exception instanceof SSLHandshakeException) {// 不要重试SSL握手异常 + return false; + } + if (exception instanceof InterruptedIOException) {// 超时 + return false; + } + if (exception instanceof UnknownHostException) {// 目标服务器不可达 + return false; + } + if (exception instanceof SSLException) {// SSL握手异常 + return false; + } + + HttpClientContext clientContext = HttpClientContext.adapt(context); + org.apache.http.HttpRequest request = clientContext.getRequest(); + // 如果请求是幂等的,就再次尝试 + return !(request instanceof HttpEntityEnclosingRequest); + } + }; + + return HttpClients.custom() + .setConnectionManager(cm) + .setRetryHandler(httpRequestRetryHandler) + .build(); + } + + /** + * 发起GET请求并获取返回的文本 + * + * @param url 响应请求的的服务器地址 + * @return 服务器返回的文本内容 + */ + public static String get(String url) throws IOException { + return executeAndParse(HttpRequest.custom().url(url).build()); + } + + /** + * 发起GET请求并获取返回的文本 + * + * @param url 响应请求的的服务器地址 + * @param params 参数 + * @param headers 请求头 + * @return 服务器返回的文本内容 + * @see HttpKits#executeAndParse(HttpRequest, BaseHttpResponseHandle) + */ + public static String get(String url, Map params, Map headers) throws IOException { + return executeAndParse(HttpRequest.custom().url(url).params(params).headers(headers).build()); + } + + /** + * 发起POST请求并获取返回的文本 + * + * @param url 响应请求的的服务器地址 + * @param params POST请求的参数 + * @return 服务器返回的文本内容 + */ + public static String post(String url, Map params) throws IOException { + return executeAndParse(HttpRequest + .custom() + .url(url) + .post(transformMap(params)) + .build()); + } + + /** + * 上传文件到指定的服务器 + * + * @param url 接收文件的服务器地址 + * @param file 要上传的文件,默认的文件编码为utf-8 + * @throws IOException 上传中出现错误则抛出此异常 + */ + public static void upload(String url, File file) throws IOException { + upload(url, file, StandardCharsets.UTF_8); + } + + /** + * 上传文件到指定的服务器 + * + * @param url 接收文件的服务器地址 + * @param file 要上传的文件 + * @param charset 文件的编码 + * @throws IOException 上传中出现错误则抛出此异常 + */ + public static void upload(String url, File file, Charset charset) throws IOException { + upload(url, new FileEntity(file), charset); + } + + /** + * 上传文件到指定的服务器 + * + * @param url 接收文件的服务器地址 + * @param fileEntity 文件实体 + * @param charset 文件的编码 + * @throws IOException 上传中出现错误则抛出此异常 + */ + public static void upload(String url, FileEntity fileEntity, Charset charset) throws IOException { + upload(url, fileEntity, charset, Collections.emptyMap(), HttpRequestType.POST); + } + + /** + * 上传文件到指定的服务器 + * + * @param url 接收文件的服务器地址 + * @param reqEntity 请求实体 + * @param charset 文件的编码 + * @param headers 请求头 + * @param httpRequestType 请求类型 + * @throws IOException 上传中出现错误则抛出此异常 + */ + public static void upload(String url, HttpEntity reqEntity, Charset charset, Map headers, HttpRequestType httpRequestType) throws IOException { + executeAndParse(HttpRequest + .custom() + .url(url) + .headers(headers) + .method(httpRequestType) + .httpEntity(reqEntity) + .encoding(charset.toString()) + .build(), + UploadResponseHandle.DEFAULT); + } + + /** + * 请求资源或服务,使用默认文本http解析器,UTF-8编码 + * + * @param httpRequest httpRequest + * @return 返回处理结果 + */ + public static String executeAndParse(HttpRequest httpRequest) throws IOException { + return executeAndParse(httpRequest, TextResponseHandle.DEFAULT); + } + + /** + * 请求资源或服务,自请求参数,并指定 http 响应处理器 + * 例: + *
+     *      String res = HttpToolbox.executeAndParse(HttpRequest
+     *              .custom()
+     *              .url("")
+     *              .build(),
+     *          TextResponseHandle.DEFAULT);
+     * 
+ * + * @param httpRequest httpRequest + * @param handle http 解析器 + * @return 返回处理结果 + */ + public static T executeAndParse(HttpRequest httpRequest, BaseHttpResponseHandle handle) throws IOException { + return handle.parse(execute(httpRequest)); + } + + /** + * 请求资源或服务,传入请求参数 + * + * @param httpRequest httpRequest + * @return 返回处理结果 + */ + public static CloseableHttpResponse execute(HttpRequest httpRequest) throws IOException { + return execute(getHttpClient(httpRequest.getUrl()), httpRequest); + } + + /** + * 请求资源或服务,自定义client对象,传入请求参数 + * + * @param httpClient http客户端 + * @param httpRequest httpRequest + * @return 返回处理结果 + */ + public static CloseableHttpResponse execute(CloseableHttpClient httpClient, HttpRequest httpRequest) throws IOException { + String url = httpRequest.getUrl(); + + // 创建请求对象 + HttpRequestBase httpRequestBase = httpRequest.getMethod().createHttpRequest(url); + + // 设置header信息 + httpRequestBase.setHeader("User-Agent", "Mozilla/5.0"); + Map headers = httpRequest.getHeaders(); + if (headers != null && !headers.isEmpty()) { + for (Map.Entry entry : headers.entrySet()) { + httpRequestBase.setHeader(entry.getKey(), entry.getValue()); + } + } + + // 配置请求的设置 + RequestConfig requestConfig = httpRequest.getConfig(); + if (requestConfig != null) { + httpRequestBase.setConfig(requestConfig); + } + + // 判断是否支持设置entity(仅HttpPost、HttpPut、HttpPatch支持) + if (HttpEntityEnclosingRequestBase.class.isAssignableFrom(httpRequestBase.getClass())) { + setHttpEntity((HttpEntityEnclosingRequestBase) httpRequestBase, httpRequest); + } else { + Map params = httpRequest.getParams(); + if (params != null && !params.isEmpty()) { + // 注意get等不支持设置entity需要更新拼接之后的URL,但是url变量没有更新 + httpRequestBase.setURI(URI.create(buildUrl(url, params, httpRequest.getEncoding()))); + } + } + + return httpClient.execute(httpRequestBase); + } + + /** + * 设置 httpEntity + * + * @param requestBase 请求体 + * @param httpRequest 请求 + */ + private static void setHttpEntity(@NotNull HttpEntityEnclosingRequestBase requestBase, @NotNull HttpRequest httpRequest) { + HttpEntity httpEntity = httpRequest.getHttpEntity(); + if (httpEntity != null) { + // 如果存在 httpEntity 直接设置 + requestBase.setEntity(httpEntity); + return; + } + Map params = httpRequest.getParams(); + if (params == null || params.isEmpty()) { + return; + } + List pairs = new ArrayList<>(); + for (Map.Entry entry : params.entrySet()) { + pairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); + } + try { + requestBase.setEntity(new UrlEncodedFormEntity(pairs, httpRequest.getEncoding())); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + + private static Map transformMap(Map oldMap) { + if (oldMap == null) { + return null; + } + return Maps.transformEntries(oldMap, (key, value) -> value == null ? null : value.toString()); + } + + /** + * 构建 Url + * + * @param url 请求地址 + * @param params 参数 + * @return 拼接之后的地址 + * @throws UnsupportedEncodingException 不支持的编码 + */ + private static String buildUrl(String url, Map params, String paramsEncoding) throws UnsupportedEncodingException { + if (params == null || params.isEmpty()) { + return url; + } + URIBuilder builder; + try { + builder = new URIBuilder(url); + for (Map.Entry entry : params.entrySet()) { + String key = URLEncoder.encode(entry.getKey(), paramsEncoding); + String value = URLEncoder.encode(entry.getValue(), paramsEncoding); + builder.setParameter(key, value); + } + return builder.build().toString(); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + return url; + } +} diff --git a/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/BaseHttpResponseHandle.java b/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/BaseHttpResponseHandle.java new file mode 100644 index 0000000..b8922dd --- /dev/null +++ b/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/BaseHttpResponseHandle.java @@ -0,0 +1,47 @@ +package com.fanruan.hihidata.datasource.server.http.rs; + +import org.apache.http.client.methods.CloseableHttpResponse; + +import java.io.IOException; + +public abstract class BaseHttpResponseHandle { + + /** + * 解析编码,默认为 UTF_8 + */ + private String encoding = "utf-8"; + + public BaseHttpResponseHandle() { + } + + public BaseHttpResponseHandle(String encoding) { + this.encoding = encoding; + } + + /** + * 获取解析编码 + * + * @return 解析编码 + */ + public String getEncoding() { + return encoding; + } + + /** + * 设置解析编码 + * + * @param encoding 解析编码 + */ + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + /** + * 解析响应结果 + * + * @param response 响应 + * @return 解析结果 + * @throws IOException io异常 + */ + public abstract T parse(CloseableHttpResponse response) throws IOException; +} diff --git a/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/HttpRequest.java b/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/HttpRequest.java new file mode 100644 index 0000000..d49b232 --- /dev/null +++ b/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/HttpRequest.java @@ -0,0 +1,211 @@ +package com.fanruan.hihidata.datasource.server.http.rs; + +import org.apache.http.HttpEntity; +import org.apache.http.client.config.RequestConfig; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.Map; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-08-29 + */ +public class HttpRequest { + + private static final int TIME_OUT = 10 * 1000; + private static final RequestConfig DEFAULT = RequestConfig + .custom() + .setConnectionRequestTimeout(TIME_OUT) + .setConnectTimeout(TIME_OUT) + .setSocketTimeout(TIME_OUT) + .build(); + /** + * 请求地址 + */ + private String url; + + /** + * 请求头 + */ + private Map headers; + + /** + * 请求参数 + */ + private Map params; + + /** + * 请求参数 + * + * @see RequestConfig + */ + @Nullable + private RequestConfig config; + + /** + * 请求参数 + * + * @see HttpEntity + */ + @Nullable + private HttpEntity httpEntity; + + /** + * 请求方法 + */ + private HttpRequestType method; + + /** + * 参数字符集 + */ + private String encoding; + + private HttpRequest(Builder builder) { + this.url = builder.url; + this.headers = builder.headers; + this.params = builder.params; + this.config = builder.config; + this.encoding = builder.encoding; + this.httpEntity = builder.httpEntity; + this.method = builder.method; + } + + public String getUrl() { + return url; + } + + public Map getHeaders() { + return headers; + } + + public Map getParams() { + return params; + } + + public RequestConfig getConfig() { + return config; + } + + public String getEncoding() { + return encoding; + } + + public HttpEntity getHttpEntity() { + return httpEntity; + } + + public HttpRequestType getMethod() { + return method; + } + + public static Builder custom() { + return new Builder(); + } + + public static final class Builder { + private String url; + private Map headers = Collections.emptyMap(); + private Map params = Collections.emptyMap(); + @Nullable + private RequestConfig config = DEFAULT; + @Nullable + private HttpEntity httpEntity; + private String encoding = "utf-8"; + private HttpRequestType method = HttpRequestType.GET; + + private Builder() { + } + + public HttpRequest build() { + if (this.url == null) { + throw new IllegalStateException("url == null"); + } + return new HttpRequest(this); + } + + public Builder url(@NotNull String url) { + this.url = url; + return this; + } + + public Builder headers(Map headers) { + if (headers != null) { + this.headers = headers; + } + return this; + } + + public Builder params(Map params) { + if (params != null) { + this.params = params; + } + return this; + } + + public Builder config(RequestConfig config) { + this.config = config; + return this; + } + + public Builder get() { + this.method = HttpRequestType.GET; + return this; + } + + public Builder post(HttpEntity httpEntity) { + this.method = HttpRequestType.POST; + this.httpEntity(httpEntity); + return this; + } + + public Builder post(Map params) { + this.method = HttpRequestType.POST; + this.params(params); + return this; + } + + public Builder put(HttpEntity httpEntity) { + this.method = HttpRequestType.PUT; + this.httpEntity(httpEntity); + return this; + } + + public Builder put(Map params) { + this.method = HttpRequestType.PUT; + this.params(params); + return this; + } + + public Builder delete() { + this.method = HttpRequestType.DELETE; + return this; + } + + public Builder encoding(String encoding) { + if (encoding == null) { + throw new NullPointerException("httpEntity == null"); + } + this.encoding = encoding; + return this; + } + + public Builder httpEntity(HttpEntity httpEntity) { + this.httpEntity = httpEntity; + return this; + } + + public Builder method(@NotNull HttpRequestType method) { + if (method == null) { + throw new NullPointerException("method == null"); + } + this.method = method; + return this; + } + + } + + +} \ No newline at end of file diff --git a/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/HttpRequestType.java b/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/HttpRequestType.java new file mode 100644 index 0000000..d2cb56c --- /dev/null +++ b/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/HttpRequestType.java @@ -0,0 +1,109 @@ +package com.fanruan.hihidata.datasource.server.http.rs; + +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpOptions; +import org.apache.http.client.methods.HttpPatch; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.client.methods.HttpTrace; + +public enum HttpRequestType { + /** + * 求获取Request-URI所标识的资源 + */ + GET("GET") { + @Override + public HttpRequestBase createHttpRequest(String url) { + return new HttpGet(url); + } + }, + + /** + * 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。 + * POST请求可能会导致新的资源的建立和/或已有资源的修改 + */ + POST("POST") { + @Override + public HttpRequestBase createHttpRequest(String url) { + return new HttpPost(url); + } + }, + + /** + * 向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。 + * 这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息 + * 只获取响应信息报头 + */ + HEAD("HEAD") { + @Override + public HttpRequestBase createHttpRequest(String url) { + return new HttpHead(url); + } + }, + + /** + * 向指定资源位置上传其最新内容(全部更新,操作幂等) + */ + PUT("PUT") { + @Override + public HttpRequestBase createHttpRequest(String url) { + return new HttpPut(url); + } + }, + + /** + * 请求服务器删除Request-URI所标识的资源 + */ + DELETE("DELETE") { + @Override + public HttpRequestBase createHttpRequest(String url) { + return new HttpDelete(url); + } + }, + + /** + * 请求服务器回送收到的请求信息,主要用于测试或诊断 + */ + TRACE("TRACE") { + @Override + public HttpRequestBase createHttpRequest(String url) { + return new HttpTrace(url); + } + }, + + /** + * 向指定资源位置上传其最新内容(部分更新,非幂等) + */ + PATCH("PATCH") { + @Override + public HttpRequestBase createHttpRequest(String url) { + return new HttpPatch(url); + } + }, + + /** + * 返回服务器针对特定资源所支持的HTTP请求方法。 + * 也可以利用向Web服务器发送'*'的请求来测试服务器的功能性 + */ + OPTIONS("OPTIONS") { + @Override + public HttpRequestBase createHttpRequest(String url) { + return new HttpOptions(url); + } + }; + + public abstract HttpRequestBase createHttpRequest(String url); + + private String name; + + HttpRequestType(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/HttpResponseType.java b/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/HttpResponseType.java new file mode 100644 index 0000000..63848bf --- /dev/null +++ b/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/HttpResponseType.java @@ -0,0 +1,98 @@ +package com.fanruan.hihidata.datasource.server.http.rs; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.util.EntityUtils; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public interface HttpResponseType { + + /** + * 处理http响应 + * + * @param client 客户端 + * @param url 地址 + * @param request 请求 + * @param charset 字符集 + * @return 处理之后的响应 + * @throws IOException 异常 + */ + @Deprecated + T result(CloseableHttpClient client, String url, HttpUriRequest request, String charset) throws IOException; + + /** + * 处理http响应 + * + * @param response 响应 + * @param charset 字符集 + * @return 处理之后的响应 + * @throws IOException 异常 + */ + T result(CloseableHttpResponse response, String charset) throws IOException; + + HttpResponseType TEXT = new HttpResponseType() { + + @Override + public String result(CloseableHttpClient client, String url, HttpUriRequest request, String charset) throws IOException { + CloseableHttpResponse response = client.execute(request, HttpClientContext.create()); + return result(response, charset); + } + + @Override + public String result(CloseableHttpResponse response, String charset) throws IOException { + try { + HttpEntity entity = response.getEntity(); + String result = EntityUtils.toString(entity, charset); + EntityUtils.consume(entity); + return result; + } finally { + if (response != null) { + response.close(); + } + } + } + }; + + HttpResponseType STREAM = new HttpResponseType() { + + @Override + public ByteArrayInputStream result(CloseableHttpClient client, String url, HttpUriRequest request, String charset) throws IOException { + CloseableHttpResponse response = client.execute(request, HttpClientContext.create()); + return result(response, charset); + } + + @Override + public ByteArrayInputStream result(CloseableHttpResponse response, String charset) throws IOException { + InputStream in = null; + try { + HttpEntity entity = response.getEntity(); + if (entity != null) { + in = entity.getContent(); + byte[] buff = new byte[8000]; + int bytesRead; + ByteArrayOutputStream bao = new ByteArrayOutputStream(); + while ((bytesRead = in.read(buff)) != -1) { + bao.write(buff, 0, bytesRead); + } + byte[] data = bao.toByteArray(); + return new ByteArrayInputStream(data); + } + return null; + } finally { + if (response != null) { + response.close(); + } + if (in != null) { + in.close(); + } + } + } + }; +} \ No newline at end of file diff --git a/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/StreamResponseHandle.java b/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/StreamResponseHandle.java new file mode 100644 index 0000000..80e88c8 --- /dev/null +++ b/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/StreamResponseHandle.java @@ -0,0 +1,49 @@ +package com.fanruan.hihidata.datasource.server.http.rs; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class StreamResponseHandle extends BaseHttpResponseHandle { + + public static final StreamResponseHandle DEFAULT = new StreamResponseHandle(); + private static final int BUFFER_LENGTH = 8000; + + public StreamResponseHandle() { + } + + public StreamResponseHandle(String encoding) { + super(encoding); + } + + @Override + public ByteArrayInputStream parse(CloseableHttpResponse response) throws IOException { + InputStream in = null; + try { + HttpEntity entity = response.getEntity(); + if (entity != null) { + in = entity.getContent(); + byte[] buff = new byte[BUFFER_LENGTH]; + int bytesRead; + ByteArrayOutputStream bao = new ByteArrayOutputStream(); + while ((bytesRead = in.read(buff)) != -1) { + bao.write(buff, 0, bytesRead); + } + byte[] data = bao.toByteArray(); + return new ByteArrayInputStream(data); + } + return null; + } finally { + if (response != null) { + response.close(); + } + if (in != null) { + in.close(); + } + } + } +} diff --git a/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/TextResponseHandle.java b/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/TextResponseHandle.java new file mode 100644 index 0000000..5e8e091 --- /dev/null +++ b/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/TextResponseHandle.java @@ -0,0 +1,33 @@ +package com.fanruan.hihidata.datasource.server.http.rs; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; + +public class TextResponseHandle extends BaseHttpResponseHandle { + + public static final TextResponseHandle DEFAULT = new TextResponseHandle(); + + public TextResponseHandle() { + } + + public TextResponseHandle(String encoding) { + super(encoding); + } + + @Override + public String parse(CloseableHttpResponse response) throws IOException { + try { + HttpEntity entity = response.getEntity(); + String result = EntityUtils.toString(entity, getEncoding()); + EntityUtils.consume(entity); + return result; + } finally { + if (response != null) { + response.close(); + } + } + } +} diff --git a/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/UploadResponseHandle.java b/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/UploadResponseHandle.java new file mode 100644 index 0000000..115f7a5 --- /dev/null +++ b/src/main/java/com/fanruan/hihidata/datasource/server/http/rs/UploadResponseHandle.java @@ -0,0 +1,43 @@ +package com.fanruan.hihidata.datasource.server.http.rs; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpStatus; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; + + +public class UploadResponseHandle extends BaseHttpResponseHandle { + + public static final UploadResponseHandle DEFAULT = new UploadResponseHandle(); + + public UploadResponseHandle() { + } + + public UploadResponseHandle(String encoding) { + super(encoding); + } + + @Override + public Void parse(CloseableHttpResponse response) throws IOException { + try { + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode == HttpStatus.SC_OK) { + HttpEntity entity = response.getEntity(); + if (entity != null) { + EntityUtils.consume(entity); + } + } else { + HttpEntity entity = response.getEntity(); + String result = EntityUtils.toString(entity, getEncoding()); + throw new IOException("Connect error, error code:" + statusCode + "; message:" + result); + } + } finally { + if (response != null) { + response.close(); + } + } + return null; + } +}