From c84cfc8c7189653d7aacd91db06214c717419fac Mon Sep 17 00:00:00 2001 From: chentianming Date: Sun, 17 Dec 2023 20:06:15 +0800 Subject: [PATCH] Optimized aggregate log printing and integration testing --- .travis.yml | 2 +- README.md | 302 +++++------- README_EN.md | 295 +++++------- pom.xml | 29 +- .../boot/config/RetrofitProperties.java | 2 +- .../boot/core/ServiceInstanceChooser.java | 3 +- .../spring/boot/degrade/DegradeProxy.java | 9 +- .../resilience4j/Resilience4jDegrade.java | 2 +- .../boot/log/AggregateLoggingInterceptor.java | 55 --- .../spring/boot/log/GlobalLogProperty.java | 7 +- .../retrofit/spring/boot/log/Logging.java | 6 + .../spring/boot/log/LoggingInterceptor.java | 32 +- .../spring/boot/retry/RetryInterceptor.java | 13 +- .../spring/boot/other/OtherPathApi.java | 29 -- .../spring/boot/test/InterceptTest.java | 78 --- .../boot/test/InvalidRespErrorDecoder.java | 16 - .../boot/test/MySpringBootApplication.java | 24 - .../spring/boot/test/OtherPathTest.java | 81 ---- .../test/RetrofitConvertFactoriesTest.java | 78 --- .../boot/test/RetrofitExceptionTest.java | 85 ---- .../spring/boot/test/RetrofitStarterTest.java | 447 ------------------ .../boot/test/RetrofitTestApplication.java | 45 -- .../test/custom/okhttp/CustomOkHttpTest.java | 80 ---- .../custom/okhttp/CustomOkHttpTestApi.java | 25 - .../CustomSourceOkHttpClientRegistrar.java | 36 -- .../boot/test/decoder/ErrorDecoderTest.java | 78 --- .../test/decoder/ErrorDecoderTestApi.java | 21 - .../boot/test/degrade/DegradeR4jApi.java | 67 --- .../boot/test/degrade/DegradeR4jTest.java | 90 ---- .../boot/test/degrade/DegradeSentinelApi.java | 31 -- .../degrade/DegradeSentinelApiFallback.java | 33 -- .../test/degrade/DegradeSentinelTest.java | 98 ---- .../spring/boot/test/entity/Person.java | 18 - .../spring/boot/test/entity/Result.java | 19 - .../spring/boot/test/ex/AppException.java | 79 ---- .../spring/boot/test/ex/AppIOException.java | 79 ---- .../spring/boot/test/ex/TestErrorDecoder.java | 38 -- .../test/http/ConvertFactoriesTestApi.java | 21 - .../spring/boot/test/http/HttpApi.java | 102 ---- .../spring/boot/test/http/HttpApi2.java | 37 -- .../spring/boot/test/http/HttpApi3.java | 19 - .../spring/boot/test/http/InterceptApi.java | 28 -- .../test/integration/MockWebServerTest.java | 104 ++++ .../integration/RetrofitBootApplication.java | 16 + .../test/integration/base/UserService.java | 78 +++ .../integration/base/UserServiceTest.java | 149 ++++++ .../chooser/ChooserOkHttpUserService.java | 21 + .../chooser/ChooserOkHttpUserServiceTest.java | 39 ++ .../chooser/MyServiceInstanceChooser.java | 22 + .../okhttp/CustomOkHttpClientRegistrar.java | 30 ++ .../okhttp/CustomOkHttpUserService.java | 20 + .../okhttp/CustomOkHttpUserServiceTest.java | 30 ++ .../CustomCircuitBreakerConfigRegistrar.java | 17 +- .../GlobalResilience4jFallbackFactory.java | 23 + .../GlobalResilience4jUserService.java | 22 + .../GlobalResilience4jUserServiceTest.java | 44 ++ .../Resilience4jFallbackFactory.java | 33 ++ .../resilience4j/Resilience4jUserService.java | 34 ++ .../Resilience4jUserServiceTest.java | 56 +++ .../GlobalSentinelFallbackUserService.java | 15 + .../sentinel/GlobalSentinelUserService.java | 21 + .../GlobalSentinelUserServiceTest.java | 44 ++ .../sentinel/SentinelFallbackUserService.java | 22 + .../degrade/sentinel/SentinelUserService.java | 33 ++ .../sentinel/SentinelUserServiceTest.java | 56 +++ .../boot/test/integration/entity/User.java | 21 + .../interceptor/InterceptorUserService.java | 40 ++ .../InterceptorUserServiceTest.java | 96 ++++ .../interceptor/MyGlobalInterceptor.java | 21 + .../interceptor/PathMatchInterceptor.java | 23 + .../{ => integration}/interceptor/Sign.java | 2 +- .../interceptor/SignInterceptor.java | 6 +- .../log/GlobalRetryUserServiceTest.java | 59 +++ .../test/integration/log/LogUserService.java | 41 ++ .../annotation/MetaAnnotationUserService.java | 20 + .../MetaAnnotationUserServiceTest.java | 39 ++ .../meta/annotation}/MyRetrofitClient.java | 26 +- .../reactive/mono/MonoUserService.java | 21 + .../reactive/mono/MonoUserServiceTest.java | 42 ++ .../reactive/rx/RxJava2UserService.java | 31 ++ .../reactive/rx/RxJava2UserServiceTest.java | 49 ++ .../reactive/rx/RxJava3UserService.java | 33 ++ .../reactive/rx/RxJava3UserServiceTest.java | 50 ++ .../retry/GlobalRetryUserService.java | 39 ++ .../retry/GlobalRetryUserServiceTest.java | 65 +++ .../integration/retry/RetryUserService.java | 40 ++ .../retry/RetryUserServiceTest.java | 63 +++ .../timeout/TimeoutUserService.java | 20 + .../timeout/TimeoutUserServiceTest.java | 30 ++ .../boot/test/interceptor/EnumIntercept.java | 47 -- .../test/interceptor/EnumInterceptor.java | 38 -- .../spring/boot/test/interceptor/EnvEnum.java | 11 - .../interceptor/SourceGlobalInterceptor.java | 32 -- .../TestPriorityGlobalInterceptor.java | 24 - .../interceptor/TimeStamp2Interceptor.java | 32 -- .../interceptor/TimeStampInterceptor.java | 39 -- .../boot/test/meta/MetaAnnotationTest.java | 78 --- .../boot/test/meta/MetaAnnotationTestApi.java | 24 - .../completable/Rxjava2CompletableTest.java | 65 --- .../Rxjava2CompletableTestApi.java | 16 - .../completable/Rxjava3CompletableTest.java | 65 --- .../Rxjava3CompletableTestApi.java | 16 - .../boot/test/reactive/mono/MonoTest.java | 126 ----- .../boot/test/reactive/mono/MonoTestApi.java | 26 - .../reactive/single/Rxjava2SingleTest.java | 113 ----- .../reactive/single/Rxjava2SingleTestApi.java | 23 - .../reactive/single/Rxjava3SingleTest.java | 113 ----- .../reactive/single/Rxjava3SingleTestApi.java | 23 - .../spring/boot/test/service/TestService.java | 14 - .../spring/boot/test/timeout/TimeoutTest.java | 80 ---- .../boot/test/timeout/TimeoutTestApi.java | 24 - src/test/resources/application-r4j.yml | 11 - src/test/resources/application-sentinel.yml | 15 - src/test/resources/application.yml | 17 +- src/test/resources/default-config.yml | 64 --- 115 files changed, 2114 insertions(+), 3467 deletions(-) delete mode 100644 src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/AggregateLoggingInterceptor.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/other/OtherPathApi.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/InterceptTest.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/InvalidRespErrorDecoder.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/MySpringBootApplication.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/OtherPathTest.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitConvertFactoriesTest.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitExceptionTest.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitStarterTest.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitTestApplication.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/custom/okhttp/CustomOkHttpTest.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/custom/okhttp/CustomOkHttpTestApi.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/custom/okhttp/CustomSourceOkHttpClientRegistrar.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/decoder/ErrorDecoderTest.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/decoder/ErrorDecoderTestApi.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeR4jApi.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeR4jTest.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeSentinelApi.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeSentinelApiFallback.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeSentinelTest.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/entity/Person.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/entity/Result.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/ex/AppException.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/ex/AppIOException.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/ex/TestErrorDecoder.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/ConvertFactoriesTestApi.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/HttpApi.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/HttpApi2.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/HttpApi3.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/InterceptApi.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/MockWebServerTest.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/RetrofitBootApplication.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/base/UserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/base/UserServiceTest.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/chooser/ChooserOkHttpUserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/chooser/ChooserOkHttpUserServiceTest.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/chooser/MyServiceInstanceChooser.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/custom/okhttp/CustomOkHttpClientRegistrar.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/custom/okhttp/CustomOkHttpUserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/custom/okhttp/CustomOkHttpUserServiceTest.java rename src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/{degrade => integration/degrade/resilience4j}/CustomCircuitBreakerConfigRegistrar.java (76%) create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/GlobalResilience4jFallbackFactory.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/GlobalResilience4jUserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/GlobalResilience4jUserServiceTest.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/Resilience4jFallbackFactory.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/Resilience4jUserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/Resilience4jUserServiceTest.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/GlobalSentinelFallbackUserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/GlobalSentinelUserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/GlobalSentinelUserServiceTest.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/SentinelFallbackUserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/SentinelUserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/SentinelUserServiceTest.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/entity/User.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/InterceptorUserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/InterceptorUserServiceTest.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/MyGlobalInterceptor.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/PathMatchInterceptor.java rename src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/{ => integration}/interceptor/Sign.java (94%) rename src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/{ => integration}/interceptor/SignInterceptor.java (74%) create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/log/GlobalRetryUserServiceTest.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/log/LogUserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/meta/annotation/MetaAnnotationUserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/meta/annotation/MetaAnnotationUserServiceTest.java rename src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/{meta => integration/meta/annotation}/MyRetrofitClient.java (90%) create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/mono/MonoUserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/mono/MonoUserServiceTest.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/rx/RxJava2UserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/rx/RxJava2UserServiceTest.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/rx/RxJava3UserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/rx/RxJava3UserServiceTest.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/retry/GlobalRetryUserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/retry/GlobalRetryUserServiceTest.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/retry/RetryUserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/retry/RetryUserServiceTest.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/timeout/TimeoutUserService.java create mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/timeout/TimeoutUserServiceTest.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/EnumIntercept.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/EnumInterceptor.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/EnvEnum.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/SourceGlobalInterceptor.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/TestPriorityGlobalInterceptor.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/TimeStamp2Interceptor.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/TimeStampInterceptor.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/meta/MetaAnnotationTest.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/meta/MetaAnnotationTestApi.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/completable/Rxjava2CompletableTest.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/completable/Rxjava2CompletableTestApi.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/completable/Rxjava3CompletableTest.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/completable/Rxjava3CompletableTestApi.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/mono/MonoTest.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/mono/MonoTestApi.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/single/Rxjava2SingleTest.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/single/Rxjava2SingleTestApi.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/single/Rxjava3SingleTest.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/single/Rxjava3SingleTestApi.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/service/TestService.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/timeout/TimeoutTest.java delete mode 100644 src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/timeout/TimeoutTestApi.java delete mode 100644 src/test/resources/application-r4j.yml delete mode 100644 src/test/resources/application-sentinel.yml delete mode 100644 src/test/resources/default-config.yml diff --git a/.travis.yml b/.travis.yml index 751065b..e9ad1f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ language: java jdk: - openjdk17 -install: mvn install -DskipTests=true -Dmaven.javadoc.skip=true -Dgpg.skip=true +install: mvn clean install -Dmaven.javadoc.skip=true -Dgpg.skip=true diff --git a/README.md b/README.md index 4d59460..57694ff 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ gitee项目地址:[https://gitee.com/lianjiatech/retrofit-spring-boot-starter] com.github.lianjiatech retrofit-spring-boot-starter - 3.0.2 + 3.0.3 ``` @@ -63,10 +63,13 @@ gitee项目地址:[https://gitee.com/lianjiatech/retrofit-spring-boot-starter] ```java @RetrofitClient(baseUrl = "${test.baseUrl}") -public interface HttpApi { +public interface UserService { - @GET("person") - Result getPerson(@Query("id") Long id); + /** + * 根据id查询用户姓名 + */ + @POST("getName") + String getName(@Query("id") Long id); } ``` @@ -78,13 +81,13 @@ public interface HttpApi { ```java @Service -public class TestService { +public class BusinessService { @Autowired - private HttpApi httpApi; + private UserService userService; - public void test() { - // 使用`httpApi`发起HTTP请求 + public void doBusiness() { + // call userService } } ``` @@ -131,6 +134,8 @@ retrofit: log-level: info # 全局日志打印策略 log-strategy: basic + # 是否聚合打印请求日志 + aggregate: true # 全局重试配置 global-retry: @@ -192,44 +197,40 @@ retrofit: 如果需要修改`OkHttpClient`其它配置,可以通过自定义`OkHttpClient`来实现,步骤如下: -1. 实现`SourceOkHttpClientRegistrar`接口,调用`SourceOkHttpClientRegistry#register()`方法注册`OkHttpClient`。 - - ```java - @Slf4j - @Component - public class CustomSourceOkHttpClientRegistrar implements SourceOkHttpClientRegistrar { +**实现`SourceOkHttpClientRegistrar`接口,调用`SourceOkHttpClientRegistry#register()`方法注册`OkHttpClient`** - @Override - public void register(SourceOkHttpClientRegistry registry) { - - // 添加testSourceOkHttpClient - registry.register("testSourceOkHttpClient", new OkHttpClient.Builder() - .connectTimeout(Duration.ofSeconds(3)) - .writeTimeout(Duration.ofSeconds(3)) - .readTimeout(Duration.ofSeconds(3)) - .addInterceptor(chain -> { - log.info("============use testSourceOkHttpClient============="); - return chain.proceed(chain.request()); - }) - .build()); - } - } - ``` - -2. 通过`@RetrofitClient.sourceOkHttpClient`指定当前接口要使用的`OkHttpClient`。 +```java +@Component +public class CustomOkHttpClientRegistrar implements SourceOkHttpClientRegistrar { - ```java - @RetrofitClient(baseUrl = "${test.baseUrl}", sourceOkHttpClient = "testSourceOkHttpClient") - public interface CustomOkHttpTestApi { - - @GET("person") - Result getPerson(@Query("id") Long id); + @Override + public void register(SourceOkHttpClientRegistry registry) { + // 注册customOkHttpClient,超时时间设置为1s + registry.register("customOkHttpClient", new OkHttpClient.Builder() + .connectTimeout(Duration.ofSeconds(1)) + .writeTimeout(Duration.ofSeconds(1)) + .readTimeout(Duration.ofSeconds(1)) + .addInterceptor(chain -> chain.proceed(chain.request())) + .build()); } - ``` +} +``` -> 注意:组件不会直接使用指定的`OkHttpClient`,而是基于该`OkHttpClient`创建一个新的。 +**通过`@RetrofitClient.sourceOkHttpClient`指定当前接口要使用的`OkHttpClient`** +```java +@RetrofitClient(baseUrl = "${test.baseUrl}", sourceOkHttpClient = "customOkHttpClient") +public interface CustomOkHttpUserService { + /** + * 根据id查询用户信息 + */ + @GET("getUser") + User getUser(@Query("id") Long id); +} +``` + +> 注意:组件不会直接使用指定的`OkHttpClient`,而是基于该`OkHttpClient`创建一个新的。 ### 注解式拦截器 @@ -240,27 +241,17 @@ retrofit: > 如果需要使用多个拦截器,在接口上标注多个`@Intercept`注解即可。 -下面以"给指定请求的url后面拼接timestamp时间戳"为例,介绍下如何使用注解式拦截器。 - #### 继承`BasePathMatchInterceptor`编写拦截处理器 ```java @Component -public class TimeStampInterceptor extends BasePathMatchInterceptor { - - @Override - public Response doIntercept(Chain chain) throws IOException { - Request request = chain.request(); - HttpUrl url = request.url(); - long timestamp = System.currentTimeMillis(); - HttpUrl newUrl = url.newBuilder() - .addQueryParameter("timestamp", String.valueOf(timestamp)) - .build(); - Request newRequest = request.newBuilder() - .url(newUrl) - .build(); - return chain.proceed(newRequest); - } +public class PathMatchInterceptor extends BasePathMatchInterceptor { + @Override + protected Response doIntercept(Chain chain) throws IOException { + Response response = chain.proceed(chain.request()); + // response的Header加上path.match + return response.newBuilder().header("path.match", "true").build(); + } } ``` @@ -270,12 +261,8 @@ public class TimeStampInterceptor extends BasePathMatchInterceptor { ```java @Component @Scope("prototype") -public class TimeStampInterceptor extends BasePathMatchInterceptor { - - @Override - public Response doIntercept(Chain chain) throws IOException { - // ... - } +public class PathMatchInterceptor extends BasePathMatchInterceptor { + } ``` @@ -283,20 +270,26 @@ public class TimeStampInterceptor extends BasePathMatchInterceptor { ```java @RetrofitClient(baseUrl = "${test.baseUrl}") -@Intercept(handler = TimeStampInterceptor.class, include = {"/api/**"}, exclude = "/api/test/savePerson") -@Intercept(handler = TimeStamp2Interceptor.class) // 需要多个,直接添加即可 -public interface HttpApi { +@Intercept(handler = PathMatchInterceptor.class, include = {"/api/user/**"}, exclude = "/api/user/getUser") +// @Intercept() 如果需要使用多个路径匹配拦截器,继续添加@Intercept即可 +public interface InterceptorUserService { - @GET("person") - Result getPerson(@Query("id") Long id); + /** + * 根据id查询用户姓名 + */ + @POST("getName") + Response getName(@Query("id") Long id); + + /** + * 根据id查询用户信息 + */ + @GET("getUser") + Response getUser(@Query("id") Long id); - @POST("savePerson") - Result savePerson(@Body Person person); } ``` -上面的`@Intercept`配置表示:拦截`HttpApi`接口下`/api/**`路径下(排除`/api/test/savePerson`)的请求,拦截处理器使用`TimeStampInterceptor`。 - +上面的`@Intercept`配置表示:拦截`InterceptorUserService`接口下`/api/user/**`路径下(排除`/api/user/getUser`)的请求,拦截处理器使用`PathMatchInterceptor`。 ### 自定义拦截注解 @@ -337,29 +330,24 @@ public @interface Sign { ```java @Component +@Setter public class SignInterceptor extends BasePathMatchInterceptor { - private String accessKeyId; - - private String accessKeySecret; - - public void setAccessKeyId(String accessKeyId) { - this.accessKeyId = accessKeyId; - } + private String accessKeyId; - public void setAccessKeySecret(String accessKeySecret) { - this.accessKeySecret = accessKeySecret; - } + private String accessKeySecret; - @Override - public Response doIntercept(Chain chain) throws IOException { - Request request = chain.request(); - Request newReq = request.newBuilder() - .addHeader("accessKeyId", accessKeyId) - .addHeader("accessKeySecret", accessKeySecret) - .build(); - return chain.proceed(newReq); - } + @Override + public Response doIntercept(Chain chain) throws IOException { + Request request = chain.request(); + Request newReq = request.newBuilder() + .addHeader("accessKeyId", accessKeyId) + .addHeader("accessKeySecret", accessKeySecret) + .build(); + Response response = chain.proceed(newReq); + return response.newBuilder().addHeader("accessKeyId", accessKeyId) + .addHeader("accessKeySecret", accessKeySecret).build(); + } } ``` @@ -371,14 +359,15 @@ public class SignInterceptor extends BasePathMatchInterceptor { ```java @RetrofitClient(baseUrl = "${test.baseUrl}") -@Sign(accessKeyId = "${test.accessKeyId}", accessKeySecret = "${test.accessKeySecret}", exclude = {"/api/test/person"}) -public interface HttpApi { +@Sign(accessKeyId = "${test.accessKeyId}", accessKeySecret = "${test.accessKeySecret}", include = "/api/user/getAll") +public interface InterceptorUserService { - @GET("person") - Result getPerson(@Query("id") Long id); + /** + * 查询所有用户信息 + */ + @GET("getAll") + Response> getAll(); - @POST("savePerson") - Result savePerson(@Body Person person); } ``` @@ -400,6 +389,8 @@ retrofit: log-level: info # 全局日志打印策略 log-strategy: basic + # 是否聚合打印请求日志 + aggregate: true ``` 四种日志打印策略含义如下: @@ -417,17 +408,6 @@ retrofit: 如果需要修改日志打印行为,可以继承`LoggingInterceptor`,并将其配置成`Spring bean`。 -#### 聚合日志打印 - -如果需要将同一个请求的日志聚合在一起打印,可配置`AggregateLoggingInterceptor`。 - -```java -@Bean -public LoggingInterceptor loggingInterceptor(RetrofitProperties retrofitProperties){ - return new AggregateLoggingInterceptor(retrofitProperties.getGlobalLog()); -} -``` - ### 请求重试 组件支持支持全局重试和声明式重试。 @@ -541,31 +521,29 @@ retrofit: 熔断配置管理: -1. 实现`CircuitBreakerConfigRegistrar`接口,注册`CircuitBreakerConfig`。 - - ```java - @Component - public class CustomCircuitBreakerConfigRegistrar implements CircuitBreakerConfigRegistrar { - @Override - public void register(CircuitBreakerConfigRegistry registry) { - - // 替换默认的CircuitBreakerConfig - registry.register(Constants.DEFAULT_CIRCUIT_BREAKER_CONFIG, CircuitBreakerConfig.ofDefaults()); - - // 注册其它的CircuitBreakerConfig - registry.register("testCircuitBreakerConfig", CircuitBreakerConfig.custom() - .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.TIME_BASED) - .failureRateThreshold(20) - .minimumNumberOfCalls(5) - .permittedNumberOfCallsInHalfOpenState(5) - .build()); - } +实现`CircuitBreakerConfigRegistrar`接口,注册`CircuitBreakerConfig`。 + +```java +@Component +public class CustomCircuitBreakerConfigRegistrar implements CircuitBreakerConfigRegistrar { + @Override + public void register(CircuitBreakerConfigRegistry registry) { + + // 替换默认的CircuitBreakerConfig + registry.register(Constants.DEFAULT_CIRCUIT_BREAKER_CONFIG, CircuitBreakerConfig.ofDefaults()); + + // 注册其它的CircuitBreakerConfig + registry.register("testCircuitBreakerConfig", CircuitBreakerConfig.custom() + .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.TIME_BASED) + .failureRateThreshold(20) + .minimumNumberOfCalls(5) + .permittedNumberOfCallsInHalfOpenState(5) + .build()); } - ``` +} + ``` -2. 通过`circuitBreakerConfigName`指定`CircuitBreakerConfig`。包括`retrofit.degrade.global-resilience4j-degrade.circuit-breaker-config-name`或者`@Resilience4jDegrade.circuitBreakerConfigName` - - +通过`circuitBreakerConfigName`指定`CircuitBreakerConfig`。包括`retrofit.degrade.global-resilience4j-degrade.circuit-breaker-config-name`或者`@Resilience4jDegrade.circuitBreakerConfigName` #### 扩展熔断降级 @@ -581,7 +559,6 @@ retrofit: `fallbackFactory`相对于`fallback`,主要差别在于能够感知每次熔断的异常原因(cause),参考示例如下: ```java - @Slf4j @Service public class HttpDegradeFallback implements HttpDegradeApi { @@ -660,9 +637,15 @@ public class SpringCloudServiceInstanceChooser implements ServiceInstanceChooser #### 指定`serviceId`和`path` ```java +@RetrofitClient(serviceId = "user", path = "/api/user") +public interface ChooserOkHttpUserService { -@RetrofitClient(serviceId = "${jy-helicarrier-api.serviceId}", path = "/m/count") -public interface ApiCountService {} + /** + * 根据id查询用户信息 + */ + @GET("getUser") + User getUser(@Query("id") Long id); +} ``` ## 全局拦截器 @@ -673,19 +656,12 @@ public interface ApiCountService {} ```java @Component -public class SourceGlobalInterceptor implements GlobalInterceptor { - - @Autowired - private TestService testService; - +public class MyGlobalInterceptor implements GlobalInterceptor { @Override public Response intercept(Chain chain) throws IOException { - Request request = chain.request(); - Request newReq = request.newBuilder() - .addHeader("source", "test") - .build(); - testService.test(); - return chain.proceed(newReq); + Response response = chain.proceed(chain.request()); + // response的Header加上global + return response.newBuilder().header("global", "true").build(); } } ``` @@ -719,39 +695,6 @@ public class SourceGlobalInterceptor implements GlobalInterceptor { - `Single`:`Rxjava`响应式返回类型(支持`Rxjava2/Rxjava3`) - `Completable`:`Rxjava`响应式返回类型,`HTTP`请求没有响应体(支持`Rxjava2/Rxjava3`) -```java -@RetrofitClient(baseUrl = "${test.baseUrl}") -public interface HttpApi { - - @POST("getString") - String getString(@Body Person person); - - @GET("person") - Result getPerson(@Query("id") Long id); - - @GET("person") - CompletableFuture> getPersonCompletableFuture(@Query("id") Long id); - - @POST("savePerson") - Void savePersonVoid(@Body Person person); - - @GET("person") - Response> getPersonResponse(@Query("id") Long id); - - @GET("person") - Call> getPersonCall(@Query("id") Long id); - - @GET("person") - Mono> monoPerson(@Query("id") Long id); - - @GET("person") - Single> singlePerson(@Query("id") Long id); - - @GET("ping") - Completable ping(); -} - -``` 可以通过继承`CallAdapter.Factory`扩展`CallAdapter`。 @@ -767,7 +710,6 @@ retrofit: > 建议:将`CallAdapter.Factory`配置成`Spring Bean` - ### 数据转码器 `Retrofit`使用`Converter`将`@Body`注解的对象转换成`Request Body`,将`Response Body`转换成一个`Java`对象,可以选用以下几种`Converter`: @@ -875,7 +817,7 @@ public interface DownloadApi { #### `HTTP`下载使用 ```java -@SpringBootTest(classes = RetrofitTestApplication.class) +@SpringBootTest(classes = {RetrofitBootApplication.class}) @RunWith(SpringRunner.class) public class DownloadTest { @Autowired diff --git a/README_EN.md b/README_EN.md index 875ced0..5d16d4e 100644 --- a/README_EN.md +++ b/README_EN.md @@ -41,7 +41,7 @@ com.github.lianjiatech retrofit-spring-boot-starter - 3.0.2 + 3.0.3 ``` @@ -51,10 +51,13 @@ ```java @RetrofitClient(baseUrl = "${test.baseUrl}") -public interface HttpApi { +public interface UserService { - @GET("person") - Result getPerson(@Query("id") Long id); + /** + * 根据id查询用户姓名 + */ + @POST("getName") + String getName(@Query("id") Long id); } ``` @@ -68,14 +71,14 @@ public interface HttpApi { ```java @Service -public class TestService { +public class BusinessService { - @Autowired - private HttpApi httpApi; + @Autowired + private UserService userService; - public void test() { - // Use `httpApi` to initiate HTTP requests - } + public void doBusiness() { + // call userService + } } ``` @@ -113,6 +116,7 @@ retrofit: enable: true log-level: info log-strategy: basic + aggregate: true global-retry: enable: false @@ -154,51 +158,38 @@ If you only need to modify the timeout time of `OkHttpClient`, you can modify it If you need to modify other configuration of `OkHttpClient`, you can do it by customizing `OkHttpClient`, the steps are as follows: -1. Implement the `SourceOkHttpClientRegistrar` interface and call the `SourceOkHttpClientRegistry#register()` method to register the `OkHttpClient`. +Implement the `SourceOkHttpClientRegistrar` interface and call the `SourceOkHttpClientRegistry#register()` method to register the `OkHttpClient`. - ```java - @Slf4j - @Component - public class CustomSourceOkHttpClientRegistrar implements SourceOkHttpClientRegistrar { - - @Override - public void register(SourceOkHttpClientRegistry registry) { - - // replace default SourceOkHttpClient. Can be used to modify global `Okhttp Client` settings - 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()); - - // add testSourceOkHttpClient - registry.register("testSourceOkHttpClient", new OkHttpClient.Builder() - .connectTimeout(Duration.ofSeconds(3)) - .writeTimeout(Duration.ofSeconds(3)) - .readTimeout(Duration.ofSeconds(3)) - .addInterceptor(chain -> { - log.info("============use testSourceOkHttpClient============="); - return chain.proceed(chain.request()); - }) - .build()); - } +```java +@Component +public class CustomOkHttpClientRegistrar implements SourceOkHttpClientRegistrar { + + @Override + public void register(SourceOkHttpClientRegistry registry) { + // 注册customOkHttpClient,超时时间设置为1s + registry.register("customOkHttpClient", new OkHttpClient.Builder() + .connectTimeout(Duration.ofSeconds(1)) + .writeTimeout(Duration.ofSeconds(1)) + .readTimeout(Duration.ofSeconds(1)) + .addInterceptor(chain -> chain.proceed(chain.request())) + .build()); } - ``` +} +``` 2. Specify the `OkHttpClient` to be used by the current interface through `@RetrofitClient.sourceOkHttpClient`. - ```java - @RetrofitClient(baseUrl = "${test.baseUrl}", sourceOkHttpClient = "testSourceOkHttpClient") - public interface CustomOkHttpTestApi { - - @GET("person") - Result getPerson(@Query("id") Long id); - } - ``` +```java +@RetrofitClient(baseUrl = "${test.baseUrl}", sourceOkHttpClient = "customOkHttpClient") +public interface CustomOkHttpUserService { + + /** + * 根据id查询用户信息 + */ + @GET("getUser") + User getUser(@Query("id") Long id); +} +``` > Note: The component will not use the specified `OkHttpClient` directly, but will create a new one based on that `OkHttpClient`. @@ -219,21 +210,13 @@ The following is an example of "splicing timestamp behind the specified request ```java @Component -public class TimeStampInterceptor extends BasePathMatchInterceptor { - - @Override - public Response doIntercept(Chain chain) throws IOException { - Request request = chain.request(); - HttpUrl url = request.url(); - long timestamp = System.currentTimeMillis(); - HttpUrl newUrl = url.newBuilder() - .addQueryParameter("timestamp", String.valueOf(timestamp)) - .build(); - Request newRequest = request.newBuilder() - .url(newUrl) - .build(); - return chain.proceed(newRequest); - } +public class PathMatchInterceptor extends BasePathMatchInterceptor { + @Override + protected Response doIntercept(Chain chain) throws IOException { + Response response = chain.proceed(chain.request()); + // response的Header加上path.match + return response.newBuilder().header("path.match", "true").build(); + } } ``` @@ -243,12 +226,8 @@ This feature can be turned off by `retrofit.auto-set-prototype-scope-for-path-ma ```java @Component @Scope("prototype") -public class TimeStampInterceptor extends BasePathMatchInterceptor { +public class PathMatchInterceptor extends BasePathMatchInterceptor { - @Override - public Response doIntercept(Chain chain) throws IOException { - // ... - } } ``` @@ -256,15 +235,22 @@ public class TimeStampInterceptor extends BasePathMatchInterceptor { ```java @RetrofitClient(baseUrl = "${test.baseUrl}") -@Intercept(handler = TimeStampInterceptor.class, include = {"/api/**"}, exclude = "/api/test/savePerson") -@Intercept(handler = TimeStamp2Interceptor.class) // Need more than one, just add it directly -public interface HttpApi { +@Intercept(handler = PathMatchInterceptor.class, include = {"/api/user/**"}, exclude = "/api/user/getUser") +// @Intercept() 如果需要使用多个路径匹配拦截器,继续添加@Intercept即可 +public interface InterceptorUserService { - @GET("person") - Result getPerson(@Query("id") Long id); + /** + * 根据id查询用户姓名 + */ + @POST("getName") + Response getName(@Query("id") Long id); + + /** + * 根据id查询用户信息 + */ + @GET("getUser") + Response getUser(@Query("id") Long id); - @POST("savePerson") - Result savePerson(@Body Person person); } ``` @@ -305,29 +291,24 @@ The interceptor specified in the `@Sign` annotation is `SignInterceptor`. ```java @Component +@Setter public class SignInterceptor extends BasePathMatchInterceptor { - private String accessKeyId; - - private String accessKeySecret; + private String accessKeyId; - public void setAccessKeyId(String accessKeyId) { - this.accessKeyId = accessKeyId; - } - - public void setAccessKeySecret(String accessKeySecret) { - this.accessKeySecret = accessKeySecret; - } + private String accessKeySecret; - @Override - public Response doIntercept(Chain chain) throws IOException { - Request request = chain.request(); - Request newReq = request.newBuilder() - .addHeader("accessKeyId", accessKeyId) - .addHeader("accessKeySecret", accessKeySecret) - .build(); - return chain.proceed(newReq); - } + @Override + public Response doIntercept(Chain chain) throws IOException { + Request request = chain.request(); + Request newReq = request.newBuilder() + .addHeader("accessKeyId", accessKeyId) + .addHeader("accessKeySecret", accessKeySecret) + .build(); + Response response = chain.proceed(newReq); + return response.newBuilder().addHeader("accessKeyId", accessKeyId) + .addHeader("accessKeySecret", accessKeySecret).build(); + } } ``` @@ -339,14 +320,15 @@ The `accessKeyId` and `accessKeySecret` field values of the interceptor will be ```java @RetrofitClient(baseUrl = "${test.baseUrl}") -@Sign(accessKeyId = "${test.accessKeyId}", accessKeySecret = "${test.accessKeySecret}", exclude = {"/api/test/person"}) -public interface HttpApi { +@Sign(accessKeyId = "${test.accessKeyId}", accessKeySecret = "${test.accessKeySecret}", include = "/api/user/getAll") +public interface InterceptorUserService { - @GET("person") - Result getPerson(@Query("id") Long id); + /** + * 查询所有用户信息 + */ + @GET("getAll") + Response> getAll(); - @POST("savePerson") - Result savePerson(@Body Person person); } ``` @@ -364,6 +346,7 @@ retrofit: enable: true log-level: info log-strategy: basic + aggregate: true ``` The meanings of the four log printing strategies are as follows: @@ -381,17 +364,6 @@ If only some requests are required to print the log, you can use the `@Logging` If you need to modify the log printing behavior, you can inherit `LoggingInterceptor` and configure it as a `Spring bean`. -#### Aggregate log printing - -If the logs of the same request need to be aggregated and printed together, `AggregateLoggingInterceptor` can be configured. - -```java -@Bean -public LoggingInterceptor loggingInterceptor(RetrofitProperties retrofitProperties){ - return new AggregateLoggingInterceptor(retrofitProperties.getGlobalLog()); -} -``` - ### Request Retry Component support supports global retry and declarative retry. @@ -491,27 +463,27 @@ retrofit: Circuit breaker configuration management: -1. Implement the `CircuitBreakerConfigRegistrar` interface and register the `CircuitBreakerConfig`. - - ```java - @Component - public class CustomCircuitBreakerConfigRegistrar implements CircuitBreakerConfigRegistrar { - @Override - public void register(CircuitBreakerConfigRegistry registry) { - - registry.register(Constants.DEFAULT_CIRCUIT_BREAKER_CONFIG, CircuitBreakerConfig.ofDefaults()); - - registry.register("testCircuitBreakerConfig", CircuitBreakerConfig.custom() - .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.TIME_BASED) - .failureRateThreshold(20) - .minimumNumberOfCalls(5) - .permittedNumberOfCallsInHalfOpenState(5) - .build()); - } +Implement the `CircuitBreakerConfigRegistrar` interface and register the `CircuitBreakerConfig`. + +```java +@Component +public class CustomCircuitBreakerConfigRegistrar implements CircuitBreakerConfigRegistrar { + @Override + public void register(CircuitBreakerConfigRegistry registry) { + + registry.register(Constants.DEFAULT_CIRCUIT_BREAKER_CONFIG, CircuitBreakerConfig.ofDefaults()); + + registry.register("testCircuitBreakerConfig", CircuitBreakerConfig.custom() + .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.TIME_BASED) + .failureRateThreshold(20) + .minimumNumberOfCalls(5) + .permittedNumberOfCallsInHalfOpenState(5) + .build()); } - ``` +} + ``` -2. Specify the `CircuitBreakerConfig` via `circuitBreakerConfigName`. Include `retrofit.degrade.global-resilience4j-degrade.circuit-breaker-config-name` or `@Resilience4jDegrade.circuitBreakerConfigName` +Specify the `CircuitBreakerConfig` via `circuitBreakerConfigName`. Include `retrofit.degrade.global-resilience4j-degrade.circuit-breaker-config-name` or `@Resilience4jDegrade.circuitBreakerConfigName` #### Extended circuit breaker degrade @@ -528,7 +500,6 @@ Implementation class, the generic parameter type is the current interface type. The main difference between `fallbackFactory` and `fallback` is that it can perceive the abnormal cause (cause) of each fuse. The reference example is as follows: ```java - @Slf4j @Service public class HttpDegradeFallback implements HttpDegradeApi { @@ -608,9 +579,15 @@ public class SpringCloudServiceInstanceChooser implements ServiceInstanceChooser #### Specify `serviceId` and `path` ```java +@RetrofitClient(serviceId = "user", path = "/api/user") +public interface ChooserOkHttpUserService { -@RetrofitClient(serviceId = "${jy-helicarrier-api.serviceId}", path = "/m/count") -public interface ApiCountService {} + /** + * 根据id查询用户信息 + */ + @GET("getUser") + User getUser(@Query("id") Long id); +} ``` ## Global Interceptor @@ -621,19 +598,12 @@ If we need to perform unified interception processing for `HTTP` requests of the ```java @Component -public class SourceGlobalInterceptor implements GlobalInterceptor { - - @Autowired - private TestService testService; - +public class MyGlobalInterceptor implements GlobalInterceptor { @Override public Response intercept(Chain chain) throws IOException { - Request request = chain.request(); - Request newReq = request.newBuilder() - .addHeader("source", "test") - .build(); - testService.test(); - return chain.proceed(newReq); + Response response = chain.proceed(chain.request()); + // response的Header加上global + return response.newBuilder().header("global", "true").build(); } } ``` @@ -667,39 +637,6 @@ Implement the `NetworkInterceptor` interface and configure it as a `spring Bean` - `Single`: `Rxjava` reactive return type (supports `Rxjava2/Rxjava3`) - `Completable`: `Rxjava` reactive return type, `HTTP` request has no response body (supports `Rxjava2/Rxjava3`) -```java -@RetrofitClient(baseUrl = "${test.baseUrl}") -public interface HttpApi { - - @POST("getString") - String getString(@Body Person person); - - @GET("person") - Result getPerson(@Query("id") Long id); - - @GET("person") - CompletableFuture> getPersonCompletableFuture(@Query("id") Long id); - - @POST("savePerson") - Void savePersonVoid(@Body Person person); - - @GET("person") - Response> getPersonResponse(@Query("id") Long id); - - @GET("person") - Call> getPersonCall(@Query("id") Long id); - - @GET("person") - Mono> monoPerson(@Query("id") Long id); - - @GET("person") - Single> singlePerson(@Query("id") Long id); - - @GET("ping") - Completable ping(); -} - -``` `CallAdapter` can be extended by extending `CallAdapter.Factory`. diff --git a/pom.xml b/pom.xml index 49377a9..a10c697 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.github.lianjiatech retrofit-spring-boot-starter - 3.0.2 + 3.0.3 retrofit-spring-boot-starter retrofit-spring-boot-starter @@ -39,7 +39,7 @@ 2.9.0 1.3.2 - 3.0.0 + 3.1.6 3.14.9 1.6.3 1.18.24 @@ -229,6 +229,31 @@ + + org.jacoco + jacoco-maven-plugin + 0.8.11 + + + **/exception/* + **/config/* + + + + + default-prepare-agent + + prepare-agent + + + + default-report + + report + + + + org.apache.maven.plugins 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 f444725..b664c7c 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 @@ -67,7 +67,7 @@ public class RetrofitProperties { JacksonConverterFactory.class}; /** - * 全局调用适配器工厂,转换器实例优先从Spring容器获取,如果没有获取到,则反射创建。 + * 全局调用适配器工厂,适配器实例优先从Spring容器获取,如果没有获取到,则反射创建。 *

* global call adapter factories, The callAdapter 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/ServiceInstanceChooser.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/ServiceInstanceChooser.java index 31b0424..7c34c8a 100644 --- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/ServiceInstanceChooser.java +++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/ServiceInstanceChooser.java @@ -22,7 +22,8 @@ class NoValidServiceInstanceChooser implements ServiceInstanceChooser { @Override public URI choose(String serviceId) { - throw new ServiceInstanceChooseException("No valid service instance selector, Please configure it!"); + throw new ServiceInstanceChooseException( + "No valid service instance selector, Please configure it! serviceId=" + serviceId); } } diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/DegradeProxy.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/DegradeProxy.java index 9d130f1..17635ef 100644 --- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/DegradeProxy.java +++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/DegradeProxy.java @@ -4,6 +4,8 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import com.github.lianjiatech.retrofit.spring.boot.util.AppContextUtils; +import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationContext; import org.springframework.core.annotation.AnnotatedElementUtils; @@ -13,6 +15,7 @@ * @author 陈添明 * @since 2022/4/30 2:27 下午 */ +@Slf4j public class DegradeProxy implements InvocationHandler { private final Object source; @@ -28,12 +31,13 @@ public static T create(Object source, Class retrofitInterface, Applicatio Class fallbackClass = retrofitClient.fallback(); Object fallback = null; if (!void.class.isAssignableFrom(fallbackClass)) { - fallback = applicationContext.getBean(fallbackClass); + fallback = AppContextUtils.getBeanOrNew(applicationContext, fallbackClass); } Class fallbackFactoryClass = retrofitClient.fallbackFactory(); FallbackFactory fallbackFactory = null; if (!void.class.isAssignableFrom(fallbackFactoryClass)) { - fallbackFactory = (FallbackFactory)applicationContext.getBean(fallbackFactoryClass); + fallbackFactory = + (FallbackFactory)AppContextUtils.getBeanOrNew(applicationContext, fallbackFactoryClass); } DegradeProxy degradeProxy = new DegradeProxy(source, fallback, fallbackFactory); return (T)Proxy.newProxyInstance(retrofitInterface.getClassLoader(), @@ -56,6 +60,7 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl if (cause instanceof RetrofitBlockException) { Object fallbackObject = getFallbackObject(cause); if (fallbackObject != null) { + log.error("call fallback! method={}, args={}", method, args, cause); return method.invoke(fallbackObject, args); } } diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/resilience4j/Resilience4jDegrade.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/resilience4j/Resilience4jDegrade.java index e09d8f4..62c092f 100644 --- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/resilience4j/Resilience4jDegrade.java +++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/resilience4j/Resilience4jDegrade.java @@ -30,5 +30,5 @@ * * @return circuitBreakerConfigName */ - String circuitBreakerConfigName() default Constants.CIRCUIT_BREAKER_CLASS_NAME; + String circuitBreakerConfigName() default Constants.DEFAULT_CIRCUIT_BREAKER_CONFIG; } \ No newline at end of file diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/AggregateLoggingInterceptor.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/AggregateLoggingInterceptor.java deleted file mode 100644 index 8834c9a..0000000 --- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/AggregateLoggingInterceptor.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.log; - -import java.io.IOException; - -import okhttp3.Response; -import okhttp3.logging.HttpLoggingInterceptor; - -/** - * 同一个请求的日志聚合在一起打印。 The logs of the same request are aggregated and printed together. - * @author 陈添明 - * @since 2022/5/31 10:49 上午 - */ -public class AggregateLoggingInterceptor extends LoggingInterceptor { - - public AggregateLoggingInterceptor(GlobalLogProperty globalLogProperty) { - super(globalLogProperty); - } - - @Override - public Response intercept(Chain chain) throws IOException { - Logging logging = findLogging(chain); - if (!needLog(logging)) { - return chain.proceed(chain.request()); - } - LogLevel logLevel = logging == null ? globalLogProperty.getLogLevel() : logging.logLevel(); - LogStrategy logStrategy = logging == null ? globalLogProperty.getLogStrategy() : logging.logStrategy(); - BufferingLogger bufferingLogger = new BufferingLogger(matchLogger(logLevel)); - HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(bufferingLogger) - .setLevel(HttpLoggingInterceptor.Level.valueOf(logStrategy.name())); - Response response = httpLoggingInterceptor.intercept(chain); - bufferingLogger.flush(); - return response; - } - - private static class BufferingLogger implements HttpLoggingInterceptor.Logger { - - private StringBuilder buffer = new StringBuilder(System.lineSeparator()); - - private final HttpLoggingInterceptor.Logger delegate; - - public BufferingLogger(HttpLoggingInterceptor.Logger delegate) { - this.delegate = delegate; - } - - @Override - public void log(String message) { - buffer.append(message).append(System.lineSeparator()); - } - - public void flush() { - delegate.log(buffer.toString()); - buffer = new StringBuilder(System.lineSeparator()); - } - } -} diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/GlobalLogProperty.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/GlobalLogProperty.java index 8460a87..7c0cde5 100644 --- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/GlobalLogProperty.java +++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/GlobalLogProperty.java @@ -10,7 +10,7 @@ public class GlobalLogProperty { /** - * 是否启用 + * 是否启用日志 */ private boolean enable = true; @@ -25,4 +25,9 @@ public class GlobalLogProperty { * Log printing strategy, see {@link LogStrategy} for supported log printing strategies */ private LogStrategy logStrategy = LogStrategy.BASIC; + + /** + * 是否聚合打印请求日志 + */ + private boolean aggregate = true; } diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/Logging.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/Logging.java index 12a12bf..6f85f86 100644 --- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/Logging.java +++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/Logging.java @@ -43,4 +43,10 @@ * @return 日志打印策略 */ LogStrategy logStrategy() default LogStrategy.BASIC; + + /** + * 是否聚合打印请求日志 + * @return 是否聚合打印请求日志 + */ + boolean aggregate() default true; } diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/LoggingInterceptor.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/LoggingInterceptor.java index 52b1f66..05e431a 100644 --- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/LoggingInterceptor.java +++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/LoggingInterceptor.java @@ -33,9 +33,16 @@ public Response intercept(Chain chain) throws IOException { } LogLevel logLevel = logging == null ? globalLogProperty.getLogLevel() : logging.logLevel(); LogStrategy logStrategy = logging == null ? globalLogProperty.getLogStrategy() : logging.logStrategy(); - HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(matchLogger(logLevel)) + boolean aggregate = logging == null ? globalLogProperty.isAggregate() : logging.aggregate(); + HttpLoggingInterceptor.Logger matchLogger = matchLogger(logLevel); + HttpLoggingInterceptor.Logger logger = aggregate ? new BufferingLogger(matchLogger) : matchLogger; + HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(logger) .setLevel(HttpLoggingInterceptor.Level.valueOf(logStrategy.name())); - return httpLoggingInterceptor.intercept(chain); + Response response = httpLoggingInterceptor.intercept(chain); + if (aggregate) { + ((BufferingLogger)logger).flush(); + } + return response; } protected Logging findLogging(Chain chain) { @@ -68,4 +75,25 @@ protected HttpLoggingInterceptor.Logger matchLogger(LogLevel level) { } throw new UnsupportedOperationException("We don't support this log level currently."); } + + private static class BufferingLogger implements HttpLoggingInterceptor.Logger { + + private StringBuilder buffer = new StringBuilder(System.lineSeparator()); + + private final HttpLoggingInterceptor.Logger delegate; + + public BufferingLogger(HttpLoggingInterceptor.Logger delegate) { + this.delegate = delegate; + } + + @Override + public void log(String message) { + buffer.append(message).append(System.lineSeparator()); + } + + public void flush() { + delegate.log(buffer.toString()); + buffer = new StringBuilder(System.lineSeparator()); + } + } } diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/retry/RetryInterceptor.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/retry/RetryInterceptor.java index 156ecf3..ce90b72 100644 --- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/retry/RetryInterceptor.java +++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/retry/RetryInterceptor.java @@ -10,6 +10,7 @@ import com.github.lianjiatech.retrofit.spring.boot.exception.RetryFailedException; import com.github.lianjiatech.retrofit.spring.boot.util.AnnotationExtendUtils; +import com.github.lianjiatech.retrofit.spring.boot.util.RetrofitUtils; import lombok.extern.slf4j.Slf4j; import okhttp3.Interceptor; import okhttp3.Request; @@ -58,9 +59,9 @@ protected boolean needRetry(Retry retry) { protected Response retryIntercept(int maxRetries, int intervalMs, RetryRule[] retryRules, Chain chain) { HashSet retryRuleSet = (HashSet)Arrays.stream(retryRules).collect(Collectors.toSet()); RetryStrategy retryStrategy = new RetryStrategy(maxRetries, intervalMs); + Request request = chain.request(); while (true) { try { - Request request = chain.request(); Response response = chain.proceed(request); // 如果响应状态码是2xx就不用重试,直接返回 response if (!retryRuleSet.contains(RetryRule.RESPONSE_STATUS_NOT_2XX) || response.isSuccessful()) { @@ -72,7 +73,8 @@ protected Response retryIntercept(int maxRetries, int intervalMs, RetryRule[] re } // 执行重试 retryStrategy.retry(); - log.debug("The response fails, retry is performed! The response code is " + response.code()); + log.warn("The response fails, retry is performed! The request is {}, Response is {}", request, + response); response.close(); } } catch (Exception e) { @@ -81,11 +83,12 @@ protected Response retryIntercept(int maxRetries, int intervalMs, RetryRule[] re } else { if (!retryStrategy.shouldRetry()) { // 最后一次还没成功,抛出异常 - throw new RetryFailedException("Retry Failed: Total " + maxRetries - + " attempts made at interval " + intervalMs - + "ms"); + throw new RetryFailedException( + "Retry Failed: Total " + maxRetries + " attempts made at interval " + intervalMs + "ms", + e); } retryStrategy.retry(); + log.warn("The response fails, retry is performed! The request is {} ", request, e); } } } diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/other/OtherPathApi.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/other/OtherPathApi.java deleted file mode 100644 index 305a0b0..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/other/OtherPathApi.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.other; - -import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; -import com.github.lianjiatech.retrofit.spring.boot.degrade.sentinel.SentinelDegrade; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; - -import retrofit2.http.GET; -import retrofit2.http.Query; - -/** - * @author 陈添明 - * @since 2022/1/21 4:19 下午 - */ -@RetrofitClient(baseUrl = "${test.baseUrl}") -@SentinelDegrade(count = 100) -public interface OtherPathApi { - - /** - * 其他任意Java类型
- * 将响应体内容适配成一个对应的Java类型对象返回,如果http状态码不是2xx,直接抛错!
- * - * @param id id - * @return 其他任意Java类型 - */ - @GET("person") - Result getPerson(@Query("id") Long id); - -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/InterceptTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/InterceptTest.java deleted file mode 100644 index a1a3503..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/InterceptTest.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test; - -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.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; -import com.github.lianjiatech.retrofit.spring.boot.test.http.InterceptApi; - -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; - -/** - * @author 陈添明 - * @since 2022/1/21 4:20 下午 - */ -@SpringBootTest(classes = RetrofitTestApplication.class) -@RunWith(SpringRunner.class) -public class InterceptTest { - - @Autowired - private InterceptApi interceptApi; - - private static final ObjectMapper objectMapper = - new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .setSerializationInclusion(JsonInclude.Include.NON_NULL); - - private MockWebServer server; - - @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 IOException { - // 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); - - Result person = interceptApi.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/InvalidRespErrorDecoder.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/InvalidRespErrorDecoder.java deleted file mode 100644 index d9cea78..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/InvalidRespErrorDecoder.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test; - -import com.github.lianjiatech.retrofit.spring.boot.core.ErrorDecoder; -import okhttp3.Request; -import okhttp3.Response; - -/** - * @author 陈添明 - */ -public class InvalidRespErrorDecoder implements ErrorDecoder { - - @Override - public RuntimeException invalidRespDecode(Request request, Response response) { - return null; - } -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/MySpringBootApplication.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/MySpringBootApplication.java deleted file mode 100644 index c9e82bb..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/MySpringBootApplication.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.springframework.boot.autoconfigure.SpringBootApplication; - -import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitScan; - -/** - * @author 陈添明 - * @since 2022/5/7 8:48 下午 - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Inherited -@RetrofitScan("com.github.lianjiatech.retrofit.spring.boot") -@SpringBootApplication -public @interface MySpringBootApplication {} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/OtherPathTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/OtherPathTest.java deleted file mode 100644 index d297ecd..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/OtherPathTest.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test; - -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.other.OtherPathApi; -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 OtherPathTest { - - @Autowired - private OtherPathApi otherPathApi; - - 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 = otherPathApi.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/RetrofitConvertFactoriesTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitConvertFactoriesTest.java deleted file mode 100644 index 503d6e0..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitConvertFactoriesTest.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test; - -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.github.lianjiatech.retrofit.spring.boot.test.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; -import com.github.lianjiatech.retrofit.spring.boot.test.http.ConvertFactoriesTestApi; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; - -/** - * @author 陈添明 - */ -@SpringBootTest(classes = RetrofitTestApplication.class) -@RunWith(SpringRunner.class) -public class RetrofitConvertFactoriesTest { - - @Autowired - private ConvertFactoriesTestApi convertFactoriesTestApi; - - private MockWebServer server; - - private static Gson gson = new GsonBuilder() - .create(); - - @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() { - - // 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(gson.toJson(mockResult)); - server.enqueue(response); - - // http check - Result person = convertFactoriesTestApi.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/RetrofitExceptionTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitExceptionTest.java deleted file mode 100644 index 630934c..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitExceptionTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import org.junit.After; -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.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; -import com.github.lianjiatech.retrofit.spring.boot.test.http.HttpApi; - -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; - -/** - * @author 陈添明 - */ -@SpringBootTest(classes = RetrofitTestApplication.class) -@RunWith(SpringRunner.class) -public class RetrofitExceptionTest { - - @Autowired - private HttpApi httpApi; - - private static final ObjectMapper objectMapper = - new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .setSerializationInclusion(JsonInclude.Include.NON_NULL); - - private MockWebServer server; - - @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(expected = Throwable.class) -// @Test - public void testHttpResponseFailure() throws IOException { - // mock - Map map = new HashMap<>(4); - map.put("errorMessage", "我就是要手动报个错"); - map.put("errorCode", 500); - - Result mockResult = new Result<>() - .setCode(0) - .setMsg("ok") - .setData(objectMapper.writeValueAsString(map)); - MockResponse response = new MockResponse() - .setResponseCode(500) - .addHeader("Content-Type", "application/json; charset=utf-8") - .addHeader("Cache-Control", "no-cache") - .setBody(objectMapper.writeValueAsString(mockResult)); - server.enqueue(response); - - Person person = new Person().setId(1L).setName("test").setAge(10); - Person error = httpApi.error(person); - System.out.println(error); - } - - @Test(expected = Throwable.class) - public void testIOException() { - Person person = new Person().setId(1L).setName("test").setAge(10); - Person error = httpApi.error(person); - } - -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitStarterTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitStarterTest.java deleted file mode 100644 index 7e074f4..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitStarterTest.java +++ /dev/null @@ -1,447 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.stream.IntStream; - -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.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; -import com.github.lianjiatech.retrofit.spring.boot.test.http.HttpApi; -import com.github.lianjiatech.retrofit.spring.boot.test.http.HttpApi2; -import com.github.lianjiatech.retrofit.spring.boot.test.http.HttpApi3; - -import lombok.extern.slf4j.Slf4j; -import okhttp3.Request; -import okhttp3.ResponseBody; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; - -/** - * @author 陈添明 - */ -@SpringBootTest(classes = RetrofitTestApplication.class) -@RunWith(SpringRunner.class) -@Slf4j -public class RetrofitStarterTest { - - @Autowired - private HttpApi httpApi; - - @Autowired - private HttpApi2 httpApi2; - - @Autowired - private HttpApi3 httpApi3; - - private static final ObjectMapper objectMapper = - new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .setSerializationInclusion(JsonInclude.Include.NON_NULL); - - private MockWebServer server; - - @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 testGetPersonBody() throws Exception { - - // 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); - - Person person = new Person(); - person.setId(100L) - .setAge(10) - .setName("xx"); - Result personBody = httpApi2.getPersonBody(person); - System.out.println(personBody); - } - - @Test - public void testAggregateLoggingInterceptor() { - IntStream.range(1, 1000) - .parallel() - .forEach(i -> { - // mock - Person mockPerson = new Person().setId(1L) - .setName("test") - .setAge(10); - Result mockResult = new Result<>() - .setCode(0) - .setMsg("ok") - .setData(mockPerson); - MockResponse response = null; - try { - response = new MockResponse() - .setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8") - .addHeader("Cache-Control", "no-cache") - .setBody(objectMapper.writeValueAsString(mockResult)); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - server.enqueue(response); - - Person person = new Person(); - person.setId(100L) - .setAge(10) - .setName("xx"); - Result personBody = httpApi2.getPersonBody(person); - System.out.println(personBody); - }); - } - - @Test - public void testRetrofitConfigRef() throws IOException { - - // 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); - server.enqueue(response); - - // http check - Result person = httpApi.getPerson(1L); - Person data = person.getData(); - Assert.assertNotNull(data); - Assert.assertEquals("test", data.getName()); - Assert.assertEquals(10, data.getAge().intValue()); - Result person2 = httpApi2.getPerson(1L); - Person data2 = person2.getData(); - Assert.assertNotNull(data2); - Assert.assertEquals("test", data2.getName()); - Assert.assertEquals(10, data2.getAge().intValue()); - } - - @Test - public void testRetCall() throws InterruptedException, IOException { - // mock - Person mockPerson = new Person().setId(2L) - .setName("test") - .setAge(10); - Result mockResult = new Result<>() - .setCode(0) - .setMsg("ok") - .setData(mockPerson); - MockResponse response = new MockResponse() - .setResponseCode(500) - .addHeader("Content-Type", "application/json; charset=utf-8") - .addHeader("Cache-Control", "no-cache") - .setBody(objectMapper.writeValueAsString(mockResult)); - server.enqueue(response); - - Call> resultCall = httpApi.getPersonCall(2L); - CountDownLatch countDownLatch = new CountDownLatch(1); - // 异步回调处理 - resultCall.enqueue(new Callback>() { - @Override - public void onResponse(Call> call, Response> response) { - try { - if (response.isSuccessful()) { - Result personResult = response.body(); - Assert.assertEquals(0, personResult.getCode()); - Assert.assertNotNull(personResult.getData()); - Person data = personResult.getData(); - Assert.assertEquals(10, data.getAge().longValue()); - Assert.assertEquals("test", data.getName()); - } else { - ResponseBody errorBody = response.errorBody(); - System.out.println(errorBody); - } - - } finally { - countDownLatch.countDown(); - } - } - - @Override - public void onFailure(Call> call, Throwable t) { - Request request = call.request(); - log.error("请求执行失败! request = {}", request, t); - countDownLatch.countDown(); - } - }); - countDownLatch.await(); - } - - @Test - public void testFuture() throws ExecutionException, InterruptedException, IOException { - - // 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); - - CompletableFuture> resultCompletableFuture = httpApi.getPersonCompletableFuture(1L); - // CompletableFuture处理 - Result personResult = resultCompletableFuture.get(); - Assert.assertEquals(0, personResult.getCode()); - Assert.assertNotNull(personResult.getData()); - Person data = personResult.getData(); - Assert.assertEquals(10, data.getAge().longValue()); - Assert.assertEquals("test", data.getName()); - } - - @Test - public void testResponse() throws IOException { - // 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); - - Response> resultResponse = httpApi.getPersonResponse(1L); - Assert.assertTrue(resultResponse.isSuccessful()); - Result personResult = resultResponse.body(); - // 直接取值 - Assert.assertEquals(0, personResult.getCode()); - Assert.assertNotNull(personResult.getData()); - Person data = personResult.getData(); - Assert.assertEquals(10, data.getAge().longValue()); - Assert.assertEquals("test", data.getName()); - } - - @Test - public void testApi2() throws IOException { - // 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); - - Result person = httpApi2.getPerson(1L); - Person data = person.getData(); - Assert.assertNotNull(data); - Assert.assertEquals("test", data.getName()); - Assert.assertEquals(10, data.getAge().intValue()); - } - - @Test - public void savePerson() throws IOException { - - // mock - Result mockResult = new Result<>() - .setCode(0) - .setMsg("ok"); - - 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); - - Person person = new Person().setId(1L).setName("test").setAge(10); - Result voidResult = httpApi.savePerson(person); - int code = voidResult.getCode(); - Assert.assertEquals(code, 0); - } - - @Test - public void savePersonVoid() throws IOException { - // mock - - Result mockResult = new Result<>() - .setCode(0) - .setMsg("ok"); - - 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); - - Person person = new Person().setId(1L).setName("test").setAge(10); - httpApi.savePersonVoid(person); - } - - @Test - public void testNoBaseUrl() throws IOException { - // 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); - - String url = "http://localhost:8080/api/test/person"; - Result person = httpApi3.getPerson(url, 1L); - Person data = person.getData(); - Assert.assertNotNull(data); - Assert.assertEquals("test", data.getName()); - Assert.assertEquals(10, data.getAge().intValue()); - - } - - @Test - public void testMap() throws IOException { - - Map> map = new HashMap<>(4); - Map test = new HashMap<>(4); - test.put("a", "aa"); - test.put("b", "bb"); - map.put("test", test); - - MockResponse response = new MockResponse() - .setResponseCode(200) - .addHeader("Content-Type", "application/json; charset=utf-8") - .addHeader("Cache-Control", "no-cache") - .setBody(objectMapper.writeValueAsString(map)); - server.enqueue(response); - - Map> stringMapMap = httpApi2.testMap(); - System.out.println(stringMapMap); - } - - @Test - public void savePersonList() throws IOException { - - // mock - Result mockResult = new Result<>() - .setCode(0) - .setMsg("ok"); - - 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); - - Person person = new Person().setId(1L).setName("test").setAge(10); - Person person2 = new Person().setId(10L).setName("test333").setAge(100); - - List list = new ArrayList<>(); - list.add(person); - list.add(person2); - - Result voidResult = httpApi.savePersonList(list); - int code = voidResult.getCode(); - Assert.assertEquals(code, 0); - } - - @Test - public void testString() { - - MockResponse response = new MockResponse() - .setResponseCode(200) - .addHeader("Content-Type", "application/text; charset=utf-8") - .addHeader("Cache-Control", "no-cache") - .setBody("text"); - server.enqueue(response); - Person mockPerson = new Person().setId(1L) - .setName("testString") - .setAge(10); - String string = httpApi.getString(mockPerson); - System.out.println(string); - } - - @Test - public void testBoolean() { - - MockResponse response = new MockResponse() - .setResponseCode(200) - .addHeader("Content-Type", "application/text; charset=utf-8") - .addHeader("Cache-Control", "no-cache") - .setBody("false"); - server.enqueue(response); - - Person mockPerson = new Person().setId(1L) - .setName("testBoolean") - .setAge(10); - Boolean apiBoolean = httpApi.getBoolean(mockPerson); - System.out.println(apiBoolean); - } - -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitTestApplication.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitTestApplication.java deleted file mode 100644 index 43270fd..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitTestApplication.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test; - -import org.springframework.boot.SpringApplication; -import org.springframework.context.annotation.Bean; - -import com.github.lianjiatech.retrofit.spring.boot.config.RetrofitProperties; -import com.github.lianjiatech.retrofit.spring.boot.log.AggregateLoggingInterceptor; -import com.github.lianjiatech.retrofit.spring.boot.log.LoggingInterceptor; - -import lombok.extern.slf4j.Slf4j; -import retrofit2.converter.gson.GsonConverterFactory; -import retrofit2.converter.jaxb.JaxbConverterFactory; - -/** - * @author 陈添明 - */ -@MySpringBootApplication -@Slf4j -public class RetrofitTestApplication { - - public static void main(String[] args) { - SpringApplication.run(RetrofitTestApplication.class, args); - } - - @Bean - public GsonConverterFactory gsonConverterFactory() { - return GsonConverterFactory.create(); - } - - @Bean - public JaxbConverterFactory jaxbConverterFactory() { - return JaxbConverterFactory.create(); - } - - @Bean - public InvalidRespErrorDecoder invalidRespErrorDecoder() { - return new InvalidRespErrorDecoder(); - } - - @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") - @Bean - public LoggingInterceptor loggingInterceptor(RetrofitProperties retrofitProperties) { - return new AggregateLoggingInterceptor(retrofitProperties.getGlobalLog()); - } -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/custom/okhttp/CustomOkHttpTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/custom/okhttp/CustomOkHttpTest.java deleted file mode 100644 index a50c148..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/custom/okhttp/CustomOkHttpTest.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.custom.okhttp; - -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.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; - -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 com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; - -/** - * @author 陈添明 - */ -@SpringBootTest(classes = RetrofitTestApplication.class) -@RunWith(SpringRunner.class) -@ActiveProfiles("sentinel") -public class CustomOkHttpTest { - - @Autowired - private CustomOkHttpTestApi customOkHttpTestApi; - - private MockWebServer server; - - private static Gson gson = new GsonBuilder() - .create(); - - @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() { - - // 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(gson.toJson(mockResult)); - server.enqueue(response); - - // http check - Result person = customOkHttpTestApi.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/custom/okhttp/CustomOkHttpTestApi.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/custom/okhttp/CustomOkHttpTestApi.java deleted file mode 100644 index ddf6d92..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/custom/okhttp/CustomOkHttpTestApi.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.custom.okhttp; - -import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; -import com.github.lianjiatech.retrofit.spring.boot.degrade.sentinel.SentinelDegrade; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; - -import retrofit2.http.GET; -import retrofit2.http.Headers; -import retrofit2.http.Query; - -/** - * @author 陈添明 - */ -@RetrofitClient(baseUrl = "${test.baseUrl}", sourceOkHttpClient = "testSourceOkHttpClient") -@SentinelDegrade -public interface CustomOkHttpTestApi { - - @GET("person") - @Headers({ - "X-Foo: Bar", - "X-Ping: Pong" - }) - Result getPerson(@Query("id") Long id); -} 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 deleted file mode 100644 index 9edebf1..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/custom/okhttp/CustomSourceOkHttpClientRegistrar.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.custom.okhttp; - -import java.time.Duration; - -import org.springframework.stereotype.Component; - -import com.github.lianjiatech.retrofit.spring.boot.core.Constants; -import com.github.lianjiatech.retrofit.spring.boot.core.SourceOkHttpClientRegistrar; -import com.github.lianjiatech.retrofit.spring.boot.core.SourceOkHttpClientRegistry; - -import lombok.extern.slf4j.Slf4j; -import okhttp3.OkHttpClient; - -/** - * @author 陈添明 - * @since 2022/5/24 9:29 下午 - */ -@Slf4j -@Component -public class CustomSourceOkHttpClientRegistrar implements SourceOkHttpClientRegistrar { - - @Override - public void register(SourceOkHttpClientRegistry registry) { - - // 注册testSourceOkHttpClient - registry.register("testSourceOkHttpClient", new OkHttpClient.Builder() - .connectTimeout(Duration.ofSeconds(3)) - .writeTimeout(Duration.ofSeconds(3)) - .readTimeout(Duration.ofSeconds(3)) - .addInterceptor(chain -> { - log.info("============use testSourceOkHttpClient============="); - return chain.proceed(chain.request()); - }) - .build()); - } -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/decoder/ErrorDecoderTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/decoder/ErrorDecoderTest.java deleted file mode 100644 index bdb1ce9..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/decoder/ErrorDecoderTest.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.decoder; - -import java.io.IOException; - -import org.junit.After; -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 ErrorDecoderTest { - - @Autowired - private ErrorDecoderTestApi errorDecoderTestApi; - - 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(expected = Throwable.class) - 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(objectMapper.writeValueAsString(mockPerson)); - MockResponse response = new MockResponse() - .setResponseCode(500) - .addHeader("Content-Type", "application/json; charset=utf-8") - .addHeader("Cache-Control", "no-cache") - .setBody(objectMapper.writeValueAsString(mockResult)); - server.enqueue(response); - - Person person = new Person().setId(1L).setName("test").setAge(10); - Person error = errorDecoderTestApi.error(person); - System.out.println(error); - - } - -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/decoder/ErrorDecoderTestApi.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/decoder/ErrorDecoderTestApi.java deleted file mode 100644 index c33283b..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/decoder/ErrorDecoderTestApi.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.decoder; - -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 retrofit2.http.Body; -import retrofit2.http.POST; - -/** - * @author 陈添明 - */ -@Logging(logStrategy = LogStrategy.BODY) -@RetrofitClient(baseUrl = "${test.baseUrl}", errorDecoder = InvalidRespErrorDecoder.class) -public interface ErrorDecoderTestApi { - - @POST("error") - Person error(@Body Person person); -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeR4jApi.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeR4jApi.java deleted file mode 100644 index 4c924f6..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeR4jApi.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.degrade; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; - -import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; -import com.github.lianjiatech.retrofit.spring.boot.degrade.FallbackFactory; -import com.github.lianjiatech.retrofit.spring.boot.degrade.resilience4j.Resilience4jDegrade; -import com.github.lianjiatech.retrofit.spring.boot.retry.Retry; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; - -import retrofit2.http.GET; -import retrofit2.http.Query; - -/** - * @author 陈添明 - */ -@Retry(enable = false) -@RetrofitClient(baseUrl = "${test.baseUrl}", fallbackFactory = DegradeR4jApi.HttpDegradeFallbackFactory.class) -@Resilience4jDegrade(circuitBreakerConfigName = "testCircuitBreakerConfig") -public interface DegradeR4jApi { - - @GET("degrade/person1") - Result getPerson1(@Query("id") Long id); - - @Resilience4jDegrade(circuitBreakerConfigName = "testCircuitBreakerConfig") - @GET("degrade/person2") - Result getPerson2(@Query("id") Long id); - - @Service - class HttpDegradeFallbackFactory implements FallbackFactory { - Logger log = LoggerFactory.getLogger(HttpDegradeFallbackFactory.class); - - /** - * Returns an instance of the fallback appropriate for the given cause - * - * @param cause fallback cause - * @return 实现了retrofit接口的实例。an instance that implements the retrofit interface. - */ - @Override - public DegradeR4jApi create(Throwable cause) { - log.error("触发熔断了! ", cause.getMessage(), cause); - return new DegradeR4jApi() { - @Override - public Result getPerson1(Long id) { - Result fallback = new Result<>(); - fallback.setCode(-1) - .setMsg("熔断Person1") - .setData(new Person()); - return fallback; - } - - @Override - public Result getPerson2(Long id) { - Result fallback = new Result<>(); - fallback.setCode(-1) - .setMsg("熔断Person2") - .setData(new Person()); - return fallback; - } - }; - } - } - -} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeR4jTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeR4jTest.java deleted file mode 100644 index d42b1db..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeR4jTest.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.degrade; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; -import java.util.stream.IntStream; - -import com.github.lianjiatech.retrofit.spring.boot.test.http.HttpApi2; -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.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; - -import com.fasterxml.jackson.annotation.JsonInclude; -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 yukdawn@gmail.com - */ -@ActiveProfiles("r4j") -@SpringBootTest(classes = RetrofitTestApplication.class) -@RunWith(SpringRunner.class) -public class DegradeR4jTest { - - @Autowired - private DegradeR4jApi degradeR4jApi; - - @Autowired - private HttpApi2 httpApi2; - - private static final ObjectMapper objectMapper = - new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .setSerializationInclusion(JsonInclude.Include.NON_NULL); - - private MockWebServer server; - - @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 testDegradeR4j() { - long count = IntStream.range(0, 100).parallel().map((i) -> { - try { - 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/text; charset=utf-8") - .addHeader("Cache-Control", "no-cache") - .setBody(objectMapper.writeValueAsString(mockResult)) - .setBodyDelay(6, TimeUnit.SECONDS); - server.enqueue(response); - return degradeR4jApi.getPerson1(2L).getCode(); - } catch (Exception e) { - return 100; - } - }).filter(i -> i == -1).count(); - System.out.println(count); - Assert.assertTrue(count > 70L); - - } - -} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeSentinelApi.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeSentinelApi.java deleted file mode 100644 index ae12fa5..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeSentinelApi.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.degrade; - -import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; -import com.github.lianjiatech.retrofit.spring.boot.degrade.sentinel.SentinelDegrade; -import com.github.lianjiatech.retrofit.spring.boot.retry.Retry; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; - -import retrofit2.http.GET; -import retrofit2.http.Query; - -/** - * @author 陈添明 - */ -@RetrofitClient(baseUrl = "${test.baseUrl}", fallback = DegradeSentinelApiFallback.class) -@Retry(enable = false) -public interface DegradeSentinelApi { - - /** - * @param id . - * @return . - */ - @GET("degrade/person1") - Result getPerson1(@Query("id") Long id); - - @GET("degrade/person2") - @SentinelDegrade(enable = false) - Result getPerson2(@Query("id") Long id); - - -} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeSentinelApiFallback.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeSentinelApiFallback.java deleted file mode 100644 index 99da4c9..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeSentinelApiFallback.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.degrade; - -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; -import lombok.extern.slf4j.Slf4j; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Service; - -@Service -@Slf4j -@Order(value = Ordered.HIGHEST_PRECEDENCE) -public class DegradeSentinelApiFallback implements DegradeSentinelApi { - @Override - public Result getPerson1(Long id) { - log.info("触发熔断了"); - Result fallback = new Result<>(); - fallback.setCode(-1) - .setMsg("熔断Person1") - .setData(new Person()); - return fallback; - } - - @Override - public Result getPerson2(Long id) { - log.info("触发熔断了"); - Result fallback = new Result<>(); - fallback.setCode(-1) - .setMsg("熔断Person2") - .setData(new Person()); - return fallback; - } -} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeSentinelTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeSentinelTest.java deleted file mode 100644 index 9c0b26c..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/DegradeSentinelTest.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.degrade; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; -import java.util.stream.IntStream; - -import com.github.lianjiatech.retrofit.spring.boot.test.custom.okhttp.CustomOkHttpTestApi; -import com.github.lianjiatech.retrofit.spring.boot.test.http.HttpApi; -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.BeansException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; - -import com.fasterxml.jackson.annotation.JsonInclude; -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 lombok.extern.slf4j.Slf4j; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; - -/** - * @author yukdawn@gmail.com - */ -@ActiveProfiles("sentinel") -@SpringBootTest(classes = RetrofitTestApplication.class) -@RunWith(SpringRunner.class) -@Slf4j -public class DegradeSentinelTest { - - @Autowired - private DegradeSentinelApi degradeSentinelApi; - - @Autowired - private CustomOkHttpTestApi customOkHttpTestApi; - - @Autowired - private HttpApi httpApi; - - private static final ObjectMapper objectMapper = - new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .setSerializationInclusion(JsonInclude.Include.NON_NULL); - - private MockWebServer server; - - @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 testDegrade() { - long count = IntStream.range(0, 100).parallel().map((i) -> { - try { - 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/text; charset=utf-8") - .addHeader("Cache-Control", "no-cache") - .setBody(objectMapper.writeValueAsString(mockResult)) - .setBodyDelay(5, TimeUnit.SECONDS); - server.enqueue(response); - return degradeSentinelApi.getPerson1(2L).getCode(); - } catch (Exception e) { - return 100; - } - }).filter(i -> i == -1).count(); - System.out.println(count); - Assert.assertTrue(count > 80L); - - } -} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/entity/Person.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/entity/Person.java deleted file mode 100644 index d8e79b2..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/entity/Person.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.entity; - -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * @author 陈添明 - */ -@Data -@Accessors(chain = true) -public class Person { - - private Long id; - - private String name; - - private Integer age; -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/entity/Result.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/entity/Result.java deleted file mode 100644 index 59e806a..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/entity/Result.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.entity; - -import java.io.Serializable; - -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * @author 陈添明 - */ -@Data -@Accessors(chain = true) -public class Result implements Serializable { - private static final long serialVersionUID = -504027247149928390L; - private int code; - private String msg; - private String exceptionMsg; - private T data; -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/ex/AppException.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/ex/AppException.java deleted file mode 100644 index d574714..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/ex/AppException.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.ex; - -/** - * @author 陈添明 - */ -public class AppException extends RuntimeException { - - /** - * Constructs a new runtime exception with {@code null} as its - * detail message. The cause is not initialized, and may subsequently be - * initialized by a call to {@link #initCause}. - */ - public AppException() {} - - /** - * Constructs a new runtime exception with the specified detail message. - * The cause is not initialized, and may subsequently be initialized by a - * call to {@link #initCause}. - * - * @param message the detail message. The detail message is saved for - * later retrieval by the {@link #getMessage()} method. - */ - public AppException(String message) { - super(message); - } - - /** - * Constructs a new runtime exception with the specified detail message and - * cause.

Note that the detail message associated with - * {@code cause} is not automatically incorporated in - * this runtime exception's detail message. - * - * @param message the detail message (which is saved for later retrieval - * by the {@link #getMessage()} method). - * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method). (A null value is - * permitted, and indicates that the cause is nonexistent or - * unknown.) - * @since 1.4 - */ - public AppException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Constructs a new runtime exception with the specified cause and a - * detail message of (cause==null ? null : cause.toString()) - * (which typically contains the class and detail message of - * cause). This constructor is useful for runtime exceptions - * that are little more than wrappers for other throwables. - * - * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method). (A null value is - * permitted, and indicates that the cause is nonexistent or - * unknown.) - * @since 1.4 - */ - public AppException(Throwable cause) { - super(cause); - } - - /** - * Constructs a new runtime exception with the specified detail - * message, cause, suppression enabled or disabled, and writable - * stack trace enabled or disabled. - * - * @param message the detail message. - * @param cause the cause. (A {@code null} value is permitted, - * and indicates that the cause is nonexistent or unknown.) - * @param enableSuppression whether or not suppression is enabled - * or disabled - * @param writableStackTrace whether or not the stack trace should - * be writable - * @since 1.7 - */ - public AppException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/ex/AppIOException.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/ex/AppIOException.java deleted file mode 100644 index a1f3258..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/ex/AppIOException.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.ex; - -/** - * @author 陈添明 - */ -public class AppIOException extends RuntimeException { - - /** - * Constructs a new runtime exception with {@code null} as its - * detail message. The cause is not initialized, and may subsequently be - * initialized by a call to {@link #initCause}. - */ - public AppIOException() {} - - /** - * Constructs a new runtime exception with the specified detail message. - * The cause is not initialized, and may subsequently be initialized by a - * call to {@link #initCause}. - * - * @param message the detail message. The detail message is saved for - * later retrieval by the {@link #getMessage()} method. - */ - public AppIOException(String message) { - super(message); - } - - /** - * Constructs a new runtime exception with the specified detail message and - * cause.

Note that the detail message associated with - * {@code cause} is not automatically incorporated in - * this runtime exception's detail message. - * - * @param message the detail message (which is saved for later retrieval - * by the {@link #getMessage()} method). - * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method). (A null value is - * permitted, and indicates that the cause is nonexistent or - * unknown.) - * @since 1.4 - */ - public AppIOException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Constructs a new runtime exception with the specified cause and a - * detail message of (cause==null ? null : cause.toString()) - * (which typically contains the class and detail message of - * cause). This constructor is useful for runtime exceptions - * that are little more than wrappers for other throwables. - * - * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method). (A null value is - * permitted, and indicates that the cause is nonexistent or - * unknown.) - * @since 1.4 - */ - public AppIOException(Throwable cause) { - super(cause); - } - - /** - * Constructs a new runtime exception with the specified detail - * message, cause, suppression enabled or disabled, and writable - * stack trace enabled or disabled. - * - * @param message the detail message. - * @param cause the cause. (A {@code null} value is permitted, - * and indicates that the cause is nonexistent or unknown.) - * @param enableSuppression whether or not suppression is enabled - * or disabled - * @param writableStackTrace whether or not the stack trace should - * be writable - * @since 1.7 - */ - public AppIOException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/ex/TestErrorDecoder.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/ex/TestErrorDecoder.java deleted file mode 100644 index d604d2d..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/ex/TestErrorDecoder.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.ex; - -import com.github.lianjiatech.retrofit.spring.boot.core.ErrorDecoder; -import com.github.lianjiatech.retrofit.spring.boot.exception.ReadResponseBodyException; -import com.github.lianjiatech.retrofit.spring.boot.util.RetrofitUtils; -import okhttp3.Request; -import okhttp3.Response; -import org.springframework.stereotype.Component; - -import java.io.IOException; - -/** - * @author 陈添明 - */ -@Component -public class TestErrorDecoder implements ErrorDecoder { - - @Override - public RuntimeException invalidRespDecode(Request request, Response response) { - - if (!response.isSuccessful()) { - String responseBody = null; - try { - responseBody = RetrofitUtils.readResponseBody(response); - } catch (ReadResponseBodyException e) { - // do nothing - } - throw new AppException("非法响应,request=" + request + " response=" + response + "body=" + responseBody); - } - - return null; - } - - @Override - public RuntimeException ioExceptionDecode(Request request, IOException cause) { - throw new AppIOException("应用网络异常!request=" + request); - } -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/ConvertFactoriesTestApi.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/ConvertFactoriesTestApi.java deleted file mode 100644 index 98a6195..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/ConvertFactoriesTestApi.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.http; - -import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; - -import retrofit2.converter.gson.GsonConverterFactory; -import retrofit2.converter.jaxb.JaxbConverterFactory; -import retrofit2.http.GET; -import retrofit2.http.Query; - -/** - * @author 陈添明 - */ -@RetrofitClient(baseUrl = "${test.baseUrl}", - converterFactories = {GsonConverterFactory.class, JaxbConverterFactory.class}) -public interface ConvertFactoriesTestApi { - - @GET("person") - Result getPerson(@Query("id") Long id); -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/HttpApi.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/HttpApi.java deleted file mode 100644 index c68aab9..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/HttpApi.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.http; - -import java.util.List; -import java.util.concurrent.CompletableFuture; - -import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; -import com.github.lianjiatech.retrofit.spring.boot.degrade.sentinel.SentinelDegrade; -import com.github.lianjiatech.retrofit.spring.boot.interceptor.Intercept; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; -import com.github.lianjiatech.retrofit.spring.boot.test.ex.TestErrorDecoder; -import com.github.lianjiatech.retrofit.spring.boot.test.interceptor.Sign; -import com.github.lianjiatech.retrofit.spring.boot.test.interceptor.TimeStamp2Interceptor; -import com.github.lianjiatech.retrofit.spring.boot.test.interceptor.TimeStampInterceptor; - -import io.reactivex.rxjava3.core.Completable; -import io.reactivex.rxjava3.core.Single; -import reactor.core.publisher.Mono; -import retrofit2.Call; -import retrofit2.Response; -import retrofit2.http.Body; -import retrofit2.http.GET; -import retrofit2.http.POST; -import retrofit2.http.Query; - -/** - * @author 陈添明 - */ -@RetrofitClient(baseUrl = "${test.baseUrl}", errorDecoder = TestErrorDecoder.class) -@Sign(accessKeyId = "${test.accessKeyId}", accessKeySecret = "${test.accessKeySecret}", exclude = {"/api/test/query"}) -@Intercept(handler = TimeStampInterceptor.class) -@Intercept(handler = TimeStamp2Interceptor.class) -public interface HttpApi { - - /** - * 基础类型(`String`/`Long`/`Integer`/`Boolean`/`Float`/`Double`):直接将响应内容转换为上述基础类型。 - */ - @POST("getString") - String getString(@Body Person person); - - /** - * 其它任意POJO类型: 将响应体内容适配成一个对应的POJO类型对象返回,如果http状态码不是2xx,直接抛错! - */ - @GET("person") - @SentinelDegrade - Result getPerson(@Query("id") Long id); - - /** - * `CompletableFuture` :将响应体内容适配成CompletableFuture对象返回,异步调用 - */ - @GET("person") - CompletableFuture> getPersonCompletableFuture(@Query("id") Long id); - - /** - * `Void`: 不关注返回类型可以使用`Void`,如果http状态码不是2xx,直接抛错! - */ - @POST("savePerson") - Void savePersonVoid(@Body Person person); - - /** - * `Response`:将响应内容适配成Response对象返回 - */ - @GET("person") - Response> getPersonResponse(@Query("id") Long id); - - /** - * `Call`:不执行适配处理,直接返回Call对象 - */ - @GET("person") - Call> getPersonCall(@Query("id") Long id); - - - /** - * `Mono` : project-reactor响应式返回类型 - */ - @GET("person") - Mono> monoPerson(@Query("id") Long id); - - /** - * `Single`:rxjava响应式返回类型(支持rxjava2/rxjava3) - */ - @GET("person") - Single> singlePerson(@Query("id") Long id); - - /** - * `Completable`:rxjava响应式返回类型,http请求没有响应体(支持rxjava2/rxjava3) - */ - @GET("ping") - Completable ping(); - - @POST("savePerson") - Result savePerson(@Body Person person); - - @POST("error") - Person error(@Body Person person); - - @POST("savePersonList") - Result savePersonList(@Body List personList); - - @POST("getBoolean") - Boolean getBoolean(@Body Person person); -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/HttpApi2.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/HttpApi2.java deleted file mode 100644 index 4df9b5b..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/HttpApi2.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.http; - -import java.util.Map; - -import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; -import com.github.lianjiatech.retrofit.spring.boot.degrade.resilience4j.Resilience4jDegrade; -import com.github.lianjiatech.retrofit.spring.boot.interceptor.Intercept; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; -import com.github.lianjiatech.retrofit.spring.boot.test.interceptor.EnumIntercept; -import com.github.lianjiatech.retrofit.spring.boot.test.interceptor.EnvEnum; -import com.github.lianjiatech.retrofit.spring.boot.test.interceptor.TimeStampInterceptor; - -import retrofit2.http.Body; -import retrofit2.http.GET; -import retrofit2.http.HTTP; -import retrofit2.http.Query; - -/** - * @author 陈添明 - */ -@RetrofitClient(baseUrl = "${test.baseUrl}") -@Intercept(handler = TimeStampInterceptor.class, include = "/a/b", exclude = "/c/d") -@EnumIntercept(envEnum = EnvEnum.test) -@Resilience4jDegrade(circuitBreakerConfigName = "testCircuitBreakerConfig2") -public interface HttpApi2 { - - @GET("person") - Result getPerson(@Query("id") Long id); - - @GET("testMap") - Map> testMap(); - - @HTTP(method = "get", path = "/getPersonBody", hasBody = true) - Result getPersonBody(@Body Person person); - -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/HttpApi3.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/HttpApi3.java deleted file mode 100644 index 6ce71c7..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/HttpApi3.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.http; - -import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; - -import retrofit2.http.GET; -import retrofit2.http.Query; -import retrofit2.http.Url; - -/** - * @author 陈添明 - */ -@RetrofitClient(baseUrl = "http://ke.com") -public interface HttpApi3 { - - @GET - Result getPerson(@Url String url, @Query("id") Long id); -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/InterceptApi.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/InterceptApi.java deleted file mode 100644 index e755949..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/http/InterceptApi.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.http; - -import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; - -import retrofit2.http.GET; -import retrofit2.http.Query; - -/** - * @author 陈添明 - * @since 2022/1/21 4:19 下午 - */ -@RetrofitClient(baseUrl = "${test.baseUrl}") -public interface InterceptApi { - - - /** - * 其他任意Java类型
- * 将响应体内容适配成一个对应的Java类型对象返回,如果http状态码不是2xx,直接抛错!
- * - * @param id id - * @return 其他任意Java类型 - */ - @GET("person") - Result getPerson(@Query("id") Long id); - -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/MockWebServerTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/MockWebServerTest.java new file mode 100644 index 0000000..b4e099f --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/MockWebServerTest.java @@ -0,0 +1,104 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import org.junit.After; +import org.junit.Before; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; + +import lombok.SneakyThrows; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; + +/** + * @author 陈添明 + * @since 2023/12/16 10:17 下午 + */ + +public class MockWebServerTest { + + public static final int SUCCESS_CODE = 200; + public static final int ERROR_CODE = 500; + public static final long Long100 = 100L; + public static final long Long200 = 200L; + public static final String MIKE = "mike"; + public static final String EMMA = "emma"; + public static final String FALL_BACK = "fallBack"; + public static final int INT20 = 20; + public static final int INT30 = 30; + + + public static final User USER_MIKE = new User().setId(Long100) + .setName(MIKE) + .setAge(INT20) + .setMale(true); + + public static final User USER_EMMA = new User().setId(Long200) + .setName(EMMA) + .setAge(INT30) + .setMale(false); + + public static final User USER_FALL_BACK = new User().setId(Long200) + .setName(FALL_BACK) + .setAge(-1) + .setMale(false); + + + + public MockWebServer server; + + public static final ObjectMapper OBJECT_MAPPER = + new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .setSerializationInclusion(JsonInclude.Include.NON_NULL); + + @SneakyThrows + public static String writeValueAsString(Object obj) { + return OBJECT_MAPPER.writeValueAsString(obj); + } + + @Before + public void before() throws IOException { + server = new MockWebServer(); + server.start(8080); + + } + + @After + public void after() throws IOException { + server.close(); + } + + public void mockServerReturnString(Object object) { + // mock + MockResponse response = new MockResponse() + .setResponseCode(SUCCESS_CODE) + .addHeader("Content-Type", "application/json; charset=utf-8") + .addHeader("Cache-Control", "no-cache") + .setBody(String.valueOf(object)); + server.enqueue(response); + } + + public void mockServerReturnObject(Object object) { + mockServerReturnObject(object, 0); + } + + public void mockServerReturnObject(Object object, int bodyDelaySeconds) { + mockServerReturnObject(object, bodyDelaySeconds, SUCCESS_CODE); + } + + public void mockServerReturnObject(Object object, int bodyDelaySeconds, int responseCode) { + MockResponse response = new MockResponse() + .setResponseCode(responseCode) + .addHeader("Content-Type", "application/json; charset=utf-8") + .addHeader("Cache-Control", "no-cache") + .setBodyDelay(bodyDelaySeconds, TimeUnit.SECONDS) + .setBody(writeValueAsString(object)); + server.enqueue(response); + } + +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/RetrofitBootApplication.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/RetrofitBootApplication.java new file mode 100644 index 0000000..d442132 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/RetrofitBootApplication.java @@ -0,0 +1,16 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author 陈添明 + * @since 2023/12/17 2:56 下午 + */ +@SpringBootApplication +public class RetrofitBootApplication { + + public static void main(String[] args) { + SpringApplication.run(RetrofitBootApplication.class, args); + } +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/base/UserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/base/UserService.java new file mode 100644 index 0000000..9c3486f --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/base/UserService.java @@ -0,0 +1,78 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.base; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; + +import retrofit2.Call; +import retrofit2.Response; +import retrofit2.http.Body; +import retrofit2.http.GET; +import retrofit2.http.POST; +import retrofit2.http.Query; + +/** + * 包含User增删改查接口,底层通过http调用实现 + * @author 陈添明 + * @since 2023/12/16 9:47 下午 + */ +@RetrofitClient(baseUrl = "${test.baseUrl}") +public interface UserService { + + /** + * 根据id查询用户姓名 + */ + @POST("getName") + String getName(@Query("id") Long id); + + /** + * 根据id查询用户信息 + */ + @GET("getUser") + User getUser(@Query("id") Long id); + + /** + * 查询所有用户信息 + */ + @GET("getAll") + List getAll(); + + /** + * 根据id异步查询用户信息 + */ + @GET("getUserAsync") + CompletableFuture getUserAsync(@Query("id") Long id); + + /** + * 根据id查询用户信息,以Response返回 + */ + @GET("getUserReturnResponse") + Response getUserReturnResponse(@Query("id") Long id); + + /** + * 根据id查询用户信息,以Call返回,此时还没真正发起调用,需要使用方主动调用。 + */ + @GET("getUserReturnCall") + Call getUserReturnCall(@Query("id") Long id); + + /** + * 根据id查询用户是否是男性 + */ + @POST("isMale") + Boolean isMale(@Query("id") Long id); + + /** + * 保存用户 + */ + @POST("saveUser") + Void saveUser(@Body User user); + + /** + * 保存一组用户 + */ + @POST("saveUserList") + Void saveUserList(@Body List userList); + +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/base/UserServiceTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/base/UserServiceTest.java new file mode 100644 index 0000000..e313db9 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/base/UserServiceTest.java @@ -0,0 +1,149 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.base; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import com.github.lianjiatech.retrofit.spring.boot.exception.RetrofitException; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.RetrofitBootApplication; +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.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; + +import retrofit2.Call; +import retrofit2.Response; + +/** + * @author 陈添明 + * @since 2023/12/16 10:46 下午 + */ +@SpringBootTest(classes = {RetrofitBootApplication.class}) +@RunWith(SpringRunner.class) +public class UserServiceTest extends MockWebServerTest { + + @Autowired + private UserService userService; + + @Test + public void getName() { + mockServerReturnString(MIKE); + String name = userService.getName(Long100); + assertEquals(MIKE, name); + } + + @Test + public void getUser() { + mockServerReturnObject(USER_MIKE); + User user = userService.getUser(Long100); + assertNotNull(user); + assertEquals(Long100, user.getId()); + assertEquals(MIKE, user.getName()); + assertEquals(INT20, user.getAge()); + assertTrue(user.isMale()); + } + + @Test(expected = RetrofitException.class) + public void getUserError() { + mockServerReturnObject(USER_MIKE, 0, ERROR_CODE); + User user = userService.getUser(Long100); + assertNotNull(user); + assertEquals(Long100, user.getId()); + assertEquals(MIKE, user.getName()); + assertEquals(INT20, user.getAge()); + assertTrue(user.isMale()); + } + + @Test + public void getAll() { + List users = new ArrayList<>(); + users.add(USER_MIKE); + users.add(USER_EMMA); + mockServerReturnObject(users); + + List all = userService.getAll(); + assertEquals(users, all); + } + + @Test + public void getUserAsync() { + mockServerReturnObject(USER_MIKE); + CompletableFuture userCompletableFuture = userService.getUserAsync(Long100); + assertNotNull(userCompletableFuture); + User user; + try { + user = userCompletableFuture.get(); + } catch (Exception e) { + throw new IllegalStateException("userCompletableFuture get error"); + } + assertNotNull(user); + assertEquals(Long100, user.getId()); + assertEquals(MIKE, user.getName()); + assertEquals(INT20, user.getAge()); + assertTrue(user.isMale()); + } + + @Test + public void getUserReturnResponse() { + mockServerReturnObject(USER_MIKE); + Response userReturnResponse = userService.getUserReturnResponse(Long100); + assertNotNull(userReturnResponse); + assertEquals(SUCCESS_CODE, userReturnResponse.code()); + User user = userReturnResponse.body(); + assertNotNull(user); + assertEquals(Long100, user.getId()); + assertEquals(MIKE, user.getName()); + assertEquals(INT20, user.getAge()); + assertTrue(user.isMale()); + } + + @Test + public void getUserReturnCall() { + mockServerReturnObject(USER_MIKE); + Call userReturnCall = userService.getUserReturnCall(Long100); + assertNotNull(userReturnCall); + try { + Response userResponse = userReturnCall.execute(); + assertEquals(SUCCESS_CODE, userResponse.code()); + User user = userResponse.body(); + assertNotNull(user); + assertEquals(Long100, user.getId()); + assertEquals(MIKE, user.getName()); + assertEquals(INT20, user.getAge()); + assertTrue(user.isMale()); + } catch (IOException e) { + throw new IllegalStateException("userReturnCall execute error"); + } + } + + @Test + public void isMale() { + mockServerReturnString(true); + Boolean male = userService.isMale(Long100); + assertTrue(male); + } + + @Test + public void saveUser() { + mockServerReturnString(null); + userService.saveUser(USER_MIKE); + } + + @Test + public void saveUserList() { + List users = new ArrayList<>(); + users.add(USER_MIKE); + users.add(USER_EMMA); + mockServerReturnString(null); + userService.saveUserList(users); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/chooser/ChooserOkHttpUserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/chooser/ChooserOkHttpUserService.java new file mode 100644 index 0000000..b89ece8 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/chooser/ChooserOkHttpUserService.java @@ -0,0 +1,21 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.chooser; + +import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; + +import retrofit2.http.GET; +import retrofit2.http.Query; + +/** + * @author 陈添明 + * @since 2023/12/17 9:53 上午 + */ +@RetrofitClient(serviceId = "user", path = "/api/user") +public interface ChooserOkHttpUserService { + + /** + * 根据id查询用户信息 + */ + @GET("getUser") + User getUser(@Query("id") Long id); +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/chooser/ChooserOkHttpUserServiceTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/chooser/ChooserOkHttpUserServiceTest.java new file mode 100644 index 0000000..b58f40e --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/chooser/ChooserOkHttpUserServiceTest.java @@ -0,0 +1,39 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.chooser; + +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; +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.github.lianjiatech.retrofit.spring.boot.exception.RetrofitException; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.RetrofitBootApplication; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * @author 陈添明 + * @since 2023/12/17 10:03 上午 + */ +@SpringBootTest(classes = {RetrofitBootApplication.class}) +@RunWith(SpringRunner.class) +public class ChooserOkHttpUserServiceTest extends MockWebServerTest { + + @Autowired + private ChooserOkHttpUserService chooserOkHttpUserService; + + @Test + public void getUser() { + mockServerReturnObject(USER_MIKE); + User user = chooserOkHttpUserService.getUser(Long100); + assertNotNull(user); + assertEquals(Long100, user.getId()); + assertEquals(MIKE, user.getName()); + assertEquals(INT20, user.getAge()); + assertTrue(user.isMale()); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/chooser/MyServiceInstanceChooser.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/chooser/MyServiceInstanceChooser.java new file mode 100644 index 0000000..fb53097 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/chooser/MyServiceInstanceChooser.java @@ -0,0 +1,22 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.chooser; + +import com.github.lianjiatech.retrofit.spring.boot.core.ServiceInstanceChooser; +import org.springframework.stereotype.Component; + +import java.net.URI; + +/** + * @author 陈添明 + * @since 2023/12/17 6:51 下午 + */ +@Component +public class MyServiceInstanceChooser implements ServiceInstanceChooser { + + @Override + public URI choose(String serviceId) { + if (serviceId.equals("user")) { + return URI.create("http://localhost:8080"); + } + throw new IllegalStateException("illegal serviceId: " + serviceId); + } +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/custom/okhttp/CustomOkHttpClientRegistrar.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/custom/okhttp/CustomOkHttpClientRegistrar.java new file mode 100644 index 0000000..8f176cf --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/custom/okhttp/CustomOkHttpClientRegistrar.java @@ -0,0 +1,30 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.custom.okhttp; + +import java.time.Duration; + +import org.springframework.stereotype.Component; + +import com.github.lianjiatech.retrofit.spring.boot.core.SourceOkHttpClientRegistrar; +import com.github.lianjiatech.retrofit.spring.boot.core.SourceOkHttpClientRegistry; + +import lombok.extern.slf4j.Slf4j; +import okhttp3.OkHttpClient; + +/** + * @author 陈添明 + * @since 2022/5/24 9:29 下午 + */ +@Component +public class CustomOkHttpClientRegistrar implements SourceOkHttpClientRegistrar { + + @Override + public void register(SourceOkHttpClientRegistry registry) { + // 注册customOkHttpClient,超时时间设置为1s + registry.register("customOkHttpClient", new OkHttpClient.Builder() + .connectTimeout(Duration.ofSeconds(1)) + .writeTimeout(Duration.ofSeconds(1)) + .readTimeout(Duration.ofSeconds(1)) + .addInterceptor(chain -> chain.proceed(chain.request())) + .build()); + } +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/custom/okhttp/CustomOkHttpUserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/custom/okhttp/CustomOkHttpUserService.java new file mode 100644 index 0000000..528e99f --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/custom/okhttp/CustomOkHttpUserService.java @@ -0,0 +1,20 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.custom.okhttp; + +import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; +import retrofit2.http.GET; +import retrofit2.http.Query; + +/** + * @author 陈添明 + * @since 2023/12/17 9:53 上午 + */ +@RetrofitClient(baseUrl = "${test.baseUrl}", sourceOkHttpClient = "customOkHttpClient") +public interface CustomOkHttpUserService { + + /** + * 根据id查询用户信息 + */ + @GET("getUser") + User getUser(@Query("id") Long id); +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/custom/okhttp/CustomOkHttpUserServiceTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/custom/okhttp/CustomOkHttpUserServiceTest.java new file mode 100644 index 0000000..761d49a --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/custom/okhttp/CustomOkHttpUserServiceTest.java @@ -0,0 +1,30 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.custom.okhttp; + +import com.github.lianjiatech.retrofit.spring.boot.test.integration.RetrofitBootApplication; +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.github.lianjiatech.retrofit.spring.boot.exception.RetrofitException; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; + +/** + * @author 陈添明 + * @since 2023/12/17 10:03 上午 + */ +@SpringBootTest(classes = {RetrofitBootApplication.class}) +@RunWith(SpringRunner.class) +public class CustomOkHttpUserServiceTest extends MockWebServerTest { + + @Autowired + private CustomOkHttpUserService customOkHttpUserService; + + @Test(expected = RetrofitException.class) + public void getUser() { + // 自动okhttpClient,超时时间设置为1s,但是服务端2s才返回,因此该调用会超时 + mockServerReturnObject(USER_MIKE, 2); + customOkHttpUserService.getUser(Long100); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/CustomCircuitBreakerConfigRegistrar.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/CustomCircuitBreakerConfigRegistrar.java similarity index 76% rename from src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/CustomCircuitBreakerConfigRegistrar.java rename to src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/CustomCircuitBreakerConfigRegistrar.java index 1c4e4fd..89f6b18 100644 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/degrade/CustomCircuitBreakerConfigRegistrar.java +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/CustomCircuitBreakerConfigRegistrar.java @@ -1,4 +1,4 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.degrade; +package com.github.lianjiatech.retrofit.spring.boot.test.integration.degrade.resilience4j; import org.springframework.stereotype.Component; @@ -24,17 +24,16 @@ public void register(CircuitBreakerConfigRegistry registry) { // 注册其它的CircuitBreakerConfig registry.register("testCircuitBreakerConfig", CircuitBreakerConfig.custom() .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.TIME_BASED) - .failureRateThreshold(20) - .minimumNumberOfCalls(5) - .permittedNumberOfCallsInHalfOpenState(5) + .failureRateThreshold(1) + .minimumNumberOfCalls(1) + .permittedNumberOfCallsInHalfOpenState(2) .build()); - registry.register("testCircuitBreakerConfig2", CircuitBreakerConfig.custom() .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.TIME_BASED) - .failureRateThreshold(100) - .minimumNumberOfCalls(5000) - .permittedNumberOfCallsInHalfOpenState(5000) + .failureRateThreshold(1) + .minimumNumberOfCalls(1) + .permittedNumberOfCallsInHalfOpenState(10) .build()); } -} +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/GlobalResilience4jFallbackFactory.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/GlobalResilience4jFallbackFactory.java new file mode 100644 index 0000000..39f0b62 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/GlobalResilience4jFallbackFactory.java @@ -0,0 +1,23 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.degrade.resilience4j; + +import com.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; +import org.springframework.stereotype.Component; + +import com.github.lianjiatech.retrofit.spring.boot.degrade.FallbackFactory; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author 陈添明 + * @since 2023/12/17 3:54 下午 + */ +@Component +@Slf4j +public class GlobalResilience4jFallbackFactory implements FallbackFactory { + + @Override + public GlobalResilience4jUserService create(Throwable cause) { + log.error("触发熔断了!", cause); + return id -> MockWebServerTest.FALL_BACK; + } +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/GlobalResilience4jUserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/GlobalResilience4jUserService.java new file mode 100644 index 0000000..ee335c0 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/GlobalResilience4jUserService.java @@ -0,0 +1,22 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.degrade.resilience4j; + +import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; + +import retrofit2.http.POST; +import retrofit2.http.Query; + +/** + * @author 陈添明 + * @since 2023/12/17 12:47 下午 + */ +@RetrofitClient(baseUrl = "${test.baseUrl}", fallbackFactory = GlobalResilience4jFallbackFactory.class, + connectTimeoutMs = 1, readTimeoutMs = 1, writeTimeoutMs = 1) +public interface GlobalResilience4jUserService { + + /** + * 根据id查询用户姓名 + */ + @POST("getName") + String getName(@Query("id") Long id); + +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/GlobalResilience4jUserServiceTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/GlobalResilience4jUserServiceTest.java new file mode 100644 index 0000000..d791627 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/GlobalResilience4jUserServiceTest.java @@ -0,0 +1,44 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.degrade.resilience4j; + +import static org.junit.Assert.assertTrue; + +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +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.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.RetrofitBootApplication; + +/** + * @author 陈添明 + * @since 2023/12/17 12:50 下午 + */ +@SpringBootTest(classes = {RetrofitBootApplication.class}, + properties = {"retrofit.degrade.degrade-type=resilience4j", + "retrofit.degrade.global-resilience4j-degrade.enable=true", + "retrofit.degrade.global-resilience4j-degrade.circuit-breaker-config-name=testCircuitBreakerConfig"}) +@RunWith(SpringRunner.class) +public class GlobalResilience4jUserServiceTest extends MockWebServerTest { + + @Autowired + private GlobalResilience4jUserService globalResilience4jUserService; + + @Test + public void getName() { + Set set = IntStream.range(0, 50).parallel().mapToObj(i -> { + mockServerReturnObject(MIKE, 0, SUCCESS_CODE); + try { + return globalResilience4jUserService.getName(Long100); + } catch (Exception e) { + return null; + } + }).collect(Collectors.toSet()); + assertTrue(set.contains(FALL_BACK)); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/Resilience4jFallbackFactory.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/Resilience4jFallbackFactory.java new file mode 100644 index 0000000..dc11f6f --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/Resilience4jFallbackFactory.java @@ -0,0 +1,33 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.degrade.resilience4j; + +import com.github.lianjiatech.retrofit.spring.boot.degrade.FallbackFactory; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import com.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; + +/** + * @author 陈添明 + * @since 2023/12/17 5:18 下午 + */ +@Service +@Slf4j +public class Resilience4jFallbackFactory implements FallbackFactory { + + @Override + public Resilience4jUserService create(Throwable cause) { + log.error("触发熔断了!", cause); + return new Resilience4jUserService() { + @Override + public String getName(Long id) { + return MockWebServerTest.FALL_BACK; + } + + @Override + public User getUser(Long id) { + return MockWebServerTest.USER_FALL_BACK; + } + }; + } +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/Resilience4jUserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/Resilience4jUserService.java new file mode 100644 index 0000000..751caa4 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/Resilience4jUserService.java @@ -0,0 +1,34 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.degrade.resilience4j; + +import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; +import com.github.lianjiatech.retrofit.spring.boot.degrade.resilience4j.Resilience4jDegrade; +import com.github.lianjiatech.retrofit.spring.boot.degrade.sentinel.SentinelDegrade; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; + +import retrofit2.http.GET; +import retrofit2.http.POST; +import retrofit2.http.Query; + +/** + * @author 陈添明 + * @since 2023/12/17 12:47 下午 + */ +@RetrofitClient(baseUrl = "${test.baseUrl}", fallbackFactory = Resilience4jFallbackFactory.class, connectTimeoutMs = 1, + readTimeoutMs = 1, writeTimeoutMs = 1) +@Resilience4jDegrade(circuitBreakerConfigName = "testCircuitBreakerConfig") +public interface Resilience4jUserService { + + /** + * 根据id查询用户姓名 + */ + @POST("getName") + String getName(@Query("id") Long id); + + /** + * 根据id查询用户信息 + */ + @GET("getUser") + @Resilience4jDegrade(enable = false) + User getUser(@Query("id") Long id); + +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/Resilience4jUserServiceTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/Resilience4jUserServiceTest.java new file mode 100644 index 0000000..71bf1e9 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/resilience4j/Resilience4jUserServiceTest.java @@ -0,0 +1,56 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.degrade.resilience4j; + +import static org.junit.Assert.assertTrue; + +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +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.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.RetrofitBootApplication; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; + +/** + * @author 陈添明 + * @since 2023/12/17 12:50 下午 + */ +@SpringBootTest(classes = {RetrofitBootApplication.class}, + properties = {"retrofit.degrade.degrade-type=resilience4j"}) +@RunWith(SpringRunner.class) +public class Resilience4jUserServiceTest extends MockWebServerTest { + + @Autowired + private Resilience4jUserService resilience4jUserService; + + @Test + public void getName() { + Set set = IntStream.range(0, 50).parallel().mapToObj(i -> { + mockServerReturnObject(MIKE, 0, SUCCESS_CODE); + try { + return resilience4jUserService.getName(Long100); + } catch (Exception e) { + return null; + } + }).collect(Collectors.toSet()); + assertTrue(set.contains(FALL_BACK)); + } + + @Test + public void getUser() { + Set set = IntStream.range(0, 50).parallel().mapToObj(i -> { + mockServerReturnObject(MIKE, 0, SUCCESS_CODE); + try { + return resilience4jUserService.getUser(Long100); + } catch (Exception e) { + return null; + } + }).collect(Collectors.toSet()); + assertTrue(!set.contains(USER_FALL_BACK)); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/GlobalSentinelFallbackUserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/GlobalSentinelFallbackUserService.java new file mode 100644 index 0000000..8ea747f --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/GlobalSentinelFallbackUserService.java @@ -0,0 +1,15 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.degrade.sentinel; + +import com.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; + +/** + * @author 陈添明 + * @since 2023/12/17 3:54 下午 + */ +public class GlobalSentinelFallbackUserService implements GlobalSentinelUserService { + + @Override + public String getName(Long id) { + return MockWebServerTest.FALL_BACK; + } +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/GlobalSentinelUserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/GlobalSentinelUserService.java new file mode 100644 index 0000000..a662b95 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/GlobalSentinelUserService.java @@ -0,0 +1,21 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.degrade.sentinel; + +import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; + +import retrofit2.http.POST; +import retrofit2.http.Query; + +/** + * @author 陈添明 + * @since 2023/12/17 12:47 下午 + */ +@RetrofitClient(baseUrl = "${test.baseUrl}", fallback = GlobalSentinelFallbackUserService.class) +public interface GlobalSentinelUserService { + + /** + * 根据id查询用户姓名 + */ + @POST("getName") + String getName(@Query("id") Long id); + +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/GlobalSentinelUserServiceTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/GlobalSentinelUserServiceTest.java new file mode 100644 index 0000000..35cf739 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/GlobalSentinelUserServiceTest.java @@ -0,0 +1,44 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.degrade.sentinel; + +import static org.junit.Assert.assertTrue; + +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +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.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.RetrofitBootApplication; + +/** + * @author 陈添明 + * @since 2023/12/17 12:50 下午 + */ +@SpringBootTest(classes = {RetrofitBootApplication.class}, + properties = {"retrofit.degrade.degrade-type=sentinel", "retrofit.degrade.global-sentinel-degrade.enable=true", + "retrofit.degrade.global-sentinel-degrade.grade=0", "retrofit.degrade.global-sentinel-degrade.count=2", + "retrofit.degrade.global-sentinel-degrade.time-window=5"}) +@RunWith(SpringRunner.class) +public class GlobalSentinelUserServiceTest extends MockWebServerTest { + + @Autowired + private GlobalSentinelUserService globalSentinelUserService; + + @Test + public void getName() { + Set set = IntStream.range(0, 50).parallel().mapToObj(i -> { + mockServerReturnObject(MIKE, 0, SUCCESS_CODE); + try { + return globalSentinelUserService.getName(Long100); + } catch (Exception e) { + return null; + } + }).collect(Collectors.toSet()); + assertTrue(set.contains(FALL_BACK)); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/SentinelFallbackUserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/SentinelFallbackUserService.java new file mode 100644 index 0000000..23e0813 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/SentinelFallbackUserService.java @@ -0,0 +1,22 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.degrade.sentinel; + +import com.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; +import org.springframework.stereotype.Service; + +/** + * @author 陈添明 + * @since 2023/12/17 5:18 下午 + */ +@Service +public class SentinelFallbackUserService implements SentinelUserService { + @Override + public String getName(Long id) { + return MockWebServerTest.FALL_BACK; + } + + @Override + public User getUser(Long id) { + return MockWebServerTest.USER_FALL_BACK; + } +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/SentinelUserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/SentinelUserService.java new file mode 100644 index 0000000..9051767 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/SentinelUserService.java @@ -0,0 +1,33 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.degrade.sentinel; + +import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; + +import com.github.lianjiatech.retrofit.spring.boot.degrade.sentinel.SentinelDegrade; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; +import retrofit2.http.GET; +import retrofit2.http.POST; +import retrofit2.http.Query; + +/** + * @author 陈添明 + * @since 2023/12/17 12:47 下午 + */ +@RetrofitClient(baseUrl = "${test.baseUrl}", fallback = SentinelFallbackUserService.class, connectTimeoutMs = 1, + readTimeoutMs = 1, writeTimeoutMs = 1) +@SentinelDegrade(grade = 1, count = 0.01, timeWindow = 3) +public interface SentinelUserService { + + /** + * 根据id查询用户姓名 + */ + @POST("getName") + String getName(@Query("id") Long id); + + /** + * 根据id查询用户信息 + */ + @GET("getUser") + @SentinelDegrade(grade = 2, count = 1, timeWindow = 4) + User getUser(@Query("id") Long id); + +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/SentinelUserServiceTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/SentinelUserServiceTest.java new file mode 100644 index 0000000..a1e87a2 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/degrade/sentinel/SentinelUserServiceTest.java @@ -0,0 +1,56 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.degrade.sentinel; + +import static org.junit.Assert.assertTrue; + +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; +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.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.RetrofitBootApplication; + +/** + * @author 陈添明 + * @since 2023/12/17 12:50 下午 + */ +@SpringBootTest(classes = {RetrofitBootApplication.class}, + properties = {"retrofit.degrade.degrade-type=sentinel"}) +@RunWith(SpringRunner.class) +public class SentinelUserServiceTest extends MockWebServerTest { + + @Autowired + private SentinelUserService sentinelUserService; + + @Test + public void getName() { + Set set = IntStream.range(0, 50).parallel().mapToObj(i -> { + mockServerReturnObject(MIKE, 0, SUCCESS_CODE); + try { + return sentinelUserService.getName(Long100); + } catch (Exception e) { + return null; + } + }).collect(Collectors.toSet()); + assertTrue(set.contains(FALL_BACK)); + } + + @Test + public void getUser() { + Set set = IntStream.range(0, 50).parallel().mapToObj(i -> { + mockServerReturnObject(MIKE, 0, SUCCESS_CODE); + try { + return sentinelUserService.getUser(Long100); + } catch (Exception e) { + return null; + } + }).collect(Collectors.toSet()); + assertTrue(set.contains(USER_FALL_BACK)); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/entity/User.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/entity/User.java new file mode 100644 index 0000000..e76cdff --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/entity/User.java @@ -0,0 +1,21 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.entity; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * @author 陈添明 + * @since 2023/12/17 2:53 下午 + */ +@Data +@Accessors(chain = true) +public class User { + + private long id; + + private String name; + + private int age; + + private boolean male; +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/InterceptorUserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/InterceptorUserService.java new file mode 100644 index 0000000..b71012a --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/InterceptorUserService.java @@ -0,0 +1,40 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.interceptor; + +import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; +import com.github.lianjiatech.retrofit.spring.boot.interceptor.Intercept; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; +import retrofit2.Response; +import retrofit2.http.GET; +import retrofit2.http.POST; +import retrofit2.http.Query; + +import java.util.List; + +/** + * @author 陈添明 + * @since 2023/12/17 10:40 上午 + */ +@RetrofitClient(baseUrl = "${test.baseUrl}") +@Intercept(handler = PathMatchInterceptor.class, include = {"/api/user/**"}, exclude = "/api/user/getUser") +@Sign(accessKeyId = "${test.accessKeyId}", accessKeySecret = "${test.accessKeySecret}", include = "/api/user/getAll") +public interface InterceptorUserService { + + /** + * 根据id查询用户姓名 + */ + @POST("getName") + Response getName(@Query("id") Long id); + + /** + * 根据id查询用户信息 + */ + @GET("getUser") + Response getUser(@Query("id") Long id); + + /** + * 查询所有用户信息 + */ + @GET("getAll") + Response> getAll(); + +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/InterceptorUserServiceTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/InterceptorUserServiceTest.java new file mode 100644 index 0000000..1361312 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/InterceptorUserServiceTest.java @@ -0,0 +1,96 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.interceptor; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.ArrayList; +import java.util.List; + +import com.github.lianjiatech.retrofit.spring.boot.test.integration.RetrofitBootApplication; +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.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; + +import okhttp3.Headers; +import retrofit2.Response; + +/** + * @author 陈添明 + * @since 2023/12/17 10:56 上午 + */ +@SpringBootTest(classes = {RetrofitBootApplication.class}) +@RunWith(SpringRunner.class) +public class InterceptorUserServiceTest extends MockWebServerTest { + + @Autowired + private InterceptorUserService interceptorUserService; + + @Test + public void getName() { + mockServerReturnString(MIKE); + Response response = interceptorUserService.getName(Long100); + String body = response.body(); + assertEquals(MIKE, body); + Headers headers = response.headers(); + // 使用了全局拦截器 + String global = headers.get("global"); + assertEquals("true", global); + // 使用路径匹配拦截器 + String pathMatch = headers.get("path.match"); + assertEquals("true", pathMatch); + // 没有使用@Sign自定义注解拦截器 + String accessKeyId = headers.get("accessKeyId"); + String accessKeySecret = headers.get("accessKeySecret"); + assertNull(accessKeyId); + assertNull(accessKeySecret); + } + + @Test + public void getUser() { + mockServerReturnObject(USER_MIKE); + Response response = interceptorUserService.getUser(Long100); + User body = response.body(); + assertEquals(USER_MIKE, body); + Headers headers = response.headers(); + // 使用了全局拦截器 + String global = headers.get("global"); + assertEquals("true", global); + // 没有使用路径匹配拦截器 + String pathMatch = headers.get("path.match"); + assertNull(pathMatch); + // 没有使用@Sign自定义注解拦截器 + String accessKeyId = headers.get("accessKeyId"); + String accessKeySecret = headers.get("accessKeySecret"); + assertNull(accessKeyId); + assertNull(accessKeySecret); + } + + @Test + public void getAll() { + List users = new ArrayList<>(); + users.add(USER_MIKE); + users.add(USER_EMMA); + mockServerReturnObject(users); + + Response> response = interceptorUserService.getAll(); + List body = response.body(); + assertEquals(users, body); + Headers headers = response.headers(); + // 使用了全局拦截器 + String global = headers.get("global"); + assertEquals("true", global); + // 使用路径匹配拦截器 + String pathMatch = headers.get("path.match"); + assertEquals("true", pathMatch); + // 使用@Sign自定义注解拦截器 + String accessKeyId = headers.get("accessKeyId"); + String accessKeySecret = headers.get("accessKeySecret"); + assertEquals("root", accessKeyId); + assertEquals("123456", accessKeySecret); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/MyGlobalInterceptor.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/MyGlobalInterceptor.java new file mode 100644 index 0000000..e8e4a0e --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/MyGlobalInterceptor.java @@ -0,0 +1,21 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.interceptor; + +import com.github.lianjiatech.retrofit.spring.boot.interceptor.GlobalInterceptor; +import okhttp3.Response; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +/** + * @author 陈添明 + * @since 2023/12/17 10:54 上午 + */ +@Component +public class MyGlobalInterceptor implements GlobalInterceptor { + @Override + public Response intercept(Chain chain) throws IOException { + Response response = chain.proceed(chain.request()); + // response的Header加上global + return response.newBuilder().header("global", "true").build(); + } +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/PathMatchInterceptor.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/PathMatchInterceptor.java new file mode 100644 index 0000000..ad9b235 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/PathMatchInterceptor.java @@ -0,0 +1,23 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.interceptor; + +import java.io.IOException; + +import org.springframework.stereotype.Component; + +import com.github.lianjiatech.retrofit.spring.boot.interceptor.BasePathMatchInterceptor; + +import okhttp3.Response; + +/** + * @author 陈添明 + * @since 2023/12/17 10:23 上午 + */ +@Component +public class PathMatchInterceptor extends BasePathMatchInterceptor { + @Override + protected Response doIntercept(Chain chain) throws IOException { + Response response = chain.proceed(chain.request()); + // response的Header加上path.match + return response.newBuilder().header("path.match", "true").build(); + } +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/Sign.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/Sign.java similarity index 94% rename from src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/Sign.java rename to src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/Sign.java index 20944ab..f2b7197 100644 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/Sign.java +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/Sign.java @@ -1,4 +1,4 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.interceptor; +package com.github.lianjiatech.retrofit.spring.boot.test.integration.interceptor; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/SignInterceptor.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/SignInterceptor.java similarity index 74% rename from src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/SignInterceptor.java rename to src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/SignInterceptor.java index a4d28b4..9f68615 100644 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/SignInterceptor.java +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/interceptor/SignInterceptor.java @@ -1,4 +1,4 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.interceptor; +package com.github.lianjiatech.retrofit.spring.boot.test.integration.interceptor; import java.io.IOException; @@ -30,6 +30,8 @@ public Response doIntercept(Chain chain) throws IOException { .addHeader("accessKeyId", accessKeyId) .addHeader("accessKeySecret", accessKeySecret) .build(); - return chain.proceed(newReq); + Response response = chain.proceed(newReq); + return response.newBuilder().addHeader("accessKeyId", accessKeyId) + .addHeader("accessKeySecret", accessKeySecret).build(); } } diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/log/GlobalRetryUserServiceTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/log/GlobalRetryUserServiceTest.java new file mode 100644 index 0000000..abde3a9 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/log/GlobalRetryUserServiceTest.java @@ -0,0 +1,59 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.log; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.github.lianjiatech.retrofit.spring.boot.test.integration.RetrofitBootApplication; +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.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author 陈添明 + * @since 2023/12/17 12:50 下午 + */ +@SpringBootTest(classes = {RetrofitBootApplication.class}) +@RunWith(SpringRunner.class) +public class GlobalRetryUserServiceTest extends MockWebServerTest { + + @Autowired + private LogUserService logUserService; + + @Test + public void getName() { + mockServerReturnString(MIKE); + String name = logUserService.getName(Long100); + assertEquals(MIKE, name); + } + + @Test + public void getUser() { + mockServerReturnObject(USER_MIKE); + User user = logUserService.getUser(Long100); + assertNotNull(user); + assertEquals(Long100, user.getId()); + assertEquals(MIKE, user.getName()); + assertEquals(INT20, user.getAge()); + assertTrue(user.isMale()); + } + + @Test + public void getAll() { + List users = new ArrayList<>(); + users.add(USER_MIKE); + users.add(USER_EMMA); + mockServerReturnObject(users); + + List all = logUserService.getAll(); + assertEquals(users, all); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/log/LogUserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/log/LogUserService.java new file mode 100644 index 0000000..b098ab3 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/log/LogUserService.java @@ -0,0 +1,41 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.log; + +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.integration.entity.User; + +import retrofit2.http.GET; +import retrofit2.http.POST; +import retrofit2.http.Query; + +import java.util.List; + +/** + * @author 陈添明 + * @since 2023/12/17 12:47 下午 + */ +@RetrofitClient(baseUrl = "${test.baseUrl}") +@Logging(logStrategy = LogStrategy.HEADERS) +public interface LogUserService { + + /** + * 根据id查询用户姓名 + */ + @POST("getName") + String getName(@Query("id") Long id); + + /** + * 根据id查询用户信息 + */ + @GET("getUser") + @Logging(logStrategy = LogStrategy.BODY) + User getUser(@Query("id") Long id); + + /** + * 查询所有用户信息 + */ + @GET("getAll") + @Logging(logStrategy = LogStrategy.BODY, aggregate = false) + List getAll(); +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/meta/annotation/MetaAnnotationUserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/meta/annotation/MetaAnnotationUserService.java new file mode 100644 index 0000000..8c0d2d7 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/meta/annotation/MetaAnnotationUserService.java @@ -0,0 +1,20 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.meta.annotation; + +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; + +import retrofit2.http.GET; +import retrofit2.http.Query; + +/** + * @author 陈添明 + * @since 2023/12/17 9:53 上午 + */ +@MyRetrofitClient +public interface MetaAnnotationUserService { + + /** + * 根据id查询用户信息 + */ + @GET("getUser") + User getUser(@Query("id") Long id); +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/meta/annotation/MetaAnnotationUserServiceTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/meta/annotation/MetaAnnotationUserServiceTest.java new file mode 100644 index 0000000..fb8b39e --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/meta/annotation/MetaAnnotationUserServiceTest.java @@ -0,0 +1,39 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.meta.annotation; + +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; +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.github.lianjiatech.retrofit.spring.boot.exception.RetrofitException; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.RetrofitBootApplication; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * @author 陈添明 + * @since 2023/12/17 10:03 上午 + */ +@SpringBootTest(classes = {RetrofitBootApplication.class}) +@RunWith(SpringRunner.class) +public class MetaAnnotationUserServiceTest extends MockWebServerTest { + + @Autowired + private MetaAnnotationUserService metaAnnotationUserService; + + @Test + public void getUser() { + mockServerReturnObject(USER_MIKE); + User user = metaAnnotationUserService.getUser(Long100); + assertNotNull(user); + assertEquals(Long100, user.getId()); + assertEquals(MIKE, user.getName()); + assertEquals(INT20, user.getAge()); + assertTrue(user.isMale()); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/meta/MyRetrofitClient.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/meta/annotation/MyRetrofitClient.java similarity index 90% rename from src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/meta/MyRetrofitClient.java rename to src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/meta/annotation/MyRetrofitClient.java index 1ca9cc2..2f27847 100644 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/meta/MyRetrofitClient.java +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/meta/annotation/MyRetrofitClient.java @@ -1,27 +1,21 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.meta; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.springframework.core.annotation.AliasFor; +package com.github.lianjiatech.retrofit.spring.boot.test.integration.meta.annotation; import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; import com.github.lianjiatech.retrofit.spring.boot.log.LogLevel; 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.retry.Retry; - +import org.springframework.core.annotation.AliasFor; import retrofit2.Converter; import retrofit2.converter.gson.GsonConverterFactory; -/** - * @author 陈添明 - * @since 2022/5/7 6:51 下午 - */ +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @@ -36,4 +30,4 @@ @AliasFor(annotation = Logging.class, attribute = "logStrategy") LogStrategy logStrategy() default LogStrategy.BODY; -} +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/mono/MonoUserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/mono/MonoUserService.java new file mode 100644 index 0000000..afae0d8 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/mono/MonoUserService.java @@ -0,0 +1,21 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.reactive.mono; + +import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; +import reactor.core.publisher.Mono; +import retrofit2.http.GET; +import retrofit2.http.Query; + +/** + * @author 陈添明 + * @since 2023/12/17 12:12 上午 + */ +@RetrofitClient(baseUrl = "${test.baseUrl}") +public interface MonoUserService { + + /** + * 根据id查询用户信息,返回Project-Reactor流式对象Mono + */ + @GET("getUserReturnMono") + Mono getUserReturnMono(@Query("id") Long id); +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/mono/MonoUserServiceTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/mono/MonoUserServiceTest.java new file mode 100644 index 0000000..cc4720e --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/mono/MonoUserServiceTest.java @@ -0,0 +1,42 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.reactive.mono; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.github.lianjiatech.retrofit.spring.boot.test.integration.RetrofitBootApplication; +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.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; + +import reactor.core.publisher.Mono; + +/** + * @author 陈添明 + * @since 2023/12/17 12:15 上午 + */ +@SpringBootTest(classes = {RetrofitBootApplication.class}) +@RunWith(SpringRunner.class) +public class MonoUserServiceTest extends MockWebServerTest { + + @Autowired + private MonoUserService monoUserService; + + @Test + public void getUserReturnMono() { + mockServerReturnObject(USER_MIKE); + Mono userReturnMono = monoUserService.getUserReturnMono(Long100); + User user = userReturnMono.block(); + assertNotNull(user); + assertEquals(Long100, user.getId()); + assertEquals(MIKE, user.getName()); + assertEquals(INT20, user.getAge()); + assertTrue(user.isMale()); + } + +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/rx/RxJava2UserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/rx/RxJava2UserService.java new file mode 100644 index 0000000..09755b9 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/rx/RxJava2UserService.java @@ -0,0 +1,31 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.reactive.rx; + +import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; +import io.reactivex.Completable; +import io.reactivex.Single; +import retrofit2.http.Body; +import retrofit2.http.GET; +import retrofit2.http.POST; +import retrofit2.http.Query; + +/** + * @author 陈添明 + * @since 2023/12/17 12:09 上午 + */ +@RetrofitClient(baseUrl = "${test.baseUrl}") +public interface RxJava2UserService { + + + /** + * 保存用户,返回Rx-Java流式对象Completable(http请求没有响应体返回该对象) + */ + @POST("saveUserReturnCompletableForRx2") + Completable saveUserReturnCompletableForRx2(@Body User user); + + /** + * 根据id查询用户信息,返回Rx-Java流式对象Single + */ + @GET("getUserReturnSingleForRx2") + Single getUserReturnSingleForRx2(@Query("id") Long id); +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/rx/RxJava2UserServiceTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/rx/RxJava2UserServiceTest.java new file mode 100644 index 0000000..a5c111e --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/rx/RxJava2UserServiceTest.java @@ -0,0 +1,49 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.reactive.rx; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.github.lianjiatech.retrofit.spring.boot.test.integration.RetrofitBootApplication; +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.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; + +import io.reactivex.Completable; +import io.reactivex.Single; + +/** + * @author 陈添明 + * @since 2023/12/17 12:20 上午 + */ +@SpringBootTest(classes = {RetrofitBootApplication.class}) +@RunWith(SpringRunner.class) +public class RxJava2UserServiceTest extends MockWebServerTest { + + @Autowired + private RxJava2UserService rxJava2UserService; + + @Test + public void saveUserReturnCompletableForRx2() { + mockServerReturnString(null); + Completable completable = rxJava2UserService.saveUserReturnCompletableForRx2(USER_MIKE); + completable.blockingAwait(); + } + + @Test + public void getUserReturnSingleForRx2() { + mockServerReturnObject(USER_MIKE); + Single userReturnSingle = rxJava2UserService.getUserReturnSingleForRx2(Long100); + User user = userReturnSingle.blockingGet(); + assertNotNull(user); + assertEquals(Long100, user.getId()); + assertEquals(MIKE, user.getName()); + assertEquals(INT20, user.getAge()); + assertTrue(user.isMale()); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/rx/RxJava3UserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/rx/RxJava3UserService.java new file mode 100644 index 0000000..07aa775 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/rx/RxJava3UserService.java @@ -0,0 +1,33 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.reactive.rx; + +import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; + + +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Single; +import retrofit2.http.Body; +import retrofit2.http.GET; +import retrofit2.http.POST; +import retrofit2.http.Query; + +/** + * @author 陈添明 + * @since 2023/12/17 12:09 上午 + */ +@RetrofitClient(baseUrl = "${test.baseUrl}") +public interface RxJava3UserService { + + + /** + * 保存用户,返回Rx-Java流式对象Completable(http请求没有响应体返回该对象) + */ + @POST("saveUserReturnCompletableForRx3") + Completable saveUserReturnCompletableForRx3(@Body User user); + + /** + * 根据id查询用户信息,返回Rx-Java流式对象Single + */ + @GET("getUserReturnSingleForRx2") + Single getUserReturnSingleForRx3(@Query("id") Long id); +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/rx/RxJava3UserServiceTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/rx/RxJava3UserServiceTest.java new file mode 100644 index 0000000..d3872be --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/reactive/rx/RxJava3UserServiceTest.java @@ -0,0 +1,50 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.reactive.rx; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.github.lianjiatech.retrofit.spring.boot.test.integration.RetrofitBootApplication; +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.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; + +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Single; + + +/** + * @author 陈添明 + * @since 2023/12/17 12:20 上午 + */ +@SpringBootTest(classes = {RetrofitBootApplication.class}) +@RunWith(SpringRunner.class) +public class RxJava3UserServiceTest extends MockWebServerTest { + + @Autowired + private RxJava3UserService rxJava3UserService; + + @Test + public void saveUserReturnCompletableForRx3() { + mockServerReturnString(null); + Completable completable = rxJava3UserService.saveUserReturnCompletableForRx3(USER_MIKE); + completable.blockingAwait(); + } + + @Test + public void getUserReturnSingleForRx3() { + mockServerReturnObject(USER_MIKE); + Single userReturnSingle = rxJava3UserService.getUserReturnSingleForRx3(Long100); + User user = userReturnSingle.blockingGet(); + assertNotNull(user); + assertEquals(Long100, user.getId()); + assertEquals(MIKE, user.getName()); + assertEquals(INT20, user.getAge()); + assertTrue(user.isMale()); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/retry/GlobalRetryUserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/retry/GlobalRetryUserService.java new file mode 100644 index 0000000..bd1e803 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/retry/GlobalRetryUserService.java @@ -0,0 +1,39 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.retry; + +import java.util.List; + +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.retry.Retry; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; + +import retrofit2.http.GET; +import retrofit2.http.POST; +import retrofit2.http.Query; + +/** + * @author 陈添明 + * @since 2023/12/17 12:47 下午 + */ +@RetrofitClient(baseUrl = "${test.baseUrl}") +public interface GlobalRetryUserService { + + /** + * 根据id查询用户姓名 + */ + @POST("getName") + String getName(@Query("id") Long id); + + /** + * 根据id查询用户信息 + */ + @GET("getUser") + User getUser(@Query("id") Long id); + + /** + * 查询所有用户信息 + */ + @GET("getAll") + List getAll(); +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/retry/GlobalRetryUserServiceTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/retry/GlobalRetryUserServiceTest.java new file mode 100644 index 0000000..89a91e6 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/retry/GlobalRetryUserServiceTest.java @@ -0,0 +1,65 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.retry; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +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.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.RetrofitBootApplication; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; + +/** + * @author 陈添明 + * @since 2023/12/17 12:50 下午 + */ +@SpringBootTest(classes = {RetrofitBootApplication.class}, properties = {"retrofit.global-retry.enable=true", "retrofit.global-retry.interval-ms=10", + "retrofit.global-retry.max-retries=3", "retrofit.global-retry.retry-rules=[RESPONSE_STATUS_NOT_2XX]"}) +@RunWith(SpringRunner.class) +public class GlobalRetryUserServiceTest extends MockWebServerTest { + + @Autowired + private GlobalRetryUserService globalRetryUserService; + + @Test + public void getName() { + mockServerReturnObject(MIKE, 0, ERROR_CODE); + mockServerReturnObject(MIKE, 0, ERROR_CODE); + mockServerReturnObject(MIKE, 0, SUCCESS_CODE); + globalRetryUserService.getName(Long100); + } + + @Test + public void getUser() { + mockServerReturnObject(USER_MIKE, 0, ERROR_CODE); + mockServerReturnObject(USER_MIKE, 0, ERROR_CODE); + mockServerReturnObject(USER_MIKE, 0, SUCCESS_CODE); + User user = globalRetryUserService.getUser(Long100); + assertNotNull(user); + assertEquals(Long100, user.getId()); + assertEquals(MIKE, user.getName()); + assertEquals(INT20, user.getAge()); + assertTrue(user.isMale()); + } + + @Test + public void getAll() { + List users = new ArrayList<>(); + users.add(USER_MIKE); + users.add(USER_EMMA); + mockServerReturnObject(users, 0, ERROR_CODE); + mockServerReturnObject(users, 0, ERROR_CODE); + mockServerReturnObject(users, 0, SUCCESS_CODE); + + List all = globalRetryUserService.getAll(); + assertEquals(users, all); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/retry/RetryUserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/retry/RetryUserService.java new file mode 100644 index 0000000..fd0c992 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/retry/RetryUserService.java @@ -0,0 +1,40 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.retry; + +import java.util.List; + +import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; +import com.github.lianjiatech.retrofit.spring.boot.retry.Retry; +import com.github.lianjiatech.retrofit.spring.boot.retry.RetryRule; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; + +import retrofit2.http.GET; +import retrofit2.http.POST; +import retrofit2.http.Query; + +/** + * @author 陈添明 + * @since 2023/12/17 12:47 下午 + */ +@RetrofitClient(baseUrl = "${test.baseUrl}", connectTimeoutMs = 100, readTimeoutMs = 100, writeTimeoutMs = 100) +@Retry(intervalMs = 5, maxRetries = 3, retryRules = RetryRule.RESPONSE_STATUS_NOT_2XX) +public interface RetryUserService { + + /** + * 根据id查询用户姓名 + */ + @POST("getName") + String getName(@Query("id") Long id); + + /** + * 根据id查询用户信息 + */ + @GET("getUser") + User getUser(@Query("id") Long id); + + /** + * 查询所有用户信息 + */ + @GET("getAll") + @Retry(enable = false) + List getAll(); +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/retry/RetryUserServiceTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/retry/RetryUserServiceTest.java new file mode 100644 index 0000000..537aee7 --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/retry/RetryUserServiceTest.java @@ -0,0 +1,63 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.retry; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import com.github.lianjiatech.retrofit.spring.boot.test.integration.RetrofitBootApplication; +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.github.lianjiatech.retrofit.spring.boot.exception.RetrofitException; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; + +/** + * @author 陈添明 + * @since 2023/12/17 12:50 下午 + */ +@SpringBootTest(classes = {RetrofitBootApplication.class}) +@RunWith(SpringRunner.class) +public class RetryUserServiceTest extends MockWebServerTest { + + @Autowired + private RetryUserService retryUserService; + + @Test + public void getName() { + mockServerReturnObject(MIKE, 0, ERROR_CODE); + mockServerReturnObject(MIKE, 0, ERROR_CODE); + mockServerReturnObject(MIKE, 0, SUCCESS_CODE); + retryUserService.getName(Long100); + } + + @Test + public void getUser() { + mockServerReturnObject(USER_MIKE, 0, ERROR_CODE); + mockServerReturnObject(USER_MIKE, 0, ERROR_CODE); + mockServerReturnObject(USER_MIKE, 0, SUCCESS_CODE); + User user = retryUserService.getUser(Long100); + assertNotNull(user); + assertEquals(Long100, user.getId()); + assertEquals(MIKE, user.getName()); + assertEquals(INT20, user.getAge()); + assertTrue(user.isMale()); + } + + @Test + public void getAll() { + List users = new ArrayList<>(); + users.add(USER_MIKE); + users.add(USER_EMMA); + mockServerReturnObject(users, 0, SUCCESS_CODE); + + List all = retryUserService.getAll(); + assertEquals(users, all); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/timeout/TimeoutUserService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/timeout/TimeoutUserService.java new file mode 100644 index 0000000..abda88a --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/timeout/TimeoutUserService.java @@ -0,0 +1,20 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.timeout; + +import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.entity.User; +import retrofit2.http.GET; +import retrofit2.http.Query; + +/** + * @author 陈添明 + * @since 2023/12/17 12:40 下午 + */ +@RetrofitClient(baseUrl = "${test.baseUrl}", readTimeoutMs = 1000, writeTimeoutMs = 1000) +public interface TimeoutUserService { + + /** + * 根据id查询用户信息 + */ + @GET("getUser") + User getUser(@Query("id") Long id); +} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/timeout/TimeoutUserServiceTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/timeout/TimeoutUserServiceTest.java new file mode 100644 index 0000000..3aa110c --- /dev/null +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/integration/timeout/TimeoutUserServiceTest.java @@ -0,0 +1,30 @@ +package com.github.lianjiatech.retrofit.spring.boot.test.integration.timeout; + +import com.github.lianjiatech.retrofit.spring.boot.test.integration.RetrofitBootApplication; +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.github.lianjiatech.retrofit.spring.boot.exception.RetrofitException; +import com.github.lianjiatech.retrofit.spring.boot.test.integration.MockWebServerTest; + +/** + * @author 陈添明 + * @since 2023/12/17 12:41 下午 + */ +@SpringBootTest(classes = {RetrofitBootApplication.class}) +@RunWith(SpringRunner.class) +public class TimeoutUserServiceTest extends MockWebServerTest { + + @Autowired + private TimeoutUserService timeoutUserService; + + @Test(expected = RetrofitException.class) + public void getUser() { + // 超时时间设置为1s,但是服务端2s才返回,因此该调用会超时 + mockServerReturnObject(USER_MIKE, 2); + timeoutUserService.getUser(Long100); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/EnumIntercept.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/EnumIntercept.java deleted file mode 100644 index 8b71f5c..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/EnumIntercept.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.interceptor; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import com.github.lianjiatech.retrofit.spring.boot.interceptor.BasePathMatchInterceptor; -import com.github.lianjiatech.retrofit.spring.boot.interceptor.InterceptMark; - -/** - * 自动将注解上的参数值赋值到handleInterceptor实例上 - * - * @author 陈添明 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -@Documented -@InterceptMark -public @interface EnumIntercept { - - EnvEnum envEnum(); - - /** - * 拦截器匹配路径 - * - * @return 拦截器匹配路径 - */ - String[] include() default {"/**"}; - - /** - * 拦截器排除匹配,排除指定路径拦截 - * - * @return 排除指定路径拦截 - */ - String[] exclude() default {}; - - /** - * 处理该注解的拦截器类
- * 优先从spring容器获取对应的Bean,如果获取不到,则使用反射创建一个!
- * 如果以Bean的形式配置,scope必须是prototype
- * - * @return 处理该注解的拦截器类 - */ - Class handler() default EnumInterceptor.class; -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/EnumInterceptor.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/EnumInterceptor.java deleted file mode 100644 index 3bad457..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/EnumInterceptor.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.interceptor; - -import com.github.lianjiatech.retrofit.spring.boot.interceptor.BasePathMatchInterceptor; -import okhttp3.Request; -import okhttp3.Response; -import org.springframework.stereotype.Component; - -import java.io.IOException; - -/** - * @author 陈添明 - */ -@Component -public class EnumInterceptor extends BasePathMatchInterceptor { - - private EnvEnum envEnum; - - public void setEnvEnum(EnvEnum envEnum) { - this.envEnum = envEnum; - } - - /** - * do intercept - * - * @param chain interceptor chain - * @return http Response - * @throws IOException IOException - */ - @Override - protected Response doIntercept(Chain chain) throws IOException { - - Request request = chain.request(); - - System.out.println(envEnum); - - return chain.proceed(request); - } -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/EnvEnum.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/EnvEnum.java deleted file mode 100644 index f08debb..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/EnvEnum.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.interceptor; - -/** - * @author 陈添明 - */ -public enum EnvEnum { - - test, - - prod -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/SourceGlobalInterceptor.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/SourceGlobalInterceptor.java deleted file mode 100644 index 2813b25..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/SourceGlobalInterceptor.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.interceptor; - -import java.io.IOException; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; - -import com.github.lianjiatech.retrofit.spring.boot.interceptor.GlobalInterceptor; -import com.github.lianjiatech.retrofit.spring.boot.test.service.TestService; - -import okhttp3.Request; -import okhttp3.Response; - -@Component -@Order(2) -public class SourceGlobalInterceptor implements GlobalInterceptor { - - @Autowired - private TestService testService; - - @Override - public Response intercept(Chain chain) throws IOException { - Request request = chain.request(); - Request newReq = request.newBuilder() - .addHeader("source", "test") - .build(); - System.out.println("===========执行全局重试==========="); - testService.test(); - return chain.proceed(newReq); - } -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/TestPriorityGlobalInterceptor.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/TestPriorityGlobalInterceptor.java deleted file mode 100644 index 0d68aa0..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/TestPriorityGlobalInterceptor.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.interceptor; - -import java.io.IOException; - -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; - -import com.github.lianjiatech.retrofit.spring.boot.interceptor.GlobalInterceptor; - -import okhttp3.Response; - -/** - * @author 陈添明 - * @since 2022/3/9 7:39 下午 - */ -@Component -@Order(1) -public class TestPriorityGlobalInterceptor implements GlobalInterceptor { - - @Override - public Response intercept(Chain chain) throws IOException { - return chain.proceed(chain.request()); - } -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/TimeStamp2Interceptor.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/TimeStamp2Interceptor.java deleted file mode 100644 index c263402..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/TimeStamp2Interceptor.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.interceptor; - -import java.io.IOException; - -import org.springframework.stereotype.Component; - -import com.github.lianjiatech.retrofit.spring.boot.interceptor.BasePathMatchInterceptor; - -import okhttp3.HttpUrl; -import okhttp3.Request; -import okhttp3.Response; - -/** - * @author 陈添明 - */ -@Component -public class TimeStamp2Interceptor extends BasePathMatchInterceptor { - - @Override - public Response doIntercept(Chain chain) throws IOException { - Request request = chain.request(); - HttpUrl url = request.url(); - long timestamp = System.currentTimeMillis(); - HttpUrl newUrl = url.newBuilder() - .addQueryParameter("timestamp2", String.valueOf(timestamp)) - .build(); - Request newRequest = request.newBuilder() - .url(newUrl) - .build(); - return chain.proceed(newRequest); - } -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/TimeStampInterceptor.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/TimeStampInterceptor.java deleted file mode 100644 index 65b059e..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/interceptor/TimeStampInterceptor.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.interceptor; - -import java.io.IOException; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Scope; -import org.springframework.context.annotation.ScopedProxyMode; -import org.springframework.stereotype.Component; - -import com.github.lianjiatech.retrofit.spring.boot.interceptor.BasePathMatchInterceptor; - -import okhttp3.HttpUrl; -import okhttp3.Request; -import okhttp3.Response; - -/** - * @author 陈添明 - */ -@Component -@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) -public class TimeStampInterceptor extends BasePathMatchInterceptor { - - @Value("${test.baseUrl}") - private String baseUrl; - - @Override - public Response doIntercept(Chain chain) throws IOException { - Request request = chain.request(); - HttpUrl url = request.url(); - long timestamp = System.currentTimeMillis(); - HttpUrl newUrl = url.newBuilder() - .addQueryParameter("timestamp", String.valueOf(timestamp)) - .build(); - Request newRequest = request.newBuilder() - .url(newUrl) - .build(); - return chain.proceed(newRequest); - } -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/meta/MetaAnnotationTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/meta/MetaAnnotationTest.java deleted file mode 100644 index f530322..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/meta/MetaAnnotationTest.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.meta; - -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.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 com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; - -/** - * @author 陈添明 - */ -@SpringBootTest(classes = RetrofitTestApplication.class) -@RunWith(SpringRunner.class) -public class MetaAnnotationTest { - - @Autowired - private MetaAnnotationTestApi metaAnnotationTestApi; - - private MockWebServer server; - - private static Gson gson = new GsonBuilder() - .create(); - - @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() { - - // 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(gson.toJson(mockResult)); - server.enqueue(response); - - // http check - Result person = metaAnnotationTestApi.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/meta/MetaAnnotationTestApi.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/meta/MetaAnnotationTestApi.java deleted file mode 100644 index dae9fa8..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/meta/MetaAnnotationTestApi.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.meta; - -import com.github.lianjiatech.retrofit.spring.boot.log.LogStrategy; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; - -import retrofit2.converter.gson.GsonConverterFactory; -import retrofit2.http.GET; -import retrofit2.http.Headers; -import retrofit2.http.Query; - -/** - * @author 陈添明 - */ -@MyRetrofitClient(converterFactories = GsonConverterFactory.class, logStrategy = LogStrategy.HEADERS) -public interface MetaAnnotationTestApi { - - @GET("person") - @Headers({ - "X-Foo: Bar", - "X-Ping: Pong" - }) - Result getPerson(@Query("id") Long id); -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/completable/Rxjava2CompletableTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/completable/Rxjava2CompletableTest.java deleted file mode 100644 index 84e056a..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/completable/Rxjava2CompletableTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.reactive.completable; - -import java.io.IOException; - -import org.junit.After; -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.github.lianjiatech.retrofit.spring.boot.test.RetrofitTestApplication; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import io.reactivex.Completable; -import lombok.extern.slf4j.Slf4j; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; - -/** - * @author 陈添明 - */ -@SpringBootTest(classes = RetrofitTestApplication.class) -@RunWith(SpringRunner.class) -@Slf4j -public class Rxjava2CompletableTest { - - @Autowired - private Rxjava2CompletableTestApi rxjava2CompletableTestApi; - - private MockWebServer server; - - private static Gson gson = new GsonBuilder() - .create(); - - @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 ping() { - MockResponse response = new MockResponse() - .setResponseCode(200) - .addHeader("Cache-Control", "no-cache"); - - server.enqueue(response); - - Completable completable = rxjava2CompletableTestApi.ping(); - completable.blockingAwait(); - } -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/completable/Rxjava2CompletableTestApi.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/completable/Rxjava2CompletableTestApi.java deleted file mode 100644 index 64015b1..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/completable/Rxjava2CompletableTestApi.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.reactive.completable; - -import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; - -import io.reactivex.Completable; -import retrofit2.http.GET; - -/** - * @author 陈添明 - */ -@RetrofitClient(baseUrl = "${test.baseUrl}") -public interface Rxjava2CompletableTestApi { - - @GET("ping") - Completable ping(); -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/completable/Rxjava3CompletableTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/completable/Rxjava3CompletableTest.java deleted file mode 100644 index 5414c33..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/completable/Rxjava3CompletableTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.reactive.completable; - -import java.io.IOException; - -import org.junit.After; -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.github.lianjiatech.retrofit.spring.boot.test.RetrofitTestApplication; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import io.reactivex.rxjava3.core.Completable; -import lombok.extern.slf4j.Slf4j; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; - -/** - * @author 陈添明 - */ -@SpringBootTest(classes = RetrofitTestApplication.class) -@RunWith(SpringRunner.class) -@Slf4j -public class Rxjava3CompletableTest { - - @Autowired - private Rxjava3CompletableTestApi rxjava3CompletableTestApi; - - private MockWebServer server; - - private static Gson gson = new GsonBuilder() - .create(); - - @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 ping() { - MockResponse response = new MockResponse() - .setResponseCode(200) - .addHeader("Cache-Control", "no-cache"); - - server.enqueue(response); - - Completable completable = rxjava3CompletableTestApi.ping(); - completable.blockingAwait(); - } -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/completable/Rxjava3CompletableTestApi.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/completable/Rxjava3CompletableTestApi.java deleted file mode 100644 index 38d0eb6..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/completable/Rxjava3CompletableTestApi.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.reactive.completable; - -import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; - -import io.reactivex.rxjava3.core.Completable; -import retrofit2.http.GET; - -/** - * @author 陈添明 - */ -@RetrofitClient(baseUrl = "${test.baseUrl}") -public interface Rxjava3CompletableTestApi { - - @GET("ping") - Completable ping(); -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/mono/MonoTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/mono/MonoTest.java deleted file mode 100644 index 40a2e00..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/mono/MonoTest.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.reactive.mono; - -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.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 com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import lombok.extern.slf4j.Slf4j; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import reactor.core.publisher.Mono; -import retrofit2.Response; - -/** - * @author 陈添明 - */ -@SpringBootTest(classes = RetrofitTestApplication.class) -@RunWith(SpringRunner.class) -@Slf4j -public class MonoTest { - - @Autowired - private MonoTestApi monoTestApi; - - private MockWebServer server; - - private static Gson gson = new GsonBuilder() - .create(); - - @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() { - - // 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(gson.toJson(mockResult)); - server.enqueue(response); - - // http check - Mono> mono = monoTestApi.getPerson(1L); - log.info("=======Mono立即返回,但未执行调用======="); - Result person = mono.block(); - Person data = person.getData(); - Assert.assertNotNull(data); - Assert.assertEquals("test", data.getName()); - Assert.assertEquals(10, data.getAge().intValue()); - } - - @Test - public void testResponse() { - - // 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(gson.toJson(mockResult)); - server.enqueue(response); - - // http check - Mono>> personResponse = monoTestApi.getPersonResponse(1L); - log.info("=======Mono立即返回,但未执行调用======="); - Response> resultResponse = personResponse.block(); - Assert.assertEquals(200, resultResponse.code()); - Result person = resultResponse.body(); - Person data = person.getData(); - Assert.assertNotNull(data); - Assert.assertEquals("test", data.getName()); - Assert.assertEquals(10, data.getAge().intValue()); - } - - - @Test - public void ping() { - MockResponse response = new MockResponse() - .setResponseCode(200) - .addHeader("Cache-Control", "no-cache"); - - server.enqueue(response); - - Mono mono = monoTestApi.ping(); - mono.block(); - } -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/mono/MonoTestApi.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/mono/MonoTestApi.java deleted file mode 100644 index 4557f83..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/mono/MonoTestApi.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.reactive.mono; - -import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; - -import reactor.core.publisher.Mono; -import retrofit2.Response; -import retrofit2.http.GET; -import retrofit2.http.Query; - -/** - * @author 陈添明 - */ -@RetrofitClient(baseUrl = "${test.baseUrl}") -public interface MonoTestApi { - - @GET("person") - Mono> getPerson(@Query("id") Long id); - - @GET("person") - Mono>> getPersonResponse(@Query("id") Long id); - - @GET("ping") - Mono ping(); -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/single/Rxjava2SingleTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/single/Rxjava2SingleTest.java deleted file mode 100644 index b28bc9a..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/single/Rxjava2SingleTest.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.reactive.single; - -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.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 com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import io.reactivex.Single; -import lombok.extern.slf4j.Slf4j; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import retrofit2.Response; - -/** - * @author 陈添明 - */ -@SpringBootTest(classes = RetrofitTestApplication.class) -@RunWith(SpringRunner.class) -@Slf4j -public class Rxjava2SingleTest { - - @Autowired - private Rxjava2SingleTestApi rxjava2SingleTestApi; - - private MockWebServer server; - - private static Gson gson = new GsonBuilder() - .create(); - - @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() { - - // 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(gson.toJson(mockResult)); - server.enqueue(response); - - // http check - Single> single = rxjava2SingleTestApi.getPerson(1L); - log.info("=======Single立即返回,但未执行调用======="); - Result person = single.blockingGet(); - Person data = person.getData(); - Assert.assertNotNull(data); - Assert.assertEquals("test", data.getName()); - Assert.assertEquals(10, data.getAge().intValue()); - } - - @Test - public void testResponse() { - - // 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(gson.toJson(mockResult)); - server.enqueue(response); - - // http check - Single>> personResponse = rxjava2SingleTestApi.getPersonResponse(1L); - log.info("=======Single立即返回,但未执行调用======="); - Response> resultResponse = personResponse.blockingGet(); - Assert.assertEquals(200, resultResponse.code()); - Result person = resultResponse.body(); - 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/reactive/single/Rxjava2SingleTestApi.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/single/Rxjava2SingleTestApi.java deleted file mode 100644 index d0ce5d4..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/single/Rxjava2SingleTestApi.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.reactive.single; - -import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; - -import io.reactivex.Single; -import retrofit2.Response; -import retrofit2.http.GET; -import retrofit2.http.Query; - -/** - * @author 陈添明 - */ -@RetrofitClient(baseUrl = "${test.baseUrl}") -public interface Rxjava2SingleTestApi { - - @GET("person") - Single> getPerson(@Query("id") Long id); - - @GET("person") - Single>> getPersonResponse(@Query("id") Long id); -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/single/Rxjava3SingleTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/single/Rxjava3SingleTest.java deleted file mode 100644 index 5c4869e..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/single/Rxjava3SingleTest.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.reactive.single; - -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.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 com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import io.reactivex.rxjava3.core.Single; -import lombok.extern.slf4j.Slf4j; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import retrofit2.Response; - -/** - * @author 陈添明 - */ -@SpringBootTest(classes = RetrofitTestApplication.class) -@RunWith(SpringRunner.class) -@Slf4j -public class Rxjava3SingleTest { - - @Autowired - private Rxjava3SingleTestApi rxjava3SingleTestApi; - - private MockWebServer server; - - private static Gson gson = new GsonBuilder() - .create(); - - @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() { - - // 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(gson.toJson(mockResult)); - server.enqueue(response); - - // http check - Single> single = rxjava3SingleTestApi.getPerson(1L); - log.info("=======Single立即返回,但未执行调用======="); - Result person = single.blockingGet(); - Person data = person.getData(); - Assert.assertNotNull(data); - Assert.assertEquals("test", data.getName()); - Assert.assertEquals(10, data.getAge().intValue()); - } - - @Test - public void testResponse() { - - // 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(gson.toJson(mockResult)); - server.enqueue(response); - - // http check - Single>> personResponse = rxjava3SingleTestApi.getPersonResponse(1L); - log.info("=======Single立即返回,但未执行调用======="); - Response> resultResponse = personResponse.blockingGet(); - Assert.assertEquals(200, resultResponse.code()); - Result person = resultResponse.body(); - 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/reactive/single/Rxjava3SingleTestApi.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/single/Rxjava3SingleTestApi.java deleted file mode 100644 index 207d8e3..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/reactive/single/Rxjava3SingleTestApi.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.reactive.single; - -import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person; -import com.github.lianjiatech.retrofit.spring.boot.test.entity.Result; - -import io.reactivex.rxjava3.core.Single; -import retrofit2.Response; -import retrofit2.http.GET; -import retrofit2.http.Query; - -/** - * @author 陈添明 - */ -@RetrofitClient(baseUrl = "${test.baseUrl}") -public interface Rxjava3SingleTestApi { - - @GET("person") - Single> getPerson(@Query("id") Long id); - - @GET("person") - Single>> getPersonResponse(@Query("id") Long id); -} diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/service/TestService.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/service/TestService.java deleted file mode 100644 index 5072bf6..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/service/TestService.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.github.lianjiatech.retrofit.spring.boot.test.service; - -import org.springframework.stereotype.Service; - -/** - * @author 陈添明 - * @since 2022/1/21 4:29 下午 - */ -@Service -public class TestService { - - public void test() { - } -} 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 deleted file mode 100644 index 6497940..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/timeout/TimeoutTest.java +++ /dev/null @@ -1,80 +0,0 @@ -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 deleted file mode 100644 index a654cf2..0000000 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/timeout/TimeoutTestApi.java +++ /dev/null @@ -1,24 +0,0 @@ -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-r4j.yml b/src/test/resources/application-r4j.yml deleted file mode 100644 index ae0f92a..0000000 --- a/src/test/resources/application-r4j.yml +++ /dev/null @@ -1,11 +0,0 @@ -retrofit: - # 熔断降级配置 - degrade: - # 熔断降级类型。默认none,表示不启用熔断降级 - degrade-type: resilience4j - # 全局resilience4j降级配置 - global-resilience4j-degrade: - # 是否开启 - enable: false - # 根据该名称从#{@link CircuitBreakerConfigRegistry}获取CircuitBreakerConfig,作为全局熔断配置 - circuit-breaker-config-name: defaultCircuitBreakerConfig \ No newline at end of file diff --git a/src/test/resources/application-sentinel.yml b/src/test/resources/application-sentinel.yml deleted file mode 100644 index 30285b9..0000000 --- a/src/test/resources/application-sentinel.yml +++ /dev/null @@ -1,15 +0,0 @@ -retrofit: - # 熔断降级配置 - degrade: - # 熔断降级类型。默认none,表示不启用熔断降级 - degrade-type: sentinel - # 全局sentinel降级配置 - global-sentinel-degrade: - # 是否开启 - enable: true - # 各降级策略对应的阈值。平均响应时间(ms),异常比例(0-1),异常数量(1-N) - count: 5 - # 熔断时长,单位为 s - time-window: 10 - # 降级策略(0:平均响应时间;1:异常比例;2:异常数量) - grade: 0 \ No newline at end of file diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index 6bba9eb..2209cd2 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -4,9 +4,9 @@ retrofit: global-converter-factories: - com.github.lianjiatech.retrofit.spring.boot.core.BasicTypeConverterFactory - retrofit2.converter.jackson.JacksonConverterFactory - # 全局调用适配器工厂(组件扩展的调用适配器工厂已经内置,这里请勿重复配置) + # 全局适配器工厂(组件扩展的`CallAdaptorFactory`工厂已经内置,这里请勿重复配置) global-call-adapter-factories: - - com.github.lianjiatech.retrofit.spring.boot.core.BodyCallAdapterFactory + # 全局日志打印配置 global-log: # 启用全局日志打印 @@ -14,17 +14,18 @@ retrofit: # 全局日志打印级别 log-level: info # 全局日志打印策略 - log-strategy: body - + log-strategy: basic + # 是否聚合打印请求日志 + aggregate: true # 全局重试配置 global-retry: # 是否启用全局重试 - enable: true + enable: false # 全局重试间隔时间 - interval-ms: 1 + interval-ms: 100 # 全局最大重试次数 - max-retries: 1 + max-retries: 2 # 全局重试规则 retry-rules: - response_status_not_2xx @@ -67,6 +68,6 @@ retrofit: auto-set-prototype-scope-for-path-math-interceptor: true test: - baseUrl: http://localhost:8080/api/test/ + baseUrl: http://localhost:8080/api/user/ accessKeyId: root accessKeySecret: 123456 diff --git a/src/test/resources/default-config.yml b/src/test/resources/default-config.yml deleted file mode 100644 index b23adc9..0000000 --- a/src/test/resources/default-config.yml +++ /dev/null @@ -1,64 +0,0 @@ -retrofit: - # 全局转换器工厂 - global-converter-factories: - - retrofit2.converter.jackson.JacksonConverterFactory - # 全局调用适配器工厂 - global-call-adapter-factories: - - # 全局日志打印配置 - global-log: - # 启用日志打印 - enable: true - # 全局日志打印级别 - log-level: info - # 全局日志打印策略 - log-strategy: basic - - # 全局重试配置 - global-retry: - # 是否启用全局重试 - enable: false - # 全局重试间隔时间 - interval-ms: 100 - # 全局最大重试次数 - max-retries: 2 - # 全局重试规则 - retry-rules: - - 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,表示不启用熔断降级 - degrade-type: none - # 全局sentinel降级配置 - global-sentinel-degrade: - # 是否开启 - enable: false - # 各降级策略对应的阈值。平均响应时间(ms),异常比例(0-1),异常数量(1-N) - count: 1000 - # 熔断时长,单位为 s - time-window: 5 - # 降级策略(0:平均响应时间;1:异常比例;2:异常数量) - grade: 0 - - # 全局resilience4j降级配置 - global-resilience4j-degrade: - # 是否开启 - enable: false - # 根据该名称从#{@link CircuitBreakerConfigRegistry}获取CircuitBreakerConfig,作为全局熔断配置 - circuit-breaker-config-name: defaultCircuitBreakerConfig - # 自动设置PathMathInterceptor的scope为prototype - auto-set-prototype-scope-for-path-math-interceptor: true \ No newline at end of file