Java学习之RPC常用工具Retrofit使用样例
Retrofit简介
-
概念
Retrofit是Square开源的一款基于OkHttp封装的网络请求框架,主要的网络请求还是OkHttp来完成,Retrofit只是对OkHttp进行了封装。
Retrofit实战
-
使用步骤
- 添加Retrofit库的依赖
- 创建 接收服务器返回数据 的类
- 创建 用于描述网络请求 的接口
- 创建 Retrofit 实例
- 创建 网络请求接口实例 并 配置网络请求参数
- 发送网络请求(封装了 数据转换、线程切换的操作)
- 处理服务器返回的数据
添加依赖
-
pom
<dependency> <groupId>com.squareup.retrofit2</groupId> <artifactId>retrofit</artifactId> <version>2.5.0</version> </dependency> <!-- 返回数据转换器依赖(例如的是String 就需要 scalar,如果是 json,需要使用 gson 等) --> <dependency> <groupId>com.squareup.retrofit2</groupId> <artifactId>converter-scalars</artifactId> <version>2.5.0</version> <scope>test</scope> </dependency> <!-- RxJava 其实和 Retrofit关系不大,流式编程的思想,丰富的操作符,线程的任意切换等优点 --> <dependency> <groupId>com.squareup.retrofit2</groupId> <artifactId>adapter-rxjava2</artifactId> <version>2.3.0</version> <scope>test</scope> </dependency>
创建 用于描述网络请求 的接口
-
内容介绍
Retrofit将 Http请求 抽象成 Java接口:采用 注解 描述网络请求参数 和 配置网络请求参数。
-
流程说明
用 动态代理 动态 将该接口的注解“翻译”成一个 Http 请求,最后再执行 Http 请求
注:接口中的每个方法的参数都需要使用注解标注,否则会报错。
-
案例源码
import io.reactivex.Single; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.http.GET; public interface RetrofitService { // @GET注解的作用:采用Get方法发送网络请求 // greeting() = 接收网络请求数据的方法 // 其中返回类型为Call<*>,*是接收数据的类 @GET("greeting") Call<String> greeting(); @GET("delegated") Single<String> delegated(); // 如果想直接获得Responsebody中的内容,可以定义网络请求返回值为Call<ResponseBody> @GET("greetingsResponse") Call<ResponseBody> greetingsResponse(); @GET("robot/index") Call<String> getString(@Query("info") String info, @Query("key") String key); }
创建 Retrofit 实例
-
案例源码
final long TIMEOUT = 1500; // ms OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS) .readTimeout(TIMEOUT, TimeUnit.MILLISECONDS) .writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS) .build(); Retrofit retrofit = new Retrofit.Builder() .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支持RxJava平台 .addConverterFactory(ScalarsConverterFactory.create()) // 设置数据解析器 .baseUrl("http://op.juhe.cn/") // 设置网络请求的Url地址 .client(client) .build();
创建 网络请求接口实例
-
案例源码
// 创建 网络请求接口 的实例 RetrofitService service = retrofit.create(RetrofitService.class); //对 发送请求 进行封装 Call<String> call = service.getString("你好", "2833a660902644508778b5dfd452c080");
发送网络请求(异步/同步)
-
案例源码
//发送网络请求(异步) call.enqueue(new Callback<String>() { //请求成功时回调 @Override public void onResponse(Call<String> call, Response<String> response) { //请求处理,输出结果 response.body().show(); } //请求失败时候的回调 @Override public void onFailure(Call<String> call, Throwable throwable) { System.out.println("连接失败"); } }); // 发送网络请求(同步) Response<String> response = call.execute();
处理返回数据
-
案例源码
// 对返回数据进行处理 response.body().show();
Retrofit进阶
-
内容介绍
熔断器适配Retrofit,添加熔断功能。
DecoratedCall
-
内容介绍
用于实现并装饰Retrofit的Call接口
-
案例源码
import java.io.IOException; import okhttp3.Request; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; /** * Simple decorator class that implements Call<T> and delegates all calls the the Call * instance provided in the constructor. Methods can be overridden as required. * * @param <T> Call parameter type */ public abstract class DecoratedCall<T> implements Call<T> { private final Call<T> call; public DecoratedCall(Call<T> call) { this.call = call; } @Override public Response<T> execute() throws IOException { return this.call.execute(); } @Override public void enqueue(Callback<T> callback) { call.enqueue(callback); } @Override public boolean isExecuted() { return call.isExecuted(); } @Override public void cancel() { call.cancel(); } @Override public boolean isCanceled() { return call.isCanceled(); } @Override public abstract Call<T> clone(); @Override public Request request() { return call.request(); } }
RetrofitCircuitBreaker
-
内容介绍
用于装饰改造Retrofit的Call,并在发生异常时通知熔断器
-
案例源码
import io.github.resilience4j.circuitbreaker.CallNotPermittedException; import io.github.resilience4j.circuitbreaker.CircuitBreaker; import io.github.resilience4j.core.StopWatch; import io.github.resilience4j.retrofit.internal.DecoratedCall; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import java.io.IOException; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; /** * Decorates a Retrofit {@link Call} to inform a {@link CircuitBreaker} when an exception is thrown. * All exceptions are marked as errors or responses not matching the supplied predicate. For * example: * <p> * <code> * RetrofitCircuitBreaker.decorateCall(circuitBreaker, call, Response::isSuccessful); * </code> */ public interface RetrofitCircuitBreaker { /** * Decorate {@link Call}s allow {@link CircuitBreaker} functionality. * * @param circuitBreaker {@link CircuitBreaker} to apply * @param call Call to decorate * @param responseSuccess determines whether the response should be considered an expected * response * @param <T> Response type of call * @return Original Call decorated with CircuitBreaker */ static <T> Call<T> decorateCall(final CircuitBreaker circuitBreaker, final Call<T> call, final Predicate<Response> responseSuccess) { return new CircuitBreakingCall<>(call, circuitBreaker, responseSuccess); } class CircuitBreakingCall<T> extends DecoratedCall<T> { private final Call<T> call; private final CircuitBreaker circuitBreaker; private final Predicate<Response> responseSuccess; public CircuitBreakingCall(Call<T> call, CircuitBreaker circuitBreaker, Predicate<Response> responseSuccess) { super(call); this.call = call; this.circuitBreaker = circuitBreaker; this.responseSuccess = responseSuccess; } @Override public void enqueue(final Callback<T> callback) { try { circuitBreaker.acquirePermission(); } catch (CallNotPermittedException cb) { callback.onFailure(call, cb); return; } final long start = System.nanoTime(); call.enqueue(new Callback<T>() { @Override public void onResponse(final Call<T> call, final Response<T> response) { if (responseSuccess.test(response)) { circuitBreaker.onResult(System.nanoTime() - start, TimeUnit.NANOSECONDS, response); } else { final Throwable throwable = new Throwable( "Response error: HTTP " + response.code() + " - " + response.message()); circuitBreaker .onError(System.nanoTime() - start, TimeUnit.NANOSECONDS, throwable); } callback.onResponse(call, response); } @Override public void onFailure(final Call<T> call, final Throwable t) { if (call.isCanceled()) { circuitBreaker.releasePermission(); } else { circuitBreaker.onError(System.nanoTime() - start, TimeUnit.NANOSECONDS, t); } callback.onFailure(call, t); } }); } @Override public Response<T> execute() throws IOException { circuitBreaker.acquirePermission(); final StopWatch stopWatch = StopWatch.start(); try { final Response<T> response = call.execute(); if (responseSuccess.test(response)) { circuitBreaker.onResult(stopWatch.stop().toNanos(), TimeUnit.NANOSECONDS, response); } else { final Throwable throwable = new Throwable( "Response error: HTTP " + response.code() + " - " + response.message()); circuitBreaker .onError(stopWatch.stop().toNanos(), TimeUnit.NANOSECONDS, throwable); } return response; } catch (Exception exception) { if (call.isCanceled()) { circuitBreaker.releasePermission(); } else { circuitBreaker .onError(stopWatch.stop().toNanos(), TimeUnit.NANOSECONDS, exception); } throw exception; } } @Override public Call<T> clone() { return new CircuitBreakingCall<>(call.clone(), circuitBreaker, responseSuccess); } } }
CircuitBreakerCallAdapter
-
内容介绍
用于提供集成了熔断器的Call
-
案例源码
import io.github.resilience4j.circuitbreaker.CircuitBreaker; import retrofit2.Call; import retrofit2.CallAdapter; import retrofit2.Response; import retrofit2.Retrofit; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.function.Predicate; /** * Creates a Retrofit {@link CallAdapter.Factory} that decorates a Call to provide integration with * a {@link CircuitBreaker} */ public final class CircuitBreakerCallAdapter extends CallAdapter.Factory { private final CircuitBreaker circuitBreaker; private final Predicate<Response> successResponse; private CircuitBreakerCallAdapter(final CircuitBreaker circuitBreaker, final Predicate<Response> successResponse) { this.circuitBreaker = circuitBreaker; this.successResponse = successResponse; } /** * Create a circuit-breaking call adapter that decorates retrofit calls * * @param circuitBreaker circuit breaker to use * @return a {@link CallAdapter.Factory} that can be passed into the {@link Retrofit.Builder} */ public static CircuitBreakerCallAdapter of(final CircuitBreaker circuitBreaker) { return of(circuitBreaker, Response::isSuccessful); } /** * Create a circuit-breaking call adapter that decorates retrofit calls * * @param circuitBreaker circuit breaker to use * @param successResponse {@link Predicate} that determines whether the {@link Call} {@link * Response} should be considered successful * @return a {@link CallAdapter.Factory} that can be passed into the {@link Retrofit.Builder} */ public static CircuitBreakerCallAdapter of(final CircuitBreaker circuitBreaker, final Predicate<Response> successResponse) { return new CircuitBreakerCallAdapter(circuitBreaker, successResponse); } @Override public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) { @SuppressWarnings("unchecked") CallAdapter<Object, Object> nextAdapter = (CallAdapter<Object, Object>) retrofit .nextCallAdapter(this, returnType, annotations); return new CallAdapter<Object, Object>() { @Override public Type responseType() { return nextAdapter.responseType(); } @Override public Object adapt(Call<Object> call) { return nextAdapter.adapt( RetrofitCircuitBreaker.decorateCall(circuitBreaker, call, successResponse)); } }; } }
使用样例
-
案例源码
// Create a CircuitBreaker private final CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("testName"); // Create a retrofit instance with CircuitBreaker call adapter Retrofit retrofit = new Retrofit.Builder() .addCallAdapterFactory(CircuitBreakerCallAdapter.of(circuitBreaker)) .baseUrl("http://localhost:8080/") .build(); // Get an instance of your service with circuit breaking built-in. RetrofitService service = retrofit.create(RetrofitService.class);
参考链接
版权声明:本文为weixin_42586723原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。