Skip to content

Commit

Permalink
支持reactor、rxjava响应式编程
Browse files Browse the repository at this point in the history
  • Loading branch information
chentianming11 committed Jun 11, 2022
1 parent 63a3859 commit c726a3a
Show file tree
Hide file tree
Showing 26 changed files with 1,320 additions and 110 deletions.
111 changes: 64 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ gitee项目地址:[https://gitee.com/lianjiatech/retrofit-spring-boot-starter]
<dependency>
<groupId>com.github.lianjiatech</groupId>
<artifactId>retrofit-spring-boot-starter</artifactId>
<version>2.3.4</version>
<version>2.3.5</version>
</dependency>
```

Expand All @@ -59,7 +59,7 @@ gitee项目地址:[https://gitee.com/lianjiatech/retrofit-spring-boot-starter]
<dependency>
<groupId>com.github.lianjiatech</groupId>
<artifactId>retrofit-spring-boot-starter</artifactId>
<version>2.3.4</version>
<version>2.3.5</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
Expand Down Expand Up @@ -145,14 +145,11 @@ public class TestService {

```yaml
retrofit:
# 全局转换器工厂
# 全局转换器工厂(已经内置了组件扩展的转换器工厂,这里请勿重复配置)
global-converter-factories:
- com.github.lianjiatech.retrofit.spring.boot.core.BasicTypeConverterFactory
- retrofit2.converter.jackson.JacksonConverterFactory
# 全局调用适配器工厂
# 全局调用适配器工厂(已经内置了组件扩展的调用适配器工厂,这里请勿重复配置)
global-call-adapter-factories:
- com.github.lianjiatech.retrofit.spring.boot.core.BodyCallAdapterFactory
- com.github.lianjiatech.retrofit.spring.boot.core.ResponseCallAdapterFactory

# 全局日志打印配置
global-log:
Expand Down Expand Up @@ -778,52 +775,72 @@ public class SourceGlobalInterceptor implements GlobalInterceptor {
- `Response<T>`: 将响应内容适配成`Response<T>`对象返回!(不推荐)
- `Call<T>`: 不执行适配处理,直接返回`Call<T>`对象!(不推荐)

**响应式编程支持**:

- `Mono<T>`: project-reactor响应式返回类型
- `Single<T>`:rxjava响应式返回类型(支持rxjava2/rxjava3)
- `Completable`:rxjava响应式返回类型,http请求没有响应体(支持rxjava2/rxjava3)


```java
@RetrofitClient(baseUrl = "${test.baseUrl}")
public interface HttpApi {
/**
* 其他任意Java类型
* 将响应体内容适配成一个对应的Java类型对象返回,如果http状态码不是2xx,直接抛错!
* @param id
* @return
*/
@GET("person")
Result<Person> getPerson(@Query("id") Long id);
/**
* 基础类型(`String`/`Long`/`Integer`/`Boolean`/`Float`/`Double`):直接将响应内容转换为上述基础类型。
*/
@POST("getString")
String getString(@Body Person person);

/**
* CompletableFuture<T>
* 将响应体内容适配成CompletableFuture<T>对象返回
* @param id
* @return
*/
@GET("person")
CompletableFuture<Result<Person>> getPersonCompletableFuture(@Query("id") Long id);
/**
* 其它任意POJO类型: 将响应体内容适配成一个对应的POJO类型对象返回,如果http状态码不是2xx,直接抛错!
*/
@GET("person")
Result<Person> getPerson(@Query("id") Long id);

/**
* Void
* 不关注返回类型可以使用Void。如果http状态码不是2xx,直接抛错!
* @param id
* @return
*/
@GET("person")
Void getPersonVoid(@Query("id") Long id);
/**
* `CompletableFuture<T>` :将响应体内容适配成CompletableFuture<T>对象返回,异步调用
*/
@GET("person")
CompletableFuture<Result<Person>> getPersonCompletableFuture(@Query("id") Long id);

/**
* Response<T>
* 将响应内容适配成Response<T>对象返回
* @param id
* @return
*/
@GET("person")
Response<Result<Person>> getPersonResponse(@Query("id") Long id);
/**
* `Void`: 不关注返回类型可以使用`Void`,如果http状态码不是2xx,直接抛错!
*/
@POST("savePerson")
Void savePersonVoid(@Body Person person);

/**
* Call<T>
* 不执行适配处理,直接返回Call<T>对象
* @param id
* @return
*/
@GET("person")
Call<Result<Person>> getPersonCall(@Query("id") Long id);
/**
* `Response<T>`:将响应内容适配成Response<T>对象返回
*/
@GET("person")
Response<Result<Person>> getPersonResponse(@Query("id") Long id);

/**
* `Call<T>`:不执行适配处理,直接返回Call<T>对象
*/
@GET("person")
Call<Result<Person>> getPersonCall(@Query("id") Long id);


/**
* `Mono<T>` : project-reactor响应式返回类型
*/
@GET("person")
Mono<Result<Person>> monoPerson(@Query("id") Long id);

/**
* `Single<T>`:rxjava响应式返回类型(支持rxjava2/rxjava3)
*/
@GET("person")
Single<Result<Person>> singlePerson(@Query("id") Long id);

/**
* `Completable`:rxjava响应式返回类型,http请求没有响应体(支持rxjava2/rxjava3)
*/
@GET("ping")
Completable ping();
}

```

Expand Down
22 changes: 21 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.github.lianjiatech</groupId>
<artifactId>retrofit-spring-boot-starter</artifactId>
<version>2.3.4</version>
<version>2.3.5</version>

<name>retrofit-spring-boot-starter</name>
<description>retrofit-spring-boot-starter</description>
Expand Down Expand Up @@ -172,6 +172,26 @@
<version>1.7.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.3.22.RELEASE</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.reactivex.rxjava3</groupId>
<artifactId>rxjava</artifactId>
<version>3.1.5</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>io.reactivex.rxjava2</groupId>
<artifactId>rxjava</artifactId>
<version>2.2.21</version>
<scope>provided</scope>
</dependency>

</dependencies>

<distributionManagement>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,9 @@
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.lianjiatech.retrofit.spring.boot.core.AutoConfiguredRetrofitScannerRegistrar;
import com.github.lianjiatech.retrofit.spring.boot.core.BasicTypeConverterFactory;
import com.github.lianjiatech.retrofit.spring.boot.core.BodyCallAdapterFactory;
import com.github.lianjiatech.retrofit.spring.boot.core.Constants;
import com.github.lianjiatech.retrofit.spring.boot.core.ErrorDecoder;
import com.github.lianjiatech.retrofit.spring.boot.core.PathMatchInterceptorBdfProcessor;
import com.github.lianjiatech.retrofit.spring.boot.core.ResponseCallAdapterFactory;
import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitFactoryBean;
import com.github.lianjiatech.retrofit.spring.boot.core.ServiceInstanceChooser;
import com.github.lianjiatech.retrofit.spring.boot.core.SourceOkHttpClientRegistrar;
Expand Down Expand Up @@ -70,24 +67,6 @@ public SourceOkHttpClientRegistry sourceOkHttpClientRegistry(
return new SourceOkHttpClientRegistry(sourceOkHttpClientRegistrars);
}

@Bean
@ConditionalOnMissingBean
public BodyCallAdapterFactory bodyCallAdapterFactory() {
return new BodyCallAdapterFactory();
}

@Bean
@ConditionalOnMissingBean
public ResponseCallAdapterFactory responseCallAdapterFactory() {
return new ResponseCallAdapterFactory();
}

@Bean
@ConditionalOnMissingBean
public BasicTypeConverterFactory basicTypeConverterFactory() {
return new BasicTypeConverterFactory();
}

@Bean
@ConditionalOnMissingBean
public ErrorDecoder.DefaultErrorDecoder defaultErrorDecoder() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

import com.github.lianjiatech.retrofit.spring.boot.core.BasicTypeConverterFactory;
import com.github.lianjiatech.retrofit.spring.boot.core.BodyCallAdapterFactory;
import com.github.lianjiatech.retrofit.spring.boot.core.Constants;
import com.github.lianjiatech.retrofit.spring.boot.core.ResponseCallAdapterFactory;
import com.github.lianjiatech.retrofit.spring.boot.degrade.DegradeProperty;
import com.github.lianjiatech.retrofit.spring.boot.log.GlobalLogProperty;
import com.github.lianjiatech.retrofit.spring.boot.retry.GlobalRetryProperty;
Expand Down Expand Up @@ -49,15 +46,13 @@ public class RetrofitProperties {
* global converter factories, The converter instance is first obtained from the Spring container. If it is not obtained, it is created by reflection.
*/
@SuppressWarnings("unchecked")
private Class<? extends Converter.Factory>[] globalConverterFactories = (Class<
? extends Converter.Factory>[])new Class[] {BasicTypeConverterFactory.class, JacksonConverterFactory.class};
private Class<? extends Converter.Factory>[] globalConverterFactories =
(Class<? extends Converter.Factory>[])new Class[] {JacksonConverterFactory.class};

/**
* 全局调用适配器工厂,转换器实例优先从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.
*/
@SuppressWarnings("unchecked")
private Class<? extends CallAdapter.Factory>[] globalCallAdapterFactories =
(Class<? extends CallAdapter.Factory>[])new Class[] {BodyCallAdapterFactory.class,
ResponseCallAdapterFactory.class};
private Class<? extends CallAdapter.Factory>[] globalCallAdapterFactories = new Class[0];
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
Expand All @@ -12,8 +14,11 @@
/**
* @author 陈添明
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class BasicTypeConverterFactory extends Converter.Factory {

public static final BasicTypeConverterFactory INSTANCE = new BasicTypeConverterFactory();

@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations,
Annotation[] methodAnnotations, Retrofit retrofit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

import com.github.lianjiatech.retrofit.spring.boot.exception.RetrofitException;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import okhttp3.Request;
import okhttp3.ResponseBody;
import retrofit2.Call;
Expand All @@ -35,8 +37,11 @@
*
* @author 陈添明
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class BodyCallAdapterFactory extends CallAdapter.Factory {

public static final BodyCallAdapterFactory INSTANCE = new BodyCallAdapterFactory();

@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (Call.class.isAssignableFrom(getRawType(returnType))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

import com.github.lianjiatech.retrofit.spring.boot.exception.RetrofitException;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import okhttp3.Request;
import retrofit2.Call;
import retrofit2.CallAdapter;
Expand All @@ -34,8 +36,11 @@
*
* @author 陈添明
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class ResponseCallAdapterFactory extends CallAdapter.Factory {

public static final ResponseCallAdapterFactory INSTANCE = new ResponseCallAdapterFactory();

@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (Response.class.isAssignableFrom(getRawType(returnType))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
import org.springframework.util.StringUtils;

import com.github.lianjiatech.retrofit.spring.boot.config.RetrofitConfigBean;
import com.github.lianjiatech.retrofit.spring.boot.core.reactive.MonoCallAdapterFactory;
import com.github.lianjiatech.retrofit.spring.boot.core.reactive.Rxjava2CompletableCallAdapterFactory;
import com.github.lianjiatech.retrofit.spring.boot.core.reactive.Rxjava2SingleCallAdapterFactory;
import com.github.lianjiatech.retrofit.spring.boot.core.reactive.Rxjava3CompletableCallAdapterFactory;
import com.github.lianjiatech.retrofit.spring.boot.core.reactive.Rxjava3SingleCallAdapterFactory;
import com.github.lianjiatech.retrofit.spring.boot.degrade.DegradeProxy;
import com.github.lianjiatech.retrofit.spring.boot.degrade.RetrofitDegrade;
import com.github.lianjiatech.retrofit.spring.boot.interceptor.BasePathMatchInterceptor;
Expand Down Expand Up @@ -162,12 +167,58 @@ private Retrofit createRetrofit() {

combineAndCreate(retrofitClient.callAdapterFactories(), retrofitConfigBean.getGlobalCallAdapterFactoryClasses())
.forEach(retrofitBuilder::addCallAdapterFactory);
addReactiveCallAdapterFactory(retrofitBuilder);
retrofitBuilder.addCallAdapterFactory(ResponseCallAdapterFactory.INSTANCE);
retrofitBuilder.addCallAdapterFactory(BodyCallAdapterFactory.INSTANCE);

retrofitBuilder.addConverterFactory(BasicTypeConverterFactory.INSTANCE);
combineAndCreate(retrofitClient.converterFactories(), retrofitConfigBean.getGlobalConverterFactoryClasses())
.forEach(retrofitBuilder::addConverterFactory);

return retrofitBuilder.build();
}

private void addReactiveCallAdapterFactory(Retrofit.Builder retrofitBuilder) {
if (reactor3ClassExist()) {
retrofitBuilder.addCallAdapterFactory(MonoCallAdapterFactory.INSTANCE);
}
if (rxjava2CalssExist()) {
retrofitBuilder.addCallAdapterFactory(Rxjava2SingleCallAdapterFactory.INSTANCE);
retrofitBuilder.addCallAdapterFactory(Rxjava2CompletableCallAdapterFactory.INSTANCE);
}
if (rxjava3ClassExist()) {
retrofitBuilder.addCallAdapterFactory(Rxjava3SingleCallAdapterFactory.INSTANCE);
retrofitBuilder.addCallAdapterFactory(Rxjava3CompletableCallAdapterFactory.INSTANCE);
}
}

private boolean rxjava3ClassExist() {
try {
Class.forName("io.reactivex.rxjava3.core.Single");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}

private boolean rxjava2CalssExist() {
try {
Class.forName("io.reactivex.Single");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}

private boolean reactor3ClassExist() {
try {
Class.forName("reactor.core.publisher.Mono");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}

private <E> List<E> combineAndCreate(Class<? extends E>[] clz, Class<? extends E>[] globalClz) {
if (clz.length == 0 && globalClz.length == 0) {
return Collections.emptyList();
Expand Down
Loading

0 comments on commit c726a3a

Please sign in to comment.