From 1bfa66cc498383eeea28037990755c43b14d49d7 Mon Sep 17 00:00:00 2001
From: zhaojun <873019219@qq.com>
Date: Sat, 26 Nov 2022 17:54:07 +0800
Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E6=9B=B4=E6=96=B0=20onedrive=20?=
=?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=9A=84=20restTemplate=20=E5=AE=A2=E6=88=B7?=
=?UTF-8?q?=E7=AB=AF=EF=BC=8C=E5=A2=9E=E5=8A=A0=E6=97=A5=E5=BF=97=E8=AE=B0?=
=?UTF-8?q?=E5=BD=95=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=B9=B6=E7=A7=BB=E9=99=A4?=
=?UTF-8?q?=E8=AF=B7=E6=B1=82=E5=A4=B4=E4=B8=AD=E5=86=99=20storageId=20?=
=?UTF-8?q?=E6=9D=A5=E8=8E=B7=E5=8F=96=20AccessToken=20=E7=9A=84=E5=8A=9F?=
=?UTF-8?q?=E8=83=BD=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../zfile/core/config/RestTemplateConfig.java | 78 +---
.../core/exception/ZFileRetryException.java | 26 ++
.../ZFileOkHttp3ClientHttpRequestFactory.java | 22 ++
.../logging/HttpLoggingInterceptor.java | 340 ++++++++++++++++++
4 files changed, 401 insertions(+), 65 deletions(-)
create mode 100644 src/main/java/im/zhaojun/zfile/core/exception/ZFileRetryException.java
create mode 100644 src/main/java/im/zhaojun/zfile/core/httpclient/ZFileOkHttp3ClientHttpRequestFactory.java
create mode 100644 src/main/java/im/zhaojun/zfile/core/httpclient/logging/HttpLoggingInterceptor.java
diff --git a/src/main/java/im/zhaojun/zfile/core/config/RestTemplateConfig.java b/src/main/java/im/zhaojun/zfile/core/config/RestTemplateConfig.java
index d3e485b..86cef7b 100644
--- a/src/main/java/im/zhaojun/zfile/core/config/RestTemplateConfig.java
+++ b/src/main/java/im/zhaojun/zfile/core/config/RestTemplateConfig.java
@@ -1,25 +1,10 @@
package im.zhaojun.zfile.core.config;
-import im.zhaojun.zfile.module.storage.constant.StorageConfigConstant;
-import im.zhaojun.zfile.module.storage.model.entity.StorageSourceConfig;
-import im.zhaojun.zfile.module.storage.service.StorageSourceConfigService;
-import org.apache.http.client.HttpClient;
-import org.apache.http.impl.client.HttpClientBuilder;
+import im.zhaojun.zfile.core.httpclient.ZFileOkHttp3ClientHttpRequestFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.client.ClientHttpRequestInterceptor;
-import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
-import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
-import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
-import javax.annotation.Resource;
-import java.nio.charset.StandardCharsets;
-import java.util.Collections;
-import java.util.List;
-
/**
* restTemplate 相关配置
*
@@ -27,53 +12,16 @@ import java.util.List;
*/
@Configuration
public class RestTemplateConfig {
-
- @Resource
- private StorageSourceConfigService storageSourceConfigService;
-
- /**
- * OneDrive 请求 RestTemplate.
- * 获取 header 中的 storageId 来判断到底是哪个存储源 ID, 在请求头中添加 Bearer: Authorization {token} 信息, 用于 API 认证.
- */
- @Bean
- public RestTemplate oneDriveRestTemplate() {
- RestTemplate restTemplate = new RestTemplate();
- OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory();
- restTemplate.setRequestFactory(factory);
- ClientHttpRequestInterceptor interceptor = (httpRequest, bytes, clientHttpRequestExecution) -> {
- HttpHeaders headers = httpRequest.getHeaders();
- Integer storageId = Integer.valueOf(((List)headers.get("storageId")).get(0).toString());
-
- StorageSourceConfig accessTokenConfig =
- storageSourceConfigService.findByStorageIdAndName(storageId, StorageConfigConstant.ACCESS_TOKEN_KEY);
-
- String tokenValue = String.format("%s %s", "Bearer", accessTokenConfig.getValue());
- httpRequest.getHeaders().add("Authorization", tokenValue);
- return clientHttpRequestExecution.execute(httpRequest, bytes);
- };
- restTemplate.setInterceptors(Collections.singletonList(interceptor));
- return restTemplate;
- }
-
-
- /**
- * restTemplate 设置请求和响应字符集都为 UTF-8, 并设置响应头为 Content-Type: application/text;
- */
- @Bean
- public RestTemplate restTemplate(){
- HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
- HttpClient httpClient = HttpClientBuilder.create().build();
- httpRequestFactory.setHttpClient(httpClient);
- RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
- restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
- restTemplate.setInterceptors(Collections.singletonList((request, body, execution) -> {
- ClientHttpResponse response = execution.execute(request, body);
- HttpHeaders headers = response.getHeaders();
- headers.put("Content-Type", Collections.singletonList("application/text"));
- return response;
- }));
-
- return restTemplate;
- }
-
+
+ /**
+ * OneDrive 请求 RestTemplate.
+ * 获取 header 中的 storageId 来判断到底是哪个存储源 ID, 在请求头中添加 Bearer: Authorization {token} 信息, 用于 API 认证.
+ */
+ @Bean
+ public RestTemplate oneDriveRestTemplate() {
+ RestTemplate restTemplate = new RestTemplate();
+ restTemplate.setRequestFactory(new ZFileOkHttp3ClientHttpRequestFactory());
+ return restTemplate;
+ }
+
}
\ No newline at end of file
diff --git a/src/main/java/im/zhaojun/zfile/core/exception/ZFileRetryException.java b/src/main/java/im/zhaojun/zfile/core/exception/ZFileRetryException.java
new file mode 100644
index 0000000..28138e7
--- /dev/null
+++ b/src/main/java/im/zhaojun/zfile/core/exception/ZFileRetryException.java
@@ -0,0 +1,26 @@
+package im.zhaojun.zfile.core.exception;
+
+/**
+ * @author zhaojun
+ */
+public class ZFileRetryException extends RuntimeException {
+
+ public ZFileRetryException() {
+ }
+
+ public ZFileRetryException(String message) {
+ super(message);
+ }
+
+ public ZFileRetryException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ZFileRetryException(Throwable cause) {
+ super(cause);
+ }
+
+ public ZFileRetryException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/im/zhaojun/zfile/core/httpclient/ZFileOkHttp3ClientHttpRequestFactory.java b/src/main/java/im/zhaojun/zfile/core/httpclient/ZFileOkHttp3ClientHttpRequestFactory.java
new file mode 100644
index 0000000..97ee508
--- /dev/null
+++ b/src/main/java/im/zhaojun/zfile/core/httpclient/ZFileOkHttp3ClientHttpRequestFactory.java
@@ -0,0 +1,22 @@
+package im.zhaojun.zfile.core.httpclient;
+
+import im.zhaojun.zfile.core.httpclient.logging.HttpLoggingInterceptor;
+import okhttp3.OkHttpClient;
+import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
+
+/**
+ * 自建 OkHTTP3 客户端工厂类, 增加日志输出拦截器.
+ * @author zhaojun
+ */
+public class ZFileOkHttp3ClientHttpRequestFactory extends OkHttp3ClientHttpRequestFactory {
+
+ public ZFileOkHttp3ClientHttpRequestFactory() {
+ // 使用 OkHttp3 作为底层请求库, 并设置重试机制和日志拦截器
+ super(new OkHttpClient()
+ .newBuilder()
+ .addNetworkInterceptor(new HttpLoggingInterceptor(HttpLoggingInterceptor.Logger.DEBUG)
+ .setLevel(HttpLoggingInterceptor.Level.HEADERS))
+ .build());
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/im/zhaojun/zfile/core/httpclient/logging/HttpLoggingInterceptor.java b/src/main/java/im/zhaojun/zfile/core/httpclient/logging/HttpLoggingInterceptor.java
new file mode 100644
index 0000000..a84b66c
--- /dev/null
+++ b/src/main/java/im/zhaojun/zfile/core/httpclient/logging/HttpLoggingInterceptor.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2015 Square, Inc.
+ *
+ * Licensed 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 im.zhaojun.zfile.core.httpclient.logging;
+
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.Connection;
+import okhttp3.Headers;
+import okhttp3.Interceptor;
+import okhttp3.MediaType;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+import okhttp3.ResponseBody;
+import okhttp3.internal.http.HttpHeaders;
+import okhttp3.internal.platform.Platform;
+import okio.Buffer;
+import okio.BufferedSource;
+import okio.GzipSource;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.TimeUnit;
+
+import static okhttp3.internal.platform.Platform.INFO;
+
+/**
+ * 此类代码来源于 logging-interceptor.
+ *
+ * An OkHttp interceptor which logs request and response information. Can be applied as an
+ * {@linkplain OkHttpClient#interceptors() application interceptor} or as a {@linkplain
+ * OkHttpClient#networkInterceptors() network interceptor}.
The format of the logs created by
+ * this class should not be considered stable and may change slightly between releases. If you need
+ * a stable logging format, use your own interceptor.
+ *
+ * @author zhaojun
+ */
+@Slf4j
+public final class HttpLoggingInterceptor implements Interceptor {
+
+ private static final Charset UTF8 = StandardCharsets.UTF_8;
+
+ public enum Level {
+ /** No logs. */
+ NONE,
+ /**
+ * Logs request and response lines.
+ *
+ *
Example: + *
{@code
+ * --> POST /greeting http/1.1 (3-byte body)
+ *
+ * <-- 200 OK (22ms, 6-byte body)
+ * }
+ */
+ BASIC,
+ /**
+ * Logs request and response lines and their respective headers.
+ *
+ * Example: + *
{@code
+ * --> POST /greeting http/1.1
+ * Host: example.com
+ * Content-Type: plain/text
+ * Content-Length: 3
+ * --> END POST
+ *
+ * <-- 200 OK (22ms)
+ * Content-Type: plain/text
+ * Content-Length: 6
+ * <-- END HTTP
+ * }
+ */
+ HEADERS,
+ /**
+ * Logs request and response lines and their respective headers and bodies (if present).
+ *
+ * Example: + *
{@code
+ * --> POST /greeting http/1.1
+ * Host: example.com
+ * Content-Type: plain/text
+ * Content-Length: 3
+ *
+ * Hi?
+ * --> END POST
+ *
+ * <-- 200 OK (22ms)
+ * Content-Type: plain/text
+ * Content-Length: 6
+ *
+ * Hello!
+ * <-- END HTTP
+ * }
+ */
+ BODY
+ }
+
+ public interface Logger {
+ void log(String message);
+
+ /** A {@link Logger} defaults output appropriate for the current platform. */
+ Logger DEFAULT = message -> Platform.get().log(INFO, message, null);
+
+ Logger DEBUG = log::debug;
+ Logger TRACE = log::trace;
+
+ }
+
+ public HttpLoggingInterceptor() {
+ this(Logger.DEFAULT);
+ }
+
+ public HttpLoggingInterceptor(Logger logger) {
+ this.logger = logger;
+ }
+
+ private final Logger logger;
+
+ private volatile Set