本文目录导读:

- 使用 HttpClient (JDK 11+)
- 使用 RestTemplate (Spring)
- 使用 WebClient (Spring WebFlux)
- 使用 Retrofit (Square)
- 通用接口调用工具类
- 使用示例
- 最佳实践建议
我来详细介绍Java中封装接口调用工具的几种常用方式。
使用 HttpClient (JDK 11+)
基础封装
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import java.time.Duration;
import com.fasterxml.jackson.databind.ObjectMapper;
public class HttpUtil {
private static final HttpClient httpClient;
private static final ObjectMapper objectMapper;
static {
httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
objectMapper = new ObjectMapper();
}
// GET请求
public static <T> T doGet(String url, Class<T> responseType) {
try {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.timeout(Duration.ofSeconds(30))
.GET()
.build();
HttpResponse<String> response = httpClient.send(request,
HttpResponse.BodyHandlers.ofString());
return objectMapper.readValue(response.body(), responseType);
} catch (Exception e) {
throw new RuntimeException("HTTP GET请求失败", e);
}
}
// POST请求
public static <T, R> R doPost(String url, T requestBody, Class<R> responseType) {
try {
String jsonBody = objectMapper.writeValueAsString(requestBody);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.timeout(Duration.ofSeconds(30))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
HttpResponse<String> response = httpClient.send(request,
HttpResponse.BodyHandlers.ofString());
return objectMapper.readValue(response.body(), responseType);
} catch (Exception e) {
throw new RuntimeException("HTTP POST请求失败", e);
}
}
}
使用 RestTemplate (Spring)
RestTemplate配置
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate(clientHttpRequestFactory());
}
private ClientHttpRequestFactory clientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(5000);
factory.setReadTimeout(5000);
factory.setBufferRequestBody(false);
return factory;
}
}
封装的工具类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@Component
public class RestTemplateUtil {
@Autowired
private RestTemplate restTemplate;
// GET请求
public <T> T get(String url, Class<T> responseType) {
return restTemplate.getForObject(url, responseType);
}
// GET请求带参数
public <T> T get(String url, Map<String, Object> params, Class<T> responseType) {
return restTemplate.getForObject(url, responseType, params);
}
// POST请求
public <T> T post(String url, Object requestBody, Class<T> responseType) {
return restTemplate.postForObject(url, requestBody, responseType);
}
// 完整的请求
public <T> T exchange(String url, HttpMethod method,
Object requestBody, Class<T> responseType,
HttpHeaders headers) {
HttpEntity<Object> entity = new HttpEntity<>(requestBody, headers);
ResponseEntity<T> response = restTemplate.exchange(url, method, entity, responseType);
return response.getBody();
}
}
使用 WebClient (Spring WebFlux)
基础封装
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Mono;
import java.time.Duration;
public class WebClientUtil {
private static final WebClient webClient = WebClient.builder()
.baseUrl("https://api.example.com")
.defaultHeader("Accept", "application/json")
.codecs(config -> config
.defaultCodecs()
.maxInMemorySize(16 * 1024 * 1024))
.build();
public static <T, R> Mono<R> post(String path, T requestBody, Class<R> responseType) {
return webClient.post()
.uri(path)
.bodyValue(requestBody)
.retrieve()
.bodyToMono(responseType)
.timeout(Duration.ofSeconds(30))
.onErrorResume(WebClientResponseException.class,
ex -> {
// 错误处理
return Mono.error(new RuntimeException("API调用失败: " + ex.getMessage()));
});
}
public static <T> Mono<T> get(String path, Class<T> responseType) {
return webClient.get()
.uri(path)
.retrieve()
.bodyToMono(responseType)
.timeout(Duration.ofSeconds(30));
}
}
使用 Retrofit (Square)
接口定义
import retrofit2.Call;
import retrofit2.http.*;
public interface ApiService {
@GET("users/{id}")
Call<User> getUser(@Path("id") Long id);
@POST("users")
Call<User> createUser(@Body User user);
@PUT("users/{id}")
Call<User> updateUser(@Path("id") Long id, @Body User user);
@DELETE("users/{id}")
Call<Void> deleteUser(@Path("id") Long id);
}
封装成工具类
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import java.io.IOException;
public class RetrofitClient {
private static final String BASE_URL = "https://api.example.com/";
private static Retrofit retrofit;
private static ApiService apiService;
static {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
apiService = retrofit.create(ApiService.class);
}
// 同步调用
public static <T> T execute(Call<T> call) {
try {
Response<T> response = call.execute();
if (response.isSuccessful()) {
return response.body();
} else {
throw new RuntimeException("请求失败: " + response.code());
}
} catch (IOException e) {
throw new RuntimeException("网络请求异常", e);
}
}
// 异步调用
public static <T> void enqueue(Call<T> call, ApiCallback<T> callback) {
call.enqueue(new Callback<T>() {
@Override
public void onResponse(Call<T> call, Response<T> response) {
if (response.isSuccessful()) {
callback.onSuccess(response.body());
} else {
callback.onError(500, response.message());
}
}
@Override
public void onFailure(Call<T> call, Throwable t) {
callback.onError(500, t.getMessage());
}
});
}
public interface ApiCallback<T> {
void onSuccess(T data);
void onError(int code, String message);
}
}
通用接口调用工具类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
public class ApiClient {
private static final Logger log = LoggerFactory.getLogger(ApiClient.class);
private final HttpUtil httpUtil;
private final Map<String, Object> defaultHeaders;
public ApiClient(HttpUtil httpUtil) {
this.httpUtil = httpUtil;
this.defaultHeaders = new HashMap<>();
initDefaultHeaders();
}
private void initDefaultHeaders() {
defaultHeaders.put("Content-Type", "application/json");
defaultHeaders.put("Accept", "application/json");
defaultHeaders.put("User-Agent", "ApiClient/1.0");
}
// 带重试机制的调用
public <T, R> R callWithRetry(String url, T request,
Class<R> responseType,
int maxRetries) {
Exception lastException = null;
for (int i = 0; i < maxRetries; i++) {
try {
return doCall(url, request, responseType);
} catch (Exception e) {
lastException = e;
log.warn("调用失败,重试次数: {}/{}", i + 1, maxRetries);
sleep(1000 * (i + 1)); // 递增延迟
}
}
throw new RuntimeException("接口调用失败,已重试" + maxRetries + "次", lastException);
}
// 异步调用
public <T, R> CompletableFuture<R> callAsync(String url,
T request,
Class<R> responseType) {
return CompletableFuture.supplyAsync(() -> doCall(url, request, responseType));
}
// 带缓存的调用
public <T, R> R callWithCache(String url, T request,
Class<R> responseType,
Cache<String, R> cache) {
String cacheKey = generateCacheKey(url, request);
R cachedResult = cache.get(cacheKey);
if (cachedResult != null) {
log.debug("从缓存获取数据: {}", cacheKey);
return cachedResult;
}
R result = doCall(url, request, responseType);
cache.put(cacheKey, result);
return result;
}
private <T, R> R doCall(String url, T request, Class<R> responseType) {
try {
log.debug("调用API: {}, 请求参数: {}", url, request);
long startTime = System.currentTimeMillis();
R result = httpUtil.doPost(url, request, responseType);
long duration = System.currentTimeMillis() - startTime;
log.debug("API调用完成,耗时: {}ms, 结果: {}", duration, result);
return result;
} catch (Exception e) {
log.error("API调用异常: {}", url, e);
throw new ApiException("API调用失败: " + e.getMessage(), e);
}
}
private void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private <T> String generateCacheKey(String url, T request) {
return url + ":" + request.hashCode();
}
// 自定义异常
public static class ApiException extends RuntimeException {
public ApiException(String message, Throwable cause) {
super(message, cause);
}
}
}
使用示例
// 1. 基础使用
User user = HttpUtil.doPost("https://api.example.com/users",
new CreateUserRequest("张三"),
User.class);
// 2. Spring RestTemplate
User user = restTemplateUtil.post("https://api.example.com/users",
requestBody,
User.class);
// 3. 带重试机制
User user = apiClient.callWithRetry("https://api.example.com/users",
request,
User.class,
3);
// 4. 异步调用
CompletableFuture<User> future = apiClient.callAsync(url, request, User.class);
future.thenAccept(user -> {
System.out.println("获取到用户: " + user.getName());
});
最佳实践建议
- 统一异常处理:封装统一的异常类,便于上层处理
- 日志记录:记录请求和响应信息,便于问题排查
- 超时控制:设置合理的连接和读取超时时间
- 重试机制:关键接口添加重试逻辑
- 线程安全:确保工具类是线程安全的
- 配置化:将API地址、超时等参数配置化
- 监控集成:集成APM或监控系统,跟踪调用性能
选择合适的封装方式应根据项目需求、团队技术栈和框架来决定。