okhttpがsquarecompanyによってオープンソース化されたhttpクライアントツールのJavaバージョンであることは誰もが知っています。実際、squareはokhttpに基づくレトロフィットツールをオープンソース化して、インターフェースを介したhttpリクエストの開始をサポートするためにさらにカプセル化しました。プロジェクトでまだRestTemplateまたはokhttpを直接使用している場合、またはそれらに基づくHttpUtilsを使用している場合は、Retrofitを試すことができます。
retrofit-spring-boot-starterは、Retrofitとspring-bootフレームワークの迅速な統合を実現し、いくつかの機能拡張をサポートします。これにより、spring-bootプロジェクトでのhttpインターフェース呼び出しの開発が大幅に簡素化されます。次に、retrofit-spring-boot-starterを直接使用して、httpリクエストをspring-bootプロジェクトに送信するのがいかに簡単かを確認します。
Retrofitは、Spring-Bootとの迅速な統合のためのスターターを公式には提供していません。Retrofit-spring-boot-starterは作成者によってパッケージ化されており、実稼働環境で使用されており、非常に安定しています。
プロジェクトのソースコード:retrofit-spring-boot-starter
が依存関係を導入
<dependency>
<groupId>com.github.lianjiatech</groupId>
<artifactId>retrofit-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>
@RetrofitScanアノテーションを構成する
次のように、@ Configurationを使用してクラスの@RetrofitScanを構成するか、Spring-Bootスタートアップクラスに直接構成することができます。
@SpringBootApplication
@RetrofitScan("com.github.lianjiatech.retrofit.spring.boot.test")
public class RetrofitTestApplication {
public static void main(String[] args) {
SpringApplication.run(RetrofitTestApplication.class, args);
}
}
httpインターフェースを定義する
インターフェイスは@RetrofitClientアノテーションでマークする必要があります!http関連のソリューションは、公式ドキュメントを参照できます:レトロフィット公式ドキュメント。
@RetrofitClient(baseUrl = "${test.baseUrl}")
public interface HttpApi {
@GET("person")
Result<Person> getPerson(@Query("id") Long id);
}
注射の使用
インターフェイスを他のサービスに挿入することで使用できます。
@Service
public class TestService {
@Autowired
private HttpApi httpApi;
public void test() {
// 通过httpApi发起http请求
}
}
上記の手順を実行している限り、インターフェースを介してhttpリクエストを送信できます。これは非常に簡単です。Spring-Bootプロジェクトでmybatisを使用したことがある場合は、この使用方法に慣れていると思います。次に、retrofit-spring-boot-starterのより高度な機能を引き続き紹介します。
注釈付きインターセプター
多くの場合、特定のインターフェイスでの特定のhttpリクエストが、統合されたインターセプト処理ロジックを実行することを期待しています。現時点では、注釈付きインターセプターを使用できます。使用される手順は、主に2つの手順に分けられます。
BasePathMatchInterceptorを継承してインターセプトプロセッサを作成
します。@ Interceptを使用してインターフェイスをマークします。
以下は、アノテーションインターセプターの使用方法を紹介するために、指定されたリクエストのURLの後にタイムスタンプをスプライシングする例です。
BasePathMatchInterceptorを継承して、インターセプトプロセッサを作成します
@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);
}
}
@Interceptを使用してインターフェースをマークします
@RetrofitClient(baseUrl = "${test.baseUrl}")
@Intercept(handler = TimeStampInterceptor.class, include = {
"/api/**"}, exclude = "/api/test/savePerson")
public interface HttpApi {
@GET("person")
Result<Person> getPerson(@Query("id") Long id);
@POST("savePerson")
Result<Person> savePerson(@Body Person person);
}
上記の@Intercept構成とは、HttpApiインターフェースの/ api / **パス(/ api / test / savePersonを除く)でリクエストをインターセプトし、インターセプトプロセッサーがTimeStampInterceptorを使用することを意味します。
拡張アノテーションインターセプター
場合によっては、インターセプトアノテーションでいくつかのパラメーターを動的に渡す必要があり、インターセプトを実行するときにこのパラメーターを使用する必要があります。現時点では、カスタムインターセプトアノテーションの実装を拡張できます。カスタムインターセプトアノテーションは@InterceptMarkマークを使用する必要があり、アノテーションにはinclude()、exclude()、handler()属性情報を含める必要があります。使用される手順は、主に3つの手順に分けられます。
カスタムインターセプトアノテーションは
BasePathMatchInterceptorを継承して、インターセプトプロセッサ
インターフェイスを記述し、カスタムインターセプトアノテーションを使用します。
たとえば、httpリクエストを正常に開始するには、リクエストヘッダーにaccessKeyIdおよびaccessKeySecret署名情報を動的に追加する必要があります。現時点では、シグネチャインターセプターアノテーションをカスタマイズできます。 @達成するための署名。以下は、カスタム@Signインターセプトアノテーションの例です。
カスタム@Signアノテーション
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@InterceptMark
public @interface Sign {
/**
* 密钥key
* 支持占位符形式配置。
*
* @return
*/
String accessKeyId();
/**
* 密钥
* 支持占位符形式配置。
*
* @return
*/
String accessKeySecret();
/**
* 拦截器匹配路径
*
* @return
*/
String[] include() default {
"/**"};
/**
* 拦截器排除匹配,排除指定路径拦截
*
* @return
*/
String[] exclude() default {
};
/**
* 处理该注解的拦截器类
* 优先从spring容器获取对应的Bean,如果获取不到,则使用反射创建一个!
*
* @return
*/
Class<? extends BasePathMatchInterceptor> handler() default SignInterceptor.class;
}
カスタムインターセプトアノテーションを拡張する場合は、次の2つの点に注意する必要があります。
カスタムインターセプトアノテーションは@InterceptMarkでマークする必要があります。
アノテーションには、include()、exclude()、handler()属性情報を含める必要があります。
SignInterceptorを実装する
@Component
public class SignInterceptor extends BasePathMatchInterceptor {
private String accessKeyId;
private String accessKeySecret;
public void setAccessKeyId(String accessKeyId) {
this.accessKeyId = accessKeyId;
}
public void setAccessKeySecret(String accessKeySecret) {
this.accessKeySecret = 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);
}
}
上記のaccessKeyIdおよびaccessKeySecretフィールド値は、@ Signアノテーションが付けられたaccessKeyId()およびaccessKeySecret()値に従って自動的に挿入されます。@ Signがプレースホルダーの形式で文字列を指定する場合、構成属性値は次のようになります。注射に使用されます。さらに、accessKeyIdフィールドとaccessKeySecretフィールドは、setterメソッドを提供する必要があります。
インターフェイスで@Signを使用します
@RetrofitClient(baseUrl = "${test.baseUrl}")
@Sign(accessKeyId = "${test.accessKeyId}", accessKeySecret = "${test.accessKeySecret}", exclude = {
"/api/test/person"})
public interface HttpApi {
@GET("person")
Result<Person> getPerson(@Query("id") Long id);
@POST("savePerson")
Result<Person> savePerson(@Body Person person);
}
このようにして、指定されたURLのリクエストに署名情報を自動的に追加できます。
接続プール管理
デフォルトでは、Retrofitを介して送信されるすべてのhttpリクエストは、max-idle-connections = 5 keep-alive-second = 300のデフォルトの接続プールを使用します。もちろん、構成ファイルで複数のカスタム接続プールを構成し、@ RetrofitClientのpoolNameプロパティを使用して使用を指定することもできます。たとえば、特定のインターフェイスですべてのリクエストをpoolName = test1の接続プールを使用させたい場合、コードの実装は次のようになります。
1.接続プールを構成します。
retrofit:
# 连接池配置
pool:
test1:
max-idle-connections: 3
keep-alive-second: 100
test2:
max-idle-connections: 5
keep-alive-second: 50
2. @ RetrofitClientのpoolNameプロパティを介して使用する接続プールを指定します。
@RetrofitClient(baseUrl = "${test.baseUrl}", poolName="test1")
public interface HttpApi {
@GET("person")
Result<Person> getPerson(@Query("id") Long id);
}
ログ印刷
多くの場合、httpリクエストログを記録する必要があります。@RetrofitClientのlogLevel属性とlogStrategy属性を使用して、各インターフェイスのログ印刷レベルとログ印刷戦略を指定できます。retrofit-spring-boot-starterは、5つのログ印刷レベル(ERROR、WARN、INFO、DEBUG、TRACE)、デフォルトのINFOをサポートし、4つのログ印刷戦略(NONE、BASIC、HEADERS、BODY)、デフォルトのBASICをサポートします。4つのログ印刷戦略の意味は次のとおりです。
NONE:ログなし
BASIC:要求行と応答行をログに記録します
HEADERS:要求行と応答行とそれぞれのヘッダーを
ログに記録しますBODY:要求行と応答行とそれぞれのヘッダーと本文(存在する場合)をログに記録します
retrofit-spring-boot-starterデフォルトでは、DefaultLoggingInterceptorを使用して実際のログ印刷機能を実行し、最下層はokhttpのネイティブHttpLoggingInterceptorです。もちろん、独自のログ印刷インターセプターをカスタマイズすることもできます。BaseLoggingInterceptorを継承するだけで(詳細については、DefaultLoggingInterceptorの実装を参照してください)、構成ファイルで構成します。
retrofit:
# 日志打印拦截器
logging-interceptor: com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultLoggingInterceptor
Http例外情報フォーマッタ
HTTP要求例外が発生すると、元の例外情報が読みにくくなる可能性があります。したがって、retrofit-spring-boot-starterは、http要求パラメーターの出力を美化するためのHttp例外情報フォーマッターを提供します。DefaultHttpExceptionMessageFormatterはデフォルトでリクエストデータフォーマット化。また、カスタマイズして、BaseHttpExceptionMessageFormatterを継承し、構成することもできます。
retrofit:
# Http异常信息格式化器
http-exception-message-formatter: com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultHttpExceptionMessageFormatter
コールアダプタCallAdapter
Retrofitは、アダプタCallAdapterFactoryを呼び出すことにより、Callオブジェクトをインターフェイスメソッドの戻り値タイプに適合させることができます。Retrofit-spring-boot-starterは、2つのCallAdapterFactory実装を拡張します。
BodyCallAdapterFactory
これはデフォルトで有効になっており、retrofit.enable-body-call-adapter = falseを構成
してhttp要求を同期的に実行し、応答本文の内容をインターフェイスメソッドの戻り値タイプのインスタンスに適合させることで無効にできます。
Retrofit.Call、Retrofit.Response、java.util.concurrent.CompletableFutureを除いて、他の戻り値の型はこのアダプターを使用できます。
ResponseCallAdapterFactory
これはデフォルトで有効になっており、retrofit.enable-response-call-adapter = falseを構成
してhttp要求を同期的に実行し、応答本文の内容をRetrofit.Responseに適合させて返すことで無効にできます。
メソッドの戻り値の型がRetrofit.Responseの場合、このアダプターを使用できます。
Retrofitは、対応するCallAdapterFactoryを自動的に選択して、メソッドの戻り値のタイプに従って適応処理を実行します。RetrofitのデフォルトのCallAdapterFactoryに加えて、さまざまなタイプのメソッドの戻り値をサポートできます。
Call:適応処理は実行されず、Callオブジェクトが直接返されます
。CompletableFuture:応答本文のコンテンツがCompletableFutureオブジェクトに適応されます。ReturnVoid
:戻り値の型に関係なくVoidを使用できます。httpステータスコードが2xxでない場合は、エラーをスローしてください。
応答:応答コンテンツを応答オブジェクトに
適合させ、他のJavaタイプを返します:応答本文コンテンツを対応するJavaタイプオブジェクトに適合させて返します。httpステータスコードが2xxでない場合は、エラーをスローします。
/**
* Call<T>
* 不执行适配处理,直接返回Call<T>对象
* @param id
* @return
*/
@GET("person")
Call<Result<Person>> getPersonCall(@Query("id") Long id);
/**
* CompletableFuture<T>
* 将响应体内容适配成CompletableFuture<T>对象返回
* @param id
* @return
*/
@GET("person")
CompletableFuture<Result<Person>> getPersonCompletableFuture(@Query("id") Long id);
/**
* Void
* 不关注返回类型可以使用Void。如果http状态码不是2xx,直接抛错!
* @param id
* @return
*/
@GET("person")
Void getPersonVoid(@Query("id") Long id);
/**
* Response<T>
* 将响应内容适配成Response<T>对象返回
* @param id
* @return
*/
@GET("person")
Response<Result<Person>> getPersonResponse(@Query("id") Long id);
/**
* 其他任意Java类型
* 将响应体内容适配成一个对应的Java类型对象返回,如果http状态码不是2xx,直接抛错!
* @param id
* @return
*/
@GET("person")
Result<Person> getPerson(@Query("id") Long id);
CallAdapter.Factoryを拡張して独自のCallAdapterを実装することもできます。次に、カスタムCallAdapterFactoryをSpringBeanとして構成します。
カスタム構成のCallAdapter.Factoryの優先度が高くなります。
データトランスコーダーコンバーター
Retrofiは、Converterを使用して、@ Bodyでアノテーションが付けられたオブジェクトを要求本文に変換し、応答本文データをJavaオブジェクトに変換します。次のコンバーターを使用できます。
Gson:com.squareup.Retrofit:converter-gson
Jackson:com.squareup.Retrofit:converter-jackson
Moshi:com.squareup.Retrofit:converter-
moshi Protobuf:com.squareup.Retrofit:converter-protobuf
Wire:com.squareup。
Retrofit :converter-wire単純なXML:com.squareup.Retrofit:converter-simplexml
retrofit-spring-boot-starterは、デフォルトでシリアル化変換にjacksonを使用します。他のシリアル化方法を使用する必要がある場合は、プロジェクトに対応する依存関係を導入してから、対応するConverterFactoryをSpringBeanとして構成します。
Converter.Factoryを拡張して独自のConverterを実装することもできます。次に、カスタムConverter.FactoryをSpringBeanとして構成します。
カスタム構成されたConverter.Factoryの優先度が高くなります。
BaseGlobalInterceptor
システム全体のhttpリクエストに対して統合インターセプト処理を実行する必要がある場合は、グローバルインターセプターBaseGlobalInterceptorの実装をカスタマイズして、春にBeanとして構成できます。たとえば、システム全体で開始されたすべてのhttpリクエストのソース情報を提供する必要があります。
@Component
public class SourceInterceptor extends BaseGlobalInterceptor {
@Override
public Response doIntercept(Chain chain) throws IOException {
Request request = chain.request();
Request newReq = request.newBuilder()
.addHeader("source", "test")
.build();
return chain.proceed(newReq);
}
}