Java案例怎么封装接口调用工具?

wen java案例 76

本文目录导读:

Java案例怎么封装接口调用工具?

  1. 使用 HttpClient (JDK 11+)
  2. 使用 RestTemplate (Spring)
  3. 使用 WebClient (Spring WebFlux)
  4. 使用 Retrofit (Square)
  5. 通用接口调用工具类
  6. 使用示例
  7. 最佳实践建议

我来详细介绍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());
});

最佳实践建议

  1. 统一异常处理:封装统一的异常类,便于上层处理
  2. 日志记录:记录请求和响应信息,便于问题排查
  3. 超时控制:设置合理的连接和读取超时时间
  4. 重试机制:关键接口添加重试逻辑
  5. 线程安全:确保工具类是线程安全的
  6. 配置化:将API地址、超时等参数配置化
  7. 监控集成:集成APM或监控系统,跟踪调用性能

选择合适的封装方式应根据项目需求、团队技术栈和框架来决定。

抱歉,评论功能暂时关闭!