干掉 Feign ,Spring Cloud Square 組件發(fā)布
Spring Cloud Square 是什么
談起 Spring Cloud 生態(tài)大家一定對(duì) Feign 不陌生,如下圖所示,F(xiàn)eign 可以把底層(okhttp、httpclient)Rest 的請(qǐng)求進(jìn)行隱藏,偽裝成類似 SpringMVC 的 Controller 一樣。你不用再自己拼接 url,拼接參數(shù)等等操作,一切都交給 Feign 去做。使用 Feign 調(diào)用 API 就像調(diào)用本地方法一樣,從避免了調(diào)用目標(biāo)微服務(wù)時(shí),需要不斷的解析/封裝 json 數(shù)據(jù)的繁瑣。

Spring Cloud Square 項(xiàng)目旨在替代原有的 Spring Cloud Feign , 借助 Retrofit 對(duì)底層通信類庫(kù)的封裝實(shí)現(xiàn)跨服務(wù)調(diào)用,目前已在 spring-cloud-incubator 孵化器進(jìn)行孵化 (上一個(gè)在孵化器孵化 spring-cloud-loadbalancer 已經(jīng)正式接替 Ribbon 成為正式推薦組件)。
在了解 Spring Cloud Square 之前,需要先了解以下組件:
OkHttp 是一個(gè)關(guān)于網(wǎng)絡(luò)請(qǐng)求的第三方類庫(kù),其中封裝了網(wǎng)絡(luò)請(qǐng)求的 get、post 等操作的底層實(shí)現(xiàn),是目前最為火熱的網(wǎng)絡(luò)請(qǐng)求框架之一。
Retrofit 是一個(gè) RESTful 的 HTTP 網(wǎng)絡(luò)請(qǐng)求框架,它是基于 OkHttp 的。它是通過(guò)注解配置網(wǎng)絡(luò)參數(shù)的,支持多種數(shù)據(jù)的解析和序列化(Gson、Json、Xml 等,并且對(duì) RxJava 也是支持的。
那么基于 Spring Cloud Square 的服務(wù)調(diào)用可以抽象成如下圖所示:

快速上手

添加依賴
由于目前 spring-cloud-square 未正式發(fā)布,需要配置 spring maven 倉(cāng)庫(kù)。
<repositories>
<repository>
<id>spring-milestones</id>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
maven 依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-square-okhttp</artifactId>
<version>${square.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttp.version}</version>
</dependency>
<!--添加負(fù)載均衡支持-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
代碼配置
@Bean
@LoadBalanced
public OkHttpClient.Builder okHttpClientBuilder() {
return new OkHttpClient.Builder();
}
代碼調(diào)用
和最早的 ribbon 調(diào)用一樣,非常的簡(jiǎn)單。
@Autowired
OkHttpClient.Builder builder;
@GetMapping
public String req() {
Request request = new Request.Builder()
.url("http://square-provider/req").build();
Response response = builder.build().newCall(request).execute();
return response.body().string();
}
進(jìn)階使用
作為 Spring Cloud Feign 的替代品,square 也支持聲明式客戶端的形式。注意看以下代碼 和 feign 一樣的味道
添加依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-square-retrofit</artifactId>
<version>${square.version}</version>
</dependency>
聲明調(diào)用客戶端
@RetrofitClient("square-provider")
public interface DemoService {
@GET("/req")
Call<String> req();
}
開(kāi)啟客戶端掃描
@EnableRetrofitClients
代碼調(diào)用
@Autowired
DemoService demoService;
@SneakyThrows
@GetMapping("/retrofit")
public String retrofit(){
return demoService.req().execute().body();
}
簡(jiǎn)化一下
Retrofit 我們可以添加擴(kuò)展來(lái)處理結(jié)果(代碼由春哥提供):
/**
* 原始類型返回的 處理器,去掉默認(rèn)的 Call
*
* @author L.cm
*/
@Configuration(proxyBeanMethods = false)
public class ApiCallAdapterFactory extends CallAdapter.Factory {
@Override
public CallAdapter<?, ?> get(@Nonnull Type returnType,
@Nonnull Annotation[] annotations,
@Nonnull Retrofit retrofit) {
return new CallAdapter<>() {
@Override
public Type responseType() {
return returnType;
}
@Override
public Object adapt(@Nonnull Call<Object> call) {
try {
return call.execute().body();
} catch (IOException e) {
// 自定義fallback、或者直接拋出給全局異常處理
return null;
}
}
};
}
}
然后我們上面的代碼就可以簡(jiǎn)化成這樣啦:
@RetrofitClient("square-provider")
public interface DemoService {
@GET("/req")
String req();
}
@Autowired
DemoService demoService;
@SneakyThrows
@GetMapping("/retrofit")
public String retrofit(){
return demoService.req();
}
總結(jié)
由于 spring-cloud-square 直接基于 retrofit 實(shí)現(xiàn),整體源碼非常的簡(jiǎn)單,推薦大家一讀。
目前版本暫未實(shí)現(xiàn) fallback 相關(guān)的實(shí)現(xiàn)。
本文的配套代碼 https://github.com/lltx/spring-cloud-square-demo
