diff --git a/README.md b/README.md
index 193f9df..286b015 100644
--- a/README.md
+++ b/README.md
@@ -49,7 +49,7 @@ gitee项目地址:[https://gitee.com/lianjiatech/retrofit-spring-boot-starter]
com.github.lianjiatech
retrofit-spring-boot-starter
- 2.3.7
+ 2.3.8
```
@@ -143,6 +143,17 @@ retrofit:
- response_status_not_2xx
- occur_io_exception
+ # 全局超时时间配置
+ global-timeout:
+ # 全局读取超时时间
+ read-timeout-ms: 10000
+ # 全局写入超时时间
+ write-timeout-ms: 10000
+ # 全局连接超时时间
+ connect-timeout-ms: 10000
+ # 全局完整调用超时时间
+ call-timeout-ms: 0
+
# 熔断降级配置
degrade:
# 熔断降级类型。默认none,表示不启用熔断降级
@@ -168,8 +179,15 @@ retrofit:
## 高级功能
+### 超时时间配置
+
+如果仅仅需要修改`OkHttpClient`的超时时间,可以通过`@RetrofitClient`相关字段修改,或者全局超时配置修改。
+
+
### 自定义OkHttpClient
+If you need to modify other configuration of `OkHttpClient`, you can do it by customizing `OkHttpClient`, the steps are as follows:
+
1. 实现`SourceOkHttpClientRegistrar`接口,调用`SourceOkHttpClientRegistry#register()`方法注册`OkHttpClient`。
```java
@@ -180,17 +198,6 @@ retrofit:
@Override
public void register(SourceOkHttpClientRegistry registry) {
- // 替换默认的SourceOkHttpClient,可以用来修改全局OkhttpClient设置
- registry.register(Constants.DEFAULT_SOURCE_OK_HTTP_CLIENT, new OkHttpClient.Builder()
- .connectTimeout(Duration.ofSeconds(5))
- .writeTimeout(Duration.ofSeconds(5))
- .readTimeout(Duration.ofSeconds(5))
- .addInterceptor(chain -> {
- log.info("============replace default SourceOkHttpClient=============");
- return chain.proceed(chain.request());
- })
- .build());
-
// 添加testSourceOkHttpClient
registry.register("testSourceOkHttpClient", new OkHttpClient.Builder()
.connectTimeout(Duration.ofSeconds(3))
diff --git a/README_EN.md b/README_EN.md
index 1a97ab1..aa32a0d 100644
--- a/README_EN.md
+++ b/README_EN.md
@@ -37,7 +37,7 @@
com.github.lianjiatech
retrofit-spring-boot-starter
- 2.3.7
+ 2.3.8
```
@@ -118,6 +118,11 @@ retrofit:
- response_status_not_2xx
- occur_io_exception
+ global-timeout:
+ read-timeout-ms: 10000
+ write-timeout-ms: 10000
+ connect-timeout-ms: 10000
+ call-timeout-ms: 0
degrade:
degrade-type: none
global-sentinel-degrade:
@@ -136,6 +141,10 @@ retrofit:
## Advanced Features
+### Timeout config
+
+If you only need to modify the timeout time of `OkHttpClient`, you can modify it through the relevant fields of `@RetrofitClient`, or modify the global timeout configuration.
+
### Customize OkHttpClient
1. Implement the `SourceOkHttpClientRegistrar` interface and call the `SourceOkHttpClientRegistry#register()` method to register the `OkHttpClient`.
diff --git a/pom.xml b/pom.xml
index 1391fb0..e6c1917 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.github.lianjiatech
retrofit-spring-boot-starter
- 2.3.7
+ 2.3.8
retrofit-spring-boot-starter
retrofit-spring-boot-starter
@@ -41,7 +41,7 @@
4.13.1
1.3.2
1.7.25
- 2.0.9.RELEASE
+ 2.2.11.RELEASE
3.14.9
1.6.3
2.12.6.1
@@ -58,7 +58,7 @@
org.springframework.cloud
spring-cloud-commons
- 2.0.4.RELEASE
+ 2.2.9.RELEASE
provided
diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/GlobalTimeoutProperty.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/GlobalTimeoutProperty.java
new file mode 100644
index 0000000..3a0268f
--- /dev/null
+++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/GlobalTimeoutProperty.java
@@ -0,0 +1,32 @@
+package com.github.lianjiatech.retrofit.spring.boot.config;
+
+import lombok.Data;
+
+/**
+ * 只有在@RetrofitClient.sourceOkHttpClient为NO_SOURCE_OK_HTTP_CLIENT时才有效
+ * @author 陈添明
+ * @since 2022/10/7 4:23 下午
+ */
+@Data
+public class GlobalTimeoutProperty {
+
+ /**
+ * 全局连接超时时间
+ */
+ private int connectTimeoutMs = 10_000;
+
+ /**
+ * 全局读取超时时间
+ */
+ private int readTimeoutMs = 10_000;
+
+ /**
+ * 全局写入超时时间
+ */
+ private int writeTimeoutMs = 10_000;
+
+ /**
+ * 全局完整调用超时时间
+ */
+ private int callTimeoutMs = 0;
+}
diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/RetrofitProperties.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/RetrofitProperties.java
index 9cc71dd..2ecab59 100644
--- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/RetrofitProperties.java
+++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/RetrofitProperties.java
@@ -42,6 +42,12 @@ public class RetrofitProperties {
@NestedConfigurationProperty
private GlobalLogProperty globalLog = new GlobalLogProperty();
+ /**
+ * 全局超时配置
+ */
+ @NestedConfigurationProperty
+ private GlobalTimeoutProperty globalTimeout = new GlobalTimeoutProperty();
+
/**
* 全局转换器工厂,转换器实例优先从Spring容器获取,如果没有获取到,则反射创建。
* global converter factories, The converter instance is first obtained from the Spring container. If it is not obtained, it is created by reflection.
diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/Constants.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/Constants.java
index e283242..b4abb30 100644
--- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/Constants.java
+++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/Constants.java
@@ -8,7 +8,7 @@ public interface Constants {
String STR_EMPTY = "";
- String DEFAULT_SOURCE_OK_HTTP_CLIENT = "defaultSourceOkHttpClient";
+ String NO_SOURCE_OK_HTTP_CLIENT = "";
String SPH_U_CLASS_NAME = "com.alibaba.csp.sentinel.SphU";
@@ -19,4 +19,6 @@ public interface Constants {
String RETROFIT = "retrofit";
String DEFAULT_CIRCUIT_BREAKER_CONFIG = "defaultCircuitBreakerConfig";
+
+ int INVALID_TIMEOUT_VALUE = -1;
}
diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/RetrofitClient.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/RetrofitClient.java
index f8d78c5..93bc8e1 100644
--- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/RetrofitClient.java
+++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/RetrofitClient.java
@@ -92,6 +92,42 @@
/**
* 原始OkHttpClient,根据该名称到#{@link SourceOkHttpClientRegistry}查找对应的OkHttpClient来构建当前接口的OkhttpClient。
*/
- String sourceOkHttpClient() default Constants.DEFAULT_SOURCE_OK_HTTP_CLIENT;
+ String sourceOkHttpClient() default Constants.NO_SOURCE_OK_HTTP_CLIENT;
+
+
+ /*===============以下属性只有在sourceOkHttpClient为NO_SOURCE_OK_HTTP_CLIENT时才有效=================*/
+
+ /**
+ * Sets the default connect timeout for new connections. A value of 0 means no timeout,
+ * otherwise values must be between 1 and Integer.MAX_VALUE when converted to milliseconds.
+ * If it is configured as -1, the global default configuration is used.
+ *
+ */
+ int connectTimeoutMs() default Constants.INVALID_TIMEOUT_VALUE;
+
+ /**
+ * Sets the default read timeout for new connections. A value of 0 means no timeout,
+ * otherwise values must be between 1 and Integer.MAX_VALUE when converted to milliseconds.
+ * If it is configured as -1, the global default configuration is used.
+ *
+ */
+ int readTimeoutMs() default Constants.INVALID_TIMEOUT_VALUE;
+
+ /**
+ * Sets the default write timeout for new connections. A value of 0 means no timeout,
+ * otherwise values must be between 1 and Integer.MAX_VALUE when converted to milliseconds.
+ * If it is configured as -1, the global default configuration is used.
+ *
+ */
+ int writeTimeoutMs() default Constants.INVALID_TIMEOUT_VALUE;
+
+
+ /**
+ * Sets the default timeout for complete calls. A value of 0 means no timeout,
+ * otherwise values must be between 1 and Integer.MAX_VALUE when converted to milliseconds.
+ * If it is configured as -1, the global default configuration is used.
+ *
+ */
+ int callTimeoutMs() default Constants.INVALID_TIMEOUT_VALUE;
}
diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/RetrofitFactoryBean.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/RetrofitFactoryBean.java
index 482269d..711ca2f 100644
--- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/RetrofitFactoryBean.java
+++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/RetrofitFactoryBean.java
@@ -8,7 +8,10 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import com.github.lianjiatech.retrofit.spring.boot.config.GlobalTimeoutProperty;
+import com.github.lianjiatech.retrofit.spring.boot.config.RetrofitProperties;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
@@ -90,9 +93,32 @@ public boolean isSingleton() {
private OkHttpClient createOkHttpClient() {
RetrofitClient retrofitClient =
AnnotatedElementUtils.findMergedAnnotation(retrofitInterface, RetrofitClient.class);
- OkHttpClient sourceOkHttpClient = retrofitConfigBean.getSourceOkHttpClientRegistry()
- .get(Objects.requireNonNull(retrofitClient).sourceOkHttpClient());
- OkHttpClient.Builder okHttpClientBuilder = sourceOkHttpClient.newBuilder();
+
+ OkHttpClient.Builder okHttpClientBuilder;
+ if (Constants.NO_SOURCE_OK_HTTP_CLIENT.equals(Objects.requireNonNull(retrofitClient).sourceOkHttpClient())) {
+ // 使用默认超时时间创建OkHttpClient
+ GlobalTimeoutProperty globalTimeout = retrofitConfigBean.getRetrofitProperties().getGlobalTimeout();
+
+ int connectTimeoutMs = retrofitClient.connectTimeoutMs() == Constants.INVALID_TIMEOUT_VALUE
+ ? globalTimeout.getConnectTimeoutMs() : retrofitClient.connectTimeoutMs();
+ int readTimeoutMs = retrofitClient.readTimeoutMs() == Constants.INVALID_TIMEOUT_VALUE
+ ? globalTimeout.getReadTimeoutMs() : retrofitClient.readTimeoutMs();
+ int writeTimeoutMs = retrofitClient.writeTimeoutMs() == Constants.INVALID_TIMEOUT_VALUE
+ ? globalTimeout.getWriteTimeoutMs() : retrofitClient.writeTimeoutMs();
+ int callTimeoutMs = retrofitClient.callTimeoutMs() == Constants.INVALID_TIMEOUT_VALUE
+ ? globalTimeout.getCallTimeoutMs() : retrofitClient.callTimeoutMs();
+
+ okHttpClientBuilder = new OkHttpClient.Builder()
+ .connectTimeout(connectTimeoutMs, TimeUnit.MILLISECONDS)
+ .readTimeout(readTimeoutMs, TimeUnit.MILLISECONDS)
+ .writeTimeout(writeTimeoutMs, TimeUnit.MILLISECONDS)
+ .callTimeout(callTimeoutMs, TimeUnit.MILLISECONDS);
+ } else {
+ OkHttpClient sourceOkHttpClient = retrofitConfigBean.getSourceOkHttpClientRegistry()
+ .get(retrofitClient.sourceOkHttpClient());
+ okHttpClientBuilder = sourceOkHttpClient.newBuilder();
+ }
+
if (isEnableDegrade(retrofitInterface)) {
okHttpClientBuilder.addInterceptor(retrofitConfigBean.getRetrofitDegrade());
}
@@ -159,7 +185,8 @@ private List findInterceptorByAnnotation() {
private Retrofit createRetrofit() {
RetrofitClient retrofitClient =
AnnotatedElementUtils.findMergedAnnotation(retrofitInterface, RetrofitClient.class);
- String baseUrl = RetrofitUtils.convertBaseUrl(retrofitClient, retrofitClient.baseUrl(), environment);
+ String baseUrl = RetrofitUtils.convertBaseUrl(retrofitClient, Objects.requireNonNull(retrofitClient).baseUrl(),
+ environment);
OkHttpClient client = createOkHttpClient();
Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
@@ -186,7 +213,7 @@ private Retrofit createRetrofit() {
converterFactories.addAll(Arrays.asList(retrofitClient.converterFactories()));
converterFactories.addAll(Arrays.asList(retrofitConfigBean.getGlobalConverterFactoryClasses()));
converterFactories.forEach(converterFactoryClass -> retrofitBuilder
- .addConverterFactory(AppContextUtils.getBeanOrNew(applicationContext, converterFactoryClass)));
+ .addConverterFactory(AppContextUtils.getBeanOrNew(applicationContext, converterFactoryClass)));
return retrofitBuilder.build();
}
diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/SourceOkHttpClientRegistry.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/SourceOkHttpClientRegistry.java
index 72845b2..89e1e40 100644
--- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/SourceOkHttpClientRegistry.java
+++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/SourceOkHttpClientRegistry.java
@@ -23,8 +23,7 @@ public class SourceOkHttpClientRegistry {
public SourceOkHttpClientRegistry(List registrars) {
this.registrars = registrars;
- this.okHttpClientMap = new HashMap<>(8);
- this.okHttpClientMap.put(Constants.DEFAULT_SOURCE_OK_HTTP_CLIENT, new OkHttpClient());
+ this.okHttpClientMap = new HashMap<>(4);
}
@PostConstruct
diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/custom/okhttp/CustomSourceOkHttpClientRegistrar.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/custom/okhttp/CustomSourceOkHttpClientRegistrar.java
index a7f6d5c..9edebf1 100644
--- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/custom/okhttp/CustomSourceOkHttpClientRegistrar.java
+++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/custom/okhttp/CustomSourceOkHttpClientRegistrar.java
@@ -22,18 +22,7 @@ public class CustomSourceOkHttpClientRegistrar implements SourceOkHttpClientRegi
@Override
public void register(SourceOkHttpClientRegistry registry) {
- // 替换默认的SourceOkHttpClient,可以用来修改全局OkhttpClient设置
- registry.register(Constants.DEFAULT_SOURCE_OK_HTTP_CLIENT, new OkHttpClient.Builder()
- .connectTimeout(Duration.ofSeconds(5))
- .writeTimeout(Duration.ofSeconds(5))
- .readTimeout(Duration.ofSeconds(5))
- .addInterceptor(chain -> {
- log.info("============replace default SourceOkHttpClient=============");
- return chain.proceed(chain.request());
- })
- .build());
-
- // 添加testSourceOkHttpClient
+ // 注册testSourceOkHttpClient
registry.register("testSourceOkHttpClient", new OkHttpClient.Builder()
.connectTimeout(Duration.ofSeconds(3))
.writeTimeout(Duration.ofSeconds(3))
diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/timeout/TimeoutTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/timeout/TimeoutTest.java
new file mode 100644
index 0000000..6497940
--- /dev/null
+++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/timeout/TimeoutTest.java
@@ -0,0 +1,80 @@
+package com.github.lianjiatech.retrofit.spring.boot.test.timeout;
+
+import java.io.IOException;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.lianjiatech.retrofit.spring.boot.test.RetrofitTestApplication;
+import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person;
+import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result;
+
+import okhttp3.mockwebserver.MockResponse;
+import okhttp3.mockwebserver.MockWebServer;
+
+/**
+ * @author 陈添明
+ */
+@SpringBootTest(classes = RetrofitTestApplication.class)
+@RunWith(SpringRunner.class)
+public class TimeoutTest {
+
+ @Autowired
+ private TimeoutTestApi timeoutTestApi;
+
+ private MockWebServer server;
+
+ private static final ObjectMapper objectMapper =
+ new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+ .setSerializationInclusion(JsonInclude.Include.NON_NULL);
+
+ @Before
+ public void before() throws IOException {
+ System.out.println("=========开启MockWebServer===========");
+ server = new MockWebServer();
+ server.start(8080);
+
+ }
+
+ @After
+ public void after() throws IOException {
+ System.out.println("=========关闭MockWebServer===========");
+ server.close();
+ }
+
+ @Test
+ public void test() throws JsonProcessingException {
+ // mock
+ Person mockPerson = new Person().setId(1L)
+ .setName("test")
+ .setAge(10);
+ Result mockResult = new Result<>()
+ .setCode(0)
+ .setMsg("ok")
+ .setData(mockPerson);
+ MockResponse response = new MockResponse()
+ .setResponseCode(200)
+ .addHeader("Content-Type", "application/json; charset=utf-8")
+ .addHeader("Cache-Control", "no-cache")
+ .setBody(objectMapper.writeValueAsString(mockResult));
+ server.enqueue(response);
+
+ // http check
+ Result person = timeoutTestApi.getPerson(1L);
+ Person data = person.getData();
+ Assert.assertNotNull(data);
+ Assert.assertEquals("test", data.getName());
+ Assert.assertEquals(10, data.getAge().intValue());
+ }
+
+}
diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/timeout/TimeoutTestApi.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/timeout/TimeoutTestApi.java
new file mode 100644
index 0000000..a654cf2
--- /dev/null
+++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/timeout/TimeoutTestApi.java
@@ -0,0 +1,24 @@
+package com.github.lianjiatech.retrofit.spring.boot.test.timeout;
+
+import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient;
+import com.github.lianjiatech.retrofit.spring.boot.log.LogStrategy;
+import com.github.lianjiatech.retrofit.spring.boot.log.Logging;
+import com.github.lianjiatech.retrofit.spring.boot.test.InvalidRespErrorDecoder;
+import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person;
+
+import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result;
+import retrofit2.http.Body;
+import retrofit2.http.GET;
+import retrofit2.http.POST;
+import retrofit2.http.Query;
+
+/**
+ * @author 陈添明
+ */
+@Logging(logStrategy = LogStrategy.BODY)
+@RetrofitClient(baseUrl = "${test.baseUrl}", readTimeoutMs = 2000)
+public interface TimeoutTestApi {
+
+ @GET("person")
+ Result getPerson(@Query("id") Long id);
+}
diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml
index bdd7512..ea3ca37 100644
--- a/src/test/resources/application.yml
+++ b/src/test/resources/application.yml
@@ -30,6 +30,18 @@ retrofit:
- response_status_not_2xx
- occur_io_exception
+ # 全局超时时间配置
+ global-timeout:
+ # 全局读取超时时间
+ read-timeout-ms: 10000
+ # 全局写入超时时间
+ write-timeout-ms: 10000
+ # 全局连接超时时间
+ connect-timeout-ms: 10000
+ # 全局完整调用超时时间
+ call-timeout-ms: 0
+
+
# 熔断降级配置
degrade:
# 熔断降级类型。默认none,表示不启用熔断降级
diff --git a/src/test/resources/default-config.yml b/src/test/resources/default-config.yml
index a7b3e09..dfc5193 100644
--- a/src/test/resources/default-config.yml
+++ b/src/test/resources/default-config.yml
@@ -27,6 +27,18 @@ retrofit:
- response_status_not_2xx
- occur_io_exception
+ # 全局超时时间配置
+ global-timeout:
+ # 全局读取超时时间
+ read-timeout-ms: 10000
+ # 全局写入超时时间
+ write-timeout-ms: 10000
+ # 全局连接超时时间
+ connect-timeout-ms: 10000
+ # 全局完整调用超时时间
+ call-timeout-ms: 0
+
+
# 熔断降级配置
degrade:
# 熔断降级类型。默认none,表示不启用熔断降级