Skip to content

Commit 7c700bf

Browse files
Merge pull request #20 from LianjiaTech/develop
Develop
2 parents acd9206 + 7dfabe4 commit 7c700bf

14 files changed

+344
-45
lines changed

README.md

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
[![Maven central](https://maven-badges.herokuapp.com/maven-central/com.github.lianjiatech/retrofit-spring-boot-starter/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.lianjiatech/retrofit-spring-boot-starter)
77
[![GitHub release](https://img.shields.io/github/v/release/lianjiatech/retrofit-spring-boot-starter.svg)](https://github.com/LianjiaTech/retrofit-spring-boot-starter/releases)
88
[![License](https://img.shields.io/badge/JDK-1.8+-4EB1BA.svg)](https://docs.oracle.com/javase/8/docs/index.html)
9-
[![License](https://img.shields.io/badge/springboot-1.x+-green.svg)](https://docs.spring.io/spring-boot/docs/2.1.5.RELEASE/reference/htmlsingle/)
9+
[![License](https://img.shields.io/badge/SpringBoot-1.x+-green.svg)](https://docs.spring.io/spring-boot/docs/2.1.5.RELEASE/reference/htmlsingle/)
1010
[![Author](https://img.shields.io/badge/Author-chentianming-orange.svg?style=flat-square)](https://juejin.im/user/3562073404738584/posts)
1111
[![QQ-Group](https://img.shields.io/badge/QQ%E7%BE%A4-806714302-orange.svg?style=flat-square) ](https://img.ljcdn.com/hc-picture/HTTP-exception-information-formatter6302d742-ebc8-4649-95cf-62ccf57a1add)
1212

@@ -24,6 +24,7 @@
2424
## Features
2525

2626
- [x] [Custom injection OkHttpClient](#Custom-injection-OkHttpClient)
27+
- [x] [HTTP calls between microservices](#HTTP-calls-between-microservices)
2728
- [x] [Annotation interceptor](#Annotation-interceptor)
2829
- [x] [Connection pool management](#Connection-pool-management)
2930
- [x] [Log printing](#Log-printing)
@@ -41,7 +42,7 @@
4142
<dependency>
4243
<groupId>com.github.lianjiatech</groupId>
4344
<artifactId>retrofit-spring-boot-starter</artifactId>
44-
<version>2.1.3</version>
45+
<version>2.1.4</version>
4546
</dependency>
4647
```
4748

@@ -170,6 +171,36 @@ public interface HttpApi3 {
170171

171172
> The method must be marked with `@OkHttpClientBuilder` annotation!
172173

174+
175+
### HTTP calls between microservices
176+
177+
**By configuring the `serviceId` and `path` properties of `@Retrofit`, HTTP calls between microservices can be realized**.
178+
179+
```java
180+
@RetrofitClient(serviceId = "${jy-helicarrier-api.serviceId}", path = "/m/count", errorDecoder = HelicarrierErrorDecoder.class)
181+
@Retry
182+
public interface ApiCountService {
183+
184+
}
185+
```
186+
187+
Users need to implement the `ServiceInstanceChooser` interface by themselves, complete the selection logic of the service instance, and configure it as the `Bean` of the `Spring` container.
188+
For `Spring Cloud` applications, `retrofit-spring-boot-starter` provides the implementation of `SpringCloudServiceInstanceChooser`.
189+
190+
```java
191+
public interface ServiceInstanceChooser {
192+
193+
/**
194+
* Chooses a ServiceInstance URI from the LoadBalancer for the specified service.
195+
*
196+
* @param serviceId The service ID to look up the LoadBalancer.
197+
* @return Return the uri of ServiceInstance
198+
*/
199+
URI choose(String serviceId);
200+
201+
}
202+
```
203+
173204
### Annotation interceptor
174205

175206
In many cases, we hope that certain http requests in a certain interface execute a unified interception processing logic. So as to support this feature, `retrofit-spring-boot-starter` provide **annotation interceptor** and at the same time achieves **matching interception based on URL path**. The use is mainly divided into 2 steps:

README_CN.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
## 功能特性
2424

2525
- [x] [自定义注入OkHttpClient](#自定义注入OkHttpClient)
26+
- [x] [微服务之间的HTTP调用](#微服务之间的HTTP调用)
2627
- [x] [注解式拦截器](#注解式拦截器)
2728
- [x] [连接池管理](#连接池管理)
2829
- [x] [日志打印](#日志打印)
@@ -40,7 +41,7 @@
4041
<dependency>
4142
<groupId>com.github.lianjiatech</groupId>
4243
<artifactId>retrofit-spring-boot-starter</artifactId>
43-
<version>2.1.3</version>
44+
<version>2.1.4</version>
4445
</dependency>
4546
```
4647

@@ -169,6 +170,35 @@ public interface HttpApi3 {
169170

170171
> 方法必须使用`@OkHttpClientBuilder`注解标记!
171172

173+
### 微服务之间的HTTP调用
174+
175+
**通过配置`@Retrofit`的`serviceId`和`path`属性,可以实现微服务之间的HTTP调用**。比如:
176+
177+
```java
178+
@RetrofitClient(serviceId = "${jy-helicarrier-api.serviceId}", path = "/m/count", errorDecoder = HelicarrierErrorDecoder.class)
179+
@Retry
180+
public interface ApiCountService {
181+
182+
}
183+
```
184+
185+
用户需要自行实现`ServiceInstanceChooser`接口,完成服务实例的选取逻辑,并将其配置成`Spring`容器的`Bean`。对于`Spring Cloud`应用,`retrofit-spring-boot-starter`提供了`SpringCloudServiceInstanceChooser`实现。
186+
187+
```java
188+
public interface ServiceInstanceChooser {
189+
190+
/**
191+
* Chooses a ServiceInstance URI from the LoadBalancer for the specified service.
192+
*
193+
* @param serviceId The service ID to look up the LoadBalancer.
194+
* @return Return the uri of ServiceInstance
195+
*/
196+
URI choose(String serviceId);
197+
198+
}
199+
```
200+
201+
172202
### 注解式拦截器
173203

174204
很多时候,我们希望某个接口下的某些http请求执行统一的拦截处理逻辑。为了支持这个功能,`retrofit-spring-boot-starter`提供了**注解式拦截器**,同时做到了**基于url路径的匹配拦截**。使用的步骤主要分为2步:

pom.xml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.github.lianjiatech</groupId>
88
<artifactId>retrofit-spring-boot-starter</artifactId>
9-
<version>2.1.3</version>
9+
<version>2.1.4</version>
1010

1111
<name>retrofit-spring-boot-starter</name>
1212
<description>retrofit-spring-boot-starter</description>
@@ -48,6 +48,13 @@
4848
</properties>
4949

5050
<dependencies>
51+
<dependency>
52+
<groupId>org.springframework.cloud</groupId>
53+
<artifactId>spring-cloud-commons</artifactId>
54+
<version>2.1.6.RELEASE</version>
55+
<scope>provided</scope>
56+
</dependency>
57+
5158
<dependency>
5259
<groupId>org.springframework.boot</groupId>
5360
<artifactId>spring-boot-autoconfigure</artifactId>

src/main/java/com/github/lianjiatech/retrofit/spring/boot/annotation/RetrofitClient.java

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import com.github.lianjiatech.retrofit.spring.boot.core.DefaultErrorDecoder;
44
import com.github.lianjiatech.retrofit.spring.boot.core.ErrorDecoder;
5-
import com.github.lianjiatech.retrofit.spring.boot.interceptor.BaseLoggingInterceptor;
5+
import com.github.lianjiatech.retrofit.spring.boot.interceptor.LogStrategy;
66
import org.slf4j.event.Level;
77
import retrofit2.Retrofit;
88

@@ -17,13 +17,29 @@
1717
public @interface RetrofitClient {
1818

1919
/**
20-
* 基础url, 支持占位符形式配置。
21-
* baseUrl, Supports placeholder configuration.
22-
* http://${baseUrl.test}
20+
* 绝对URL(协议是必需的)。
21+
* 可以指定为属性键,例如:$ {propertyKey}。
22+
* 如果baseUrl没有配置,则必须配置serviceId以及,path可选配置。
23+
*
24+
* An absolute URL (the protocol is necessary).
25+
* Can be specified as property key, eg: ${propertyKey}.
26+
* If baseUrl is not configured, you must configure serviceId and path optional configuration.
27+
*
2328
*
2429
* @return baseUrl
2530
*/
26-
String baseUrl();
31+
String baseUrl() default "";
32+
33+
/**
34+
* The name of the service.
35+
* Can be specified as property key, eg: ${propertyKey}.
36+
*/
37+
String serviceId() default "";
38+
39+
/**
40+
* Path prefix to be used by all method-level mappings.
41+
*/
42+
String path() default "";
2743

2844
/**
2945
* When calling {@link Retrofit#create(Class)} on the resulting {@link Retrofit} instance, eagerly validate the
@@ -136,10 +152,10 @@
136152
Level logLevel() default Level.INFO;
137153

138154
/**
139-
* 日志打印策略,支持的日志打印策略参见{@link BaseLoggingInterceptor.LogStrategy}
140-
* Log printing strategy, see {@link BaseLoggingInterceptor.LogStrategy} for supported log printing strategies
155+
* 日志打印策略,支持的日志打印策略参见{@link LogStrategy}
156+
* Log printing strategy, see {@link LogStrategy} for supported log printing strategies
141157
*
142158
* @return logStrategy
143159
*/
144-
BaseLoggingInterceptor.LogStrategy logStrategy() default BaseLoggingInterceptor.LogStrategy.BASIC;
160+
LogStrategy logStrategy() default LogStrategy.BASIC;
145161
}

src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/RetrofitAutoConfiguration.java

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,22 @@
33
import com.fasterxml.jackson.annotation.JsonInclude;
44
import com.fasterxml.jackson.databind.DeserializationFeature;
55
import com.fasterxml.jackson.databind.ObjectMapper;
6-
import com.github.lianjiatech.retrofit.spring.boot.core.BodyCallAdapterFactory;
7-
import com.github.lianjiatech.retrofit.spring.boot.core.PrototypeInterceptorBdfProcessor;
8-
import com.github.lianjiatech.retrofit.spring.boot.core.ResponseCallAdapterFactory;
6+
import com.github.lianjiatech.retrofit.spring.boot.core.*;
97
import com.github.lianjiatech.retrofit.spring.boot.interceptor.BaseGlobalInterceptor;
108
import com.github.lianjiatech.retrofit.spring.boot.interceptor.NetworkInterceptor;
9+
import com.github.lianjiatech.retrofit.spring.boot.interceptor.ServiceInstanceChooserInterceptor;
1110
import com.github.lianjiatech.retrofit.spring.boot.retry.BaseRetryInterceptor;
1211
import okhttp3.ConnectionPool;
1312
import org.springframework.beans.BeansException;
1413
import org.springframework.beans.factory.annotation.Autowired;
1514
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
15+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
16+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
1617
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
1718
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
1819
import org.springframework.boot.context.properties.EnableConfigurationProperties;
20+
import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
21+
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
1922
import org.springframework.context.ApplicationContext;
2023
import org.springframework.context.ApplicationContextAware;
2124
import org.springframework.context.annotation.Bean;
@@ -37,7 +40,7 @@
3740
*/
3841
@Configuration
3942
@EnableConfigurationProperties(RetrofitProperties.class)
40-
@AutoConfigureAfter(JacksonAutoConfiguration.class)
43+
@AutoConfigureAfter({JacksonAutoConfiguration.class, LoadBalancerAutoConfiguration.class})
4144
public class RetrofitAutoConfiguration implements ApplicationContextAware {
4245

4346
@Autowired
@@ -56,7 +59,8 @@ public static PrototypeInterceptorBdfProcessor prototypeInterceptorBdfProcessor(
5659

5760
@Bean
5861
@ConditionalOnMissingBean
59-
public RetrofitConfigBean retrofitConfigBean(@Autowired ObjectMapper objectMapper) throws IllegalAccessException, InstantiationException {
62+
@Autowired
63+
public RetrofitConfigBean retrofitConfigBean(ObjectMapper objectMapper) throws IllegalAccessException, InstantiationException {
6064
RetrofitConfigBean retrofitConfigBean = new RetrofitConfigBean(retrofitProperties);
6165
// Initialize the connection pool
6266
Map<String, ConnectionPool> poolRegistry = new ConcurrentHashMap<>(4);
@@ -106,6 +110,17 @@ public RetrofitConfigBean retrofitConfigBean(@Autowired ObjectMapper objectMappe
106110
Collection<NetworkInterceptor> networkInterceptors = getBeans(NetworkInterceptor.class);
107111
retrofitConfigBean.setNetworkInterceptors(networkInterceptors);
108112

113+
// add ServiceInstanceChooserInterceptor
114+
ServiceInstanceChooser serviceInstanceChooser;
115+
try {
116+
serviceInstanceChooser = applicationContext.getBean(ServiceInstanceChooser.class);
117+
} catch (BeansException e) {
118+
serviceInstanceChooser = new NoValidServiceInstanceChooser();
119+
}
120+
121+
ServiceInstanceChooserInterceptor serviceInstanceChooserInterceptor = new ServiceInstanceChooserInterceptor(serviceInstanceChooser);
122+
retrofitConfigBean.setServiceInstanceChooserInterceptor(serviceInstanceChooserInterceptor);
123+
109124
return retrofitConfigBean;
110125
}
111126

@@ -117,6 +132,16 @@ public ObjectMapper jacksonObjectMapper() {
117132
.setSerializationInclusion(JsonInclude.Include.NON_NULL);
118133
}
119134

135+
@Bean
136+
@ConditionalOnMissingBean
137+
@ConditionalOnClass(LoadBalancerClient.class)
138+
@ConditionalOnBean(LoadBalancerClient.class)
139+
@Autowired
140+
public ServiceInstanceChooser serviceInstanceChooser(LoadBalancerClient loadBalancerClient) {
141+
return new SpringCloudServiceInstanceChooser(loadBalancerClient);
142+
}
143+
144+
120145
private <U> Collection<U> getBeans(Class<U> clz) {
121146
try {
122147
Map<String, U> beanMap = applicationContext.getBeansOfType(clz);

src/main/java/com/github/lianjiatech/retrofit/spring/boot/config/RetrofitConfigBean.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.github.lianjiatech.retrofit.spring.boot.interceptor.BaseGlobalInterceptor;
44
import com.github.lianjiatech.retrofit.spring.boot.interceptor.NetworkInterceptor;
5+
import com.github.lianjiatech.retrofit.spring.boot.interceptor.ServiceInstanceChooserInterceptor;
56
import com.github.lianjiatech.retrofit.spring.boot.retry.BaseRetryInterceptor;
67
import okhttp3.ConnectionPool;
78
import retrofit2.CallAdapter;
@@ -30,6 +31,8 @@ public class RetrofitConfigBean {
3031

3132
private BaseRetryInterceptor retryInterceptor;
3233

34+
private ServiceInstanceChooserInterceptor serviceInstanceChooserInterceptor;
35+
3336
public RetrofitProperties getRetrofitProperties() {
3437
return retrofitProperties;
3538
}
@@ -87,4 +90,12 @@ public Collection<NetworkInterceptor> getNetworkInterceptors() {
8790
public void setNetworkInterceptors(Collection<NetworkInterceptor> networkInterceptors) {
8891
this.networkInterceptors = networkInterceptors;
8992
}
93+
94+
public ServiceInstanceChooserInterceptor getServiceInstanceChooserInterceptor() {
95+
return serviceInstanceChooserInterceptor;
96+
}
97+
98+
public void setServiceInstanceChooserInterceptor(ServiceInstanceChooserInterceptor serviceInstanceChooserInterceptor) {
99+
this.serviceInstanceChooserInterceptor = serviceInstanceChooserInterceptor;
100+
}
90101
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.github.lianjiatech.retrofit.spring.boot.core;
2+
3+
import com.github.lianjiatech.retrofit.spring.boot.exception.ServiceInstanceChooseException;
4+
5+
import java.net.URI;
6+
7+
/**
8+
* @author 陈添明
9+
*/
10+
public class NoValidServiceInstanceChooser implements ServiceInstanceChooser {
11+
12+
13+
/**
14+
* Chooses a ServiceInstance URI from the LoadBalancer for the specified service.
15+
*
16+
* @param serviceId The service ID to look up the LoadBalancer.
17+
* @return Return the uri of ServiceInstance
18+
*/
19+
@Override
20+
public URI choose(String serviceId) {
21+
throw new ServiceInstanceChooseException("No valid service instance selector, Please configure it!");
22+
}
23+
}

0 commit comments

Comments
 (0)