Retrofit,类型安全的RESTful API HTTP客户端!
在现代企业级应用和移动开发领域,Retrofit作为Square公司推出的类型安全HTTP客户端,已经成为连接RESTful API与Java/Kotlin应用的桥梁。这个基于注解的HTTP客户端库,通过将HTTP API转化为Java接口,彻底改变了传统HTTP请求的编写方式。在电商应用中,Retrofit优雅地处理商品列表和订单管理;在社交媒体平台中,它安全地传输用户动态和消息通知;在金融应用中,它严格地校验交易请求和响应格式。从接口定义到请求执行,从参数序列化到响应反序列化,从同步调用到异步回调,Retrofit都在为开发者提供着既类型安全又简洁优雅的API通信解决方案。
核心架构与设计理念
1. 注解驱动的API定义
Retrofit的核心在于使用Java注解来定义HTTP API接口,将RESTful API转换为类型安全的Java接口。
java
// 电商平台API接口定义
public interface EcommerceApiService {
// 商品相关API
@GET("api/v1/products")
Call<ApiResponse<List<Product>>> getProducts(
@Query("page") int page,
@Query("size") int size,
@Query("category") String category,
@Query("sort") String sortBy
);
@GET("api/v1/products/{id}")
Call<ApiResponse<Product>> getProductById(@Path("id") long productId);
@GET("api/v1/products/search")
Call<ApiResponse<List<Product>>> searchProducts(
@Query("q") String keyword,
@Query("page") int page,
@Query("size") int size
);
@POST("api/v1/products")
Call<ApiResponse<Product>> createProduct(
@Header("Authorization") String token,
@Body CreateProductRequest request
);
@Multipart
@POST("api/v1/products/{id}/images")
Call<ApiResponse<UploadResult>> uploadProductImage(
@Path("id") long productId,
@Part MultipartBody.Part imageFile,
@Part("description") RequestBody description
);
// 订单相关API
@POST("api/v1/orders")
Call<ApiResponse<Order>> createOrder(@Body CreateOrderRequest request);
@GET("api/v1/orders")
Call<ApiResponse<PageResponse<Order>>> getOrders(
@Query("page") int page,
@Query("size") int size,
@Query("status") OrderStatus status
);
@GET("api/v1/orders/{orderId}")
Call<ApiResponse<OrderDetail>> getOrderDetail(@Path("orderId") String orderId);
@PUT("api/v1/orders/{orderId}/cancel")
Call<ApiResponse<Void>> cancelOrder(@Path("orderId") String orderId);
// 用户相关API
@POST("api/v1/auth/login")
Call<ApiResponse<LoginResponse>> login(@Body LoginRequest request);
@POST("api/v1/auth/register")
Call<ApiResponse<RegisterResponse>> register(@Body RegisterRequest request);
@GET("api/v1/users/profile")
Call<ApiResponse<UserProfile>> getUserProfile();
@PUT("api/v1/users/profile")
Call<ApiResponse<UserProfile>> updateUserProfile(@Body UpdateProfileRequest request);
// 文件上传
@Multipart
@POST("api/v1/users/avatar")
Call<ApiResponse<AvatarResponse>> uploadAvatar(@Part MultipartBody.Part avatar);
// 流式响应
@Streaming
@GET("api/v1/products/{id}/manual")
Call<ResponseBody> downloadProductManual(@Path("id") long productId);
// 动态URL
@GET
Call<ApiResponse<Product>> getProductByUrl(@Url String url);
// 表单编码
@FormUrlEncoded
@POST("api/v1/feedback")
Call<ApiResponse<Void>> submitFeedback(
@Field("type") String type,
@Field("content") String content,
@Field("contact") String contact
);
// 自定义HTTP方法
@HTTP(method = "CHECKOUT", path = "api/v1/cart/checkout", hasBody = true)
Call<ApiResponse<CheckoutResult>> checkoutCart(@Body CheckoutRequest request);
}
// 支持RxJava的API接口
public interface RxEcommerceApiService {
@GET("api/v1/products")
Observable<ApiResponse<List<Product>>> getProducts(
@Query("page") int page,
@Query("size") int size
);
@GET("api/v1/products/{id}")
Single<ApiResponse<Product>> getProductById(@Path("id") long productId);
@POST("api/v1/orders")
Completable createOrder(@Body CreateOrderRequest request);
@GET("api/v1/orders/{orderId}")
Flowable<ApiResponse<OrderDetail>> getOrderDetailStream(@Path("orderId") String orderId);
}
// 支持协程的API接口(Kotlin)
interface CoroutineEcommerceApiService {
@GET("api/v1/products")
suspend fun getProducts(
@Query("page") page: Int,
@Query("size") size: Int
): ApiResponse<List<Product>>
@POST("api/v1/orders")
suspend fun createOrder(@Body request: CreateOrderRequest): ApiResponse<Order>
@GET("api/v1/orders/{orderId}")
suspend fun getOrderDetail(@Path("orderId") orderId: String): ApiResponse<OrderDetail>
}
2. Retrofit客户端配置与构建
java
// Retrofit客户端工厂
public class RetrofitClientFactory {
private static final String BASE_URL = "https://api.ecommerce.com/";
private static volatile Retrofit instance;
public static Retrofit getInstance() {
if (instance == null) {
synchronized (RetrofitClientFactory.class) {
if (instance == null) {
instance = createRetrofit();
}
}
}
return instance;
}
private static Retrofit createRetrofit() {
// 创建OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.addInterceptor(new AuthInterceptor())
.addInterceptor(new LoggingInterceptor())
.addInterceptor(new RetryInterceptor(3))
.addNetworkInterceptor(new StethoInterceptor())
.cache(new Cache(new File("/tmp/http-cache"), 50 * 1024 * 1024))
.build();
// 创建Gson实例,配置序列化/反序列化规则
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter())
.registerTypeAdapter(BigDecimal.class, new BigDecimalAdapter())
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create();
// 构建Retrofit实例
return new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create(gson))
.addConverterFactory(ScalarsConverterFactory.create()) // 支持基本类型
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支持RxJava
.addCallAdapterFactory(CoroutineCallAdapterFactory.create()) // 支持协程
.build();
}
// 创建API服务实例
public static EcommerceApiService createApiService() {
return getInstance().create(EcommerceApiService.class);
}
public static RxEcommerceApiService createRxApiService() {
return getInstance().create(RxEcommerceApiService.class);
}
}
// 自定义类型适配器
public class LocalDateTimeAdapter implements JsonSerializer<LocalDateTime>,
JsonDeserializer<LocalDateTime> {
private static final DateTimeFormatter FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
@Override
public JsonElement serialize(LocalDateTime src, Type typeOfSrc,
JsonSerializationContext context) {
return new JsonPrimitive(FORMATTER.format(src));
}
@Override
public LocalDateTime deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context)
throws JsonParseException {
return LocalDateTime.parse(json.getAsString(), FORMATTER);
}
}
public class BigDecimalAdapter implements JsonSerializer<BigDecimal>,
JsonDeserializer<BigDecimal> {
@Override
public JsonElement serialize(BigDecimal src, Type typeOfSrc,
JsonSerializationContext context) {
return new JsonPrimitive(src.setScale(2, RoundingMode.HALF_UP).toString());
}
@Override
public BigDecimal deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context)
throws JsonParseException {
try {
return new BigDecimal(json.getAsString());
} catch (NumberFormatException e) {
throw new JsonParseException("Invalid BigDecimal format", e);
}
}
}
高级特性与应用
1. 自定义转换器与适配器
java
// 自定义ConverterFactory - 支持Protobuf
public class ProtobufConverterFactory extends Converter.Factory {
private static final MediaType PROTOBUF = MediaType.parse("application/x-protobuf");
@Override
public Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
if (!(type instanceof Class)) {
return null;
}
Class<?> clazz = (Class<?>) type;
if (!Message.class.isAssignableFrom(clazz)) {
return null;
}
return (Converter<ResponseBody, ?>) responseBody -> {
try {
Message.Builder builder = getBuilderForType(clazz);
builder.mergeFrom(responseBody.byteStream());
return builder.build();
} catch (IOException e) {
throw new RuntimeException("Failed to parse protobuf", e);
}
};
}
@Override
public Converter<?, RequestBody> requestBodyConverter(
Type type, Annotation[] parameterAnnotations,
Annotation[] methodAnnotations, Retrofit retrofit) {
if (!(type instanceof Class)) {
return null;
}
Class<?> clazz = (Class<?>) type;
if (!Message.class.isAssignableFrom(clazz)) {
return null;
}
return (Converter<Message, RequestBody>) value ->
RequestBody.create(PROTOBUF, value.toByteArray());
}
private Message.Builder getBuilderForType(Class<?> clazz) {
try {
Method method = clazz.getMethod("newBuilder");
return (Message.Builder) method.invoke(null);
} catch (Exception e) {
throw new RuntimeException("Failed to create builder", e);
}
}
}
// 自定义CallAdapter - 支持LiveData
public class LiveDataCallAdapterFactory extends CallAdapter.Factory {
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != LiveData.class) {
return null;
}
Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
Class<?> rawObservableType = getRawType(observableType);
if (rawObservableType != ApiResponse.class) {
throw new IllegalArgumentException("LiveData type must be ApiResponse");
}
Type bodyType = getParameterUpperBound(0, (ParameterizedType) observableType);
return new LiveDataCallAdapter<>(bodyType);
}
private static class LiveDataCallAdapter<R> implements CallAdapter<R, LiveData<ApiResponse<R>>> {
private final Type responseType;
LiveDataCallAdapter(Type responseType) {
this.responseType = responseType;
}
@Override
public Type responseType() {
return responseType;
}
@Override
public LiveData<ApiResponse<R>> adapt(Call<R> call) {
return new LiveData<ApiResponse<R>>() {
@Override
protected void onActive() {
super.onActive();
call.enqueue(new Callback<R>() {
@Override
public void onResponse(Call<R> call, Response<R> response) {
if (response.isSuccessful()) {
postValue(ApiResponse.success(response.body()));
} else {
postValue(ApiResponse.error(response.code(),
response.message()));
}
}
@Override
public void onFailure(Call<R> call, Throwable t) {
postValue(ApiResponse.error(t));
}
});
}
};
}
}
}
// 自定义注解处理器 - 请求头注入
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface DynamicHeader {
String value();
}
public class DynamicHeaderConverterFactory extends Converter.Factory {
@Override
public Converter<?, String> stringConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
for (Annotation annotation : annotations) {
if (annotation instanceof DynamicHeader) {
return new DynamicHeaderConverter((DynamicHeader) annotation);
}
}
return null;
}
private static class DynamicHeaderConverter implements Converter<Object, String> {
private final DynamicHeader annotation;
DynamicHeaderConverter(DynamicHeader annotation) {
this.annotation = annotation;
}
@Override
public String convert(Object value) throws IOException {
// 根据业务逻辑动态生成请求头值
return generateHeaderValue(annotation.value(), value);
}
private String generateHeaderValue(String headerName, Object value) {
switch (headerName) {
case "X-User-Id":
return String.valueOf(((User) value).getId());
case "X-Device-Info":
return ((DeviceInfo) value).toString();
case "X-Timestamp":
return String.valueOf(System.currentTimeMillis());
default:
return value.toString();
}
}
}
}
2. 错误处理与响应包装
java
// 统一的API响应包装类
public class ApiResponse<T> {
private final T data;
private final String message;
private final int code;
private final boolean success;
private final long timestamp;
public ApiResponse(T data, String message, int code, boolean success) {
this.data = data;
this.message = message;
this.code = code;
this.success = success;
this.timestamp = System.currentTimeMillis();
}
public static <T> ApiResponse<T> success(T data) {
return new ApiResponse<>(data, "Success", 200, true);
}
public static <T> ApiResponse<T> error(int code, String message) {
return new ApiResponse<>(null, message, code, false);
}
public static <T> ApiResponse<T> error(Throwable throwable) {
return new ApiResponse<>(null, throwable.getMessage(), 500, false);
}
// Getter方法
public T getData() { return data; }
public String getMessage() { return message; }
public int getCode() { return code; }
public boolean isSuccess() { return success; }
public long getTimestamp() { return timestamp; }
// 辅助方法
public T getDataOrThrow() {
if (!success) {
throw new ApiException(code, message);
}
return data;
}
public Optional<T> getDataOptional() {
return Optional.ofNullable(data);
}
}
// 自定义响应转换器 - 处理统一的API响应格式
public class ApiResponseConverter<T> implements Converter<ResponseBody, ApiResponse<T>> {
private final Gson gson;
private final Type type;
public ApiResponseConverter(Gson gson, Type type) {
this.gson = gson;
this.type = type;
}
@Override
public ApiResponse<T> convert(ResponseBody value) throws IOException {
try {
String json = value.string();
// 解析为JsonObject
JsonObject jsonObject = gson.fromJson(json, JsonObject.class);
// 提取公共字段
boolean success = jsonObject.get("success").getAsBoolean();
int code = jsonObject.get("code").getAsInt();
String message = jsonObject.get("message").getAsString();
long timestamp = jsonObject.get("timestamp").getAsLong();
// 提取数据字段
JsonElement dataElement = jsonObject.get("data");
T data = null;
if (dataElement != null && !dataElement.isJsonNull()) {
data = gson.fromJson(dataElement, type);
}
return new ApiResponse<>(data, message, code, success);
} catch (JsonSyntaxException e) {
throw new IOException("Failed to parse API response", e);
} finally {
value.close();
}
}
}
// 自定义ConverterFactory - 包装ApiResponse
public class ApiResponseConverterFactory extends Converter.Factory {
private final Gson gson;
public ApiResponseConverterFactory(Gson gson) {
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
// 检查是否是ApiResponse类型
if (getRawType(type) != ApiResponse.class) {
return null;
}
// 获取ApiResponse的泛型参数
Type responseType = getParameterUpperBound(0, (ParameterizedType) type);
return new ApiResponseConverter<>(gson, responseType);
}
}
// 全局异常处理器
public class RetrofitExceptionHandler {
public static <T> Single<T> handleObservableError(Observable<T> observable) {
return observable
.onErrorResumeNext(throwable -> {
if (throwable instanceof HttpException) {
HttpException httpException = (HttpException) throwable;
int code = httpException.code();
String message = httpException.message();
return Single.error(new ApiException(code, message));
} else if (throwable instanceof SocketTimeoutException) {
return Single.error(new NetworkException("连接超时", throwable));
} else if (throwable instanceof ConnectException) {
return Single.error(new NetworkException("网络连接失败", throwable));
} else if (throwable instanceof IOException) {
return Single.error(new NetworkException("网络异常", throwable));
} else {
return Single.error(new ApiException(500, "系统异常", throwable));
}
})
.singleOrError();
}
public static <T> Callback<T> createCallback(
Consumer<T> onSuccess,
Consumer<Throwable> onError) {
return new Callback<T>() {
@Override
public void onResponse(Call<T> call, Response<T> response) {
if (response.isSuccessful()) {
onSuccess.accept(response.body());
} else {
onError.accept(new ApiException(
response.code(),
response.message()
));
}
}
@Override
public void onFailure(Call<T> call, Throwable t) {
onError.accept(translateException(t));
}
};
}
private static Throwable translateException(Throwable throwable) {
if (throwable instanceof HttpException) {
HttpException httpException = (HttpException) throwable;
return new ApiException(httpException.code(), httpException.message());
}
if (throwable instanceof SocketTimeoutException) {
return new NetworkException("请求超时", throwable);
}
if (throwable instanceof ConnectException) {
return new NetworkException("网络不可用", throwable);
}
if (throwable instanceof IOException) {
return new NetworkException("网络错误", throwable);
}
return new ApiException(500, "未知错误", throwable);
}
}
实战案例:电商平台API客户端
下面通过一个完整的电商平台案例,展示Retrofit在复杂业务场景中的应用。
java
// 电商平台API客户端服务
public class EcommerceApiClient {
private final EcommerceApiService apiService;
private final RxEcommerceApiService rxApiService;
private final AuthManager authManager;
private final CacheManager cacheManager;
public EcommerceApiClient() {
Retrofit retrofit = RetrofitClientFactory.getInstance();
this.apiService = retrofit.create(EcommerceApiService.class);
this.rxApiService = retrofit.create(RxEcommerceApiService.class);
this.authManager = AuthManager.getInstance();
this.cacheManager = CacheManager.getInstance();
}
// 商品服务
public Single<List<Product>> getProducts(int page, int size, String category) {
return rxApiService.getProducts(page, size, category)
.compose(RetrofitExceptionHandler::handleObservableError)
.map(ApiResponse::getDataOrThrow)
.doOnSuccess(products -> cacheManager.cacheProducts(products));
}
public Single<Product> getProductById(long productId) {
// 先尝试从缓存获取
Product cached = cacheManager.getCachedProduct(productId);
if (cached != null) {
return Single.just(cached);
}
return rxApiService.getProductById(productId)
.compose(RetrofitExceptionHandler::handleObservableError)
.map(ApiResponse::getDataOrThrow)
.doOnSuccess(product -> cacheManager.cacheProduct(product));
}
public Single<List<Product>> searchProducts(String keyword, int page) {
return rxApiService.searchProducts(keyword, page)
.compose(RetrofitExceptionHandler::handleObservableError)
.map(ApiResponse::getDataOrThrow);
}
public Completable createProduct(CreateProductRequest request) {
String token = authManager.getAccessToken();
if (token == null) {
return Completable.error(new UnauthorizedException("需要登录"));
}
return rxApiService.createProduct(token, request)
.compose(RetrofitExceptionHandler::handleObservableError)
.ignoreElement();
}
public Single<UploadResult> uploadProductImage(long productId, File imageFile, String description) {
// 创建MultipartBody.Part
RequestBody requestFile = RequestBody.create(
imageFile, MediaType.parse("image/*"));
MultipartBody.Part body = MultipartBody.Part.createFormData(
"image", imageFile.getName(), requestFile);
RequestBody descriptionBody = RequestBody.create(
description, MediaType.parse("text/plain"));
return rxApiService.uploadProductImage(productId, body, descriptionBody)
.compose(RetrofitExceptionHandler::handleObservableError)
.map(ApiResponse::getDataOrThrow);
}
// 订单服务
public Single<Order> createOrder(CreateOrderRequest request) {
return rxApiService.createOrder(request)
.compose(RetrofitExceptionHandler::handleObservableError)
.map(ApiResponse::getDataOrThrow)
.doOnSuccess(order -> {
// 发送订单创建事件
EventBus.getDefault().post(new OrderCreatedEvent(order));
});
}
public Single<PageResponse<Order>> getOrders(int page, int size, OrderStatus status) {
return rxApiService.getOrders(page, size, status)
.compose(RetrofitExceptionHandler::handleObservableError)
.map(ApiResponse::getDataOrThrow);
}
public Flowable<OrderDetail> getOrderDetailStream(String orderId) {
return rxApiService.getOrderDetailStream(orderId)
.map(ApiResponse::getDataOrThrow)
.onErrorResumeNext(throwable -> {
// 优雅处理错误
return Flowable.error(translateException(throwable));
});
}
public Completable cancelOrder(String orderId) {
return rxApiService.cancelOrder(orderId)
.compose(RetrofitExceptionHandler::handleObservableError)
.ignoreElement();
}
// 用户服务
public Single<LoginResponse> login(String username, String password) {
LoginRequest request = new LoginRequest(username, password);
return rxApiService.login(request)
.compose(RetrofitExceptionHandler::handleObservableError)
.map(ApiResponse::getDataOrThrow)
.doOnSuccess(loginResponse -> {
// 保存认证信息
authManager.saveAuthInfo(loginResponse);
});
}
public Single<RegisterResponse> register(RegisterRequest request) {
return rxApiService.register(request)
.compose(RetrofitExceptionHandler::handleObservableError)
.map(ApiResponse::getDataOrThrow);
}
public Single<UserProfile> getUserProfile() {
return rxApiService.getUserProfile()
.compose(RetrofitExceptionHandler::handleObservableError)
.map(ApiResponse::getDataOrThrow)
.doOnSuccess(profile -> cacheManager.cacheUserProfile(profile));
}
public Single<UserProfile> updateUserProfile(UpdateProfileRequest request) {
return rxApiService.updateUserProfile(request)
.compose(RetrofitExceptionHandler::handleObservableError)
.map(ApiResponse::getDataOrThrow)
.doOnSuccess(profile -> {
cacheManager.cacheUserProfile(profile);
// 发送资料更新事件
EventBus.getDefault().post(new ProfileUpdatedEvent(profile));
});
}
public Single<AvatarResponse> uploadAvatar(File avatarFile) {
// 创建MultipartBody.Part
RequestBody requestFile = RequestBody.create(
avatarFile, MediaType.parse("image/*"));
MultipartBody.Part body = MultipartBody.Part.createFormData(
"avatar", avatarFile.getName(), requestFile);
return rxApiService.uploadAvatar(body)
.compose(RetrofitExceptionHandler::handleObservableError)
.map(ApiResponse::getDataOrThrow)
.doOnSuccess(avatarResponse -> {
// 更新本地用户头像
cacheManager.updateUserAvatar(avatarResponse.getAvatarUrl());
});
}
// 批量操作
public Observable<BatchResult> batchCreateProducts(List<CreateProductRequest> requests) {
return Observable.fromIterable(requests)
.flatMap(request -> rxApiService.createProduct(
authManager.getAccessToken(), request)
.toObservable()
.map(ApiResponse::getDataOrThrow)
.map(product -> new BatchResult(product.getId(), true, null))
.onErrorReturn(throwable ->
new BatchResult(null, false, throwable.getMessage())),
5) // 并发数限制
.buffer(10) // 每10个结果打包一次
.flatMap(results -> Observable.fromIterable(results));
}
// 复杂的组合操作
public Single<CheckoutResult> checkoutWithValidation(ShoppingCart cart) {
// 1. 验证购物车
return validateCart(cart)
.flatMap(valid -> {
if (!valid) {
return Single.error(new ValidationException("购物车验证失败"));
}
// 2. 检查库存
return checkInventory(cart.getItems())
.flatMap(inStock -> {
if (!inStock) {
return Single.error(new InventoryException("库存不足"));
}
// 3. 创建订单
CreateOrderRequest request = CreateOrderRequest.fromCart(cart);
return createOrder(request)
.flatMap(order -> {
// 4. 处理支付
return processPayment(order)
.flatMap(paymentResult -> {
// 5. 发送确认邮件
return sendConfirmationEmail(order, paymentResult)
.map(success -> new CheckoutResult(
order, paymentResult, success));
});
});
});
});
}
private Single<Boolean> validateCart(ShoppingCart cart) {
// 调用验证API
return rxApiService.get("api/v1/cart/validate")
.compose(RetrofitExceptionHandler::handleObservableError)
.map(ApiResponse::getDataOrThrow)
.map(ValidationResponse::isValid);
}
private Single<Boolean> checkInventory(List<CartItem> items) {
List<Single<Boolean>> checks = items.stream()
.map(item -> checkItemInventory(item.getProductId(), item.getQuantity()))
.collect(Collectors.toList());
return Single.zip(checks, results ->
Arrays.stream(results)
.allMatch(result -> (Boolean) result))
.flatMap(allInStock -> Single.just(allInStock));
}
private Single<Boolean> checkItemInventory(long productId, int quantity) {
return getProductById(productId)
.map(product -> product.getStock() >= quantity);
}
private Single<PaymentResult> processPayment(Order order) {
PaymentRequest request = new PaymentRequest(
order.getId(), order.getTotalAmount(), order.getPaymentMethod());
return rxApiService.post("api/v1/payments/process", request)
.compose(RetrofitExceptionHandler::handleObservableError)
.map(ApiResponse::getDataOrThrow);
}
private Single<Boolean> sendConfirmationEmail(Order order, PaymentResult paymentResult) {
ConfirmationEmailRequest request = new ConfirmationEmailRequest(
order, paymentResult.getTransactionId());
return rxApiService.post("api/v1/notifications/order-confirmation", request)
.compose(RetrofitExceptionHandler::handleObservableError)
.map(ApiResponse::getDataOrThrow)
.map(EmailResponse::isSuccess);
}
// 响应式编程组合
public Flowable<Product> getProductsWithRealTimeUpdates() {
// 1. 获取初始产品列表
return getProducts(1, 20, null)
.flattenAsObservable(list -> list)
.mergeWith(
// 2. 合并实时更新流
rxApiService.getOrderDetailStream("dummy") // WebSocket流
.ofType(ProductUpdateEvent.class)
.map(ProductUpdateEvent::getProduct)
)
.distinct(Product::getId) // 去重
.filter(product -> product.isAvailable()) // 过滤可用商品
.onBackpressureBuffer(1000); // 背压处理
}
// 协程版本(Kotlin)
suspend fun getProductsCoroutine(page: Int, size: Int): List<Product> {
return withContext(Dispatchers.IO) {
try {
val response = apiService.getProducts(page, size)
if (response.isSuccessful) {
response.body()?.data ?: emptyList()
} else {
throw ApiException(response.code(), response.message())
}
} catch (e: IOException) {
throw NetworkException("网络错误", e)
}
}
}
// 错误重试与回退机制
public Single<List<Product>> getProductsWithRetry(int page, int size) {
return rxApiService.getProducts(page, size)
.retryWhen(errors -> errors
.zipWith(Observable.range(1, 3), (error, retryCount) -> {
if (retryCount == 3) {
throw error;
}
return retryCount;
})
.flatMap(retryCount ->
Observable.timer((long) Math.pow(2.0, retryCount), TimeUnit.SECONDS))
)
.onErrorResumeNext(throwable -> {
// 错误回退:从缓存获取
List<Product> cached = cacheManager.getCachedProducts();
if (!cached.isEmpty()) {
return Single.just(ApiResponse.success(cached));
}
return Single.error(throwable);
})
.compose(RetrofitExceptionHandler::handleObservableError)
.map(ApiResponse::getDataOrThrow);
}
}
// 请求/响应模型类
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Product {
private Long id;
private String name;
private String description;
private BigDecimal price;
private Integer stock;
private String category;
private List<String> images;
private Double rating;
private Integer reviewCount;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
private boolean available;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CreateProductRequest {
@NotBlank(message = "商品名称不能为空")
private String name;
@Size(max = 1000, message = "描述不能超过1000字")
private String description;
@DecimalMin(value = "0.01", message = "价格必须大于0")
private BigDecimal price;
@Min(value = 0, message = "库存不能为负数")
private Integer stock;
@NotBlank(message = "分类不能为空")
private String category;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Order {
private String id;
private Long userId;
private List<OrderItem> items;
private BigDecimal totalAmount;
private OrderStatus status;
private String shippingAddress;
private String paymentMethod;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
// 自定义注解 - 缓存控制
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CacheControl {
int maxAge() default 60; // 秒
boolean mustRevalidate() default false;
CacheStrategy strategy() default CacheStrategy.NETWORK_FIRST;
enum CacheStrategy {
NETWORK_FIRST,
CACHE_FIRST,
CACHE_ONLY,
NETWORK_ONLY
}
}
// 缓存拦截器
public class CacheInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
// 检查是否有缓存注解
CacheControl cacheControl = getCacheControlAnnotation(request);
if (cacheControl == null) {
return chain.proceed(request);
}
// 根据策略处理缓存
switch (cacheControl.strategy()) {
case NETWORK_FIRST:
return handleNetworkFirst(request, chain, cacheControl);
case CACHE_FIRST:
return handleCacheFirst(request, chain, cacheControl);
case CACHE_ONLY:
return handleCacheOnly(request, chain);
case NETWORK_ONLY:
default:
return chain.proceed(request);
}
}
private Response handleNetworkFirst(Request request, Chain chain, CacheControl cacheControl)
throws IOException {
try {
Response response = chain.proceed(request);
// 缓存成功响应
if (response.isSuccessful()) {
Response cachedResponse = response.newBuilder()
.header("Cache-Control",
"public, max-age=" + cacheControl.maxAge() +
(cacheControl.mustRevalidate() ? ", must-revalidate" : ""))
.build();
return cachedResponse;
}
return response;
} catch (IOException e) {
// 网络失败时尝试从缓存获取
Response cachedResponse = getCachedResponse(request);
if (cachedResponse != null) {
return cachedResponse;
}
throw e;
}
}
// 其他缓存策略实现...
}
Retrofit的真正革命性在于它将HTTP API从繁琐的请求构建和响应解析中解放出来,通过类型安全的接口定义和注解驱动的配置,让API调用变得既简单又可靠。其灵活的设计允许开发者通过自定义转换器、适配器和拦截器来扩展功能,满足各种复杂场景的需求。特别是在结合RxJava、协程等响应式编程框架时,Retrofit能够构建出优雅且强大的异步数据流。
然而,Retrofit的强大也需要合理的架构设计来支撑。在实际项目中,应该建立统一的错误处理机制、合理的缓存策略、完善的认证授权流程。通过合理的分层和封装,可以让Retrofit在保持简洁性的同时,也能够应对企业级应用的复杂需求。
看完这篇文章,你是否在项目中使用Retrofit构建过复杂的API客户端?或者你在Retrofit与响应式编程结合方面有什么独特的经验?欢迎在评论区分享你的Retrofit实战心得,也欢迎提出关于RESTful API设计和技术栈选型的任何技术问题,让我们一起探讨如何更好地构建现代化、类型安全的API通信体系!
更多推荐




所有评论(0)