10 Ways to Call Third-Party APIs in Spring Boot 3.3 – Full Code Guide
This article reviews ten practical methods for invoking third-party HTTP services in Spring Boot 3.3, covering plain JDK URL, HttpClient, Apache HttpClient, OkHttp, RestTemplate, WebClient, RestClient, Http Interface, OpenFeign, and Gateway proxy, each with code samples and key advantages.
Environment: SpringBoot 3.3.0
1. Introduction
Calling third‑party interfaces is common in projects; the choice of method follows the company’s tech stack and architecture guidelines. RESTful API, Feign, Apache HttpClient, etc., each have scenarios and advantages, and selecting the right one improves development efficiency and system performance.
2. Practical Examples
2.1 JDK URL
<code>URL url = URI.create("http://localhost:8002/api/data").toURL();
URLConnection connection = url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
InputStream inputStream = connection.getInputStream();
String ret = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
System.out.println(ret);
</code>This approach is cumbersome and lacks support for request parameters, making it time‑consuming for complex APIs.
2.2 JDK HttpClient (Java 11+)
<code>URI uri = URI.create("http://localhost:8002/api/data");
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(3))
.executor(Executors.newCachedThreadPool())
.build();
HttpRequest request = HttpRequest.newBuilder(uri)
.GET()
.build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
System.out.println(response.body());
</code>HttpClient offers better configurability but is still a bit verbose.
2.3 Apache HttpClient
<code>HttpGet httpget = new HttpGet("http://localhost:8002/api/data");
CloseableHttpClient client = HttpClients.custom().build();
HttpClientResponseHandler<String> responseHandler = new BasicHttpClientResponseHandler();
String ret = client.execute(httpget, responseHandler);
System.out.println(ret);
</code>Apache HttpClient 5 supports HTTP/2, high customisation, and asynchronous requests:
<code>CloseableHttpAsyncClient client = HttpAsyncClients.custom().build();
client.start();
SimpleHttpRequest request = SimpleRequestBuilder.get()
.setHttpHost(HttpHost.create("http://localhost:8002"))
.setPath("/api/data")
.build();
FutureCallback<SimpleHttpResponse> callback = new FutureCallback<SimpleHttpResponse>() {
@Override public void failed(Exception ex) { System.err.printf("Request failed: %s%n", ex.getMessage()); }
@Override public void completed(SimpleHttpResponse result) { System.out.printf("Thread: %s, completed...%n", Thread.currentThread().getName()); }
public void cancelled() {}
};
Future<SimpleHttpResponse> future = client.execute(request, callback);
System.out.println(new String(future.get().getBodyBytes(), StandardCharsets.UTF_8));
client.close(CloseMode.GRACEFUL);
</code>2.4 OkHttp
HTTP/2 support allows socket sharing for all requests to the same host.
Connection pool reduces latency when HTTP/2 is unavailable.
Transparent GZIP reduces download size.
Response cache eliminates duplicate network calls.
Simple synchronous call:
<code>URL url = URI.create("http://localhost:8002/api/data").toURL();
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
</code>Asynchronous call:
<code>URL url = URI.create("http://localhost:8002/api/data").toURL();
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new Callback() {
public void onResponse(Call call, Response response) throws IOException {
System.out.printf("Thread: %s, content: %s%n", Thread.currentThread().getName(), response.body().string());
}
public void onFailure(Call call, IOException e) {
System.err.printf("Request failed: %s%n", e.getMessage());
}
});
</code>2.5 RestTemplate
RestTemplate is the most commonly used client in Spring projects, providing a high‑level API over HTTP libraries.
<code>RestTemplate restTemplate = new RestTemplate();
Map ret = restTemplate.getForObject(URI.create("http://localhost:8002/api/data"), Map.class);
System.out.println(ret);
</code>Using RestTemplateBuilder for additional configuration (timeouts, interceptors, etc.)
<code>RestTemplate restTemplate = new RestTemplateBuilder()
.setConnectTimeout(Duration.ofSeconds(5))
.setReadTimeout(Duration.ofSeconds(5))
.interceptors(List.of())
.build();
Map ret = restTemplate.getForObject(URI.create("http://localhost:8002/api/data"), Map.class);
System.out.println(ret);
</code>By default RestTemplate uses JDK URL, but it can be switched to Apache HttpClient or OkHttp.
2.6 WebClient
WebClient is a non‑blocking, reactive HTTP client introduced in Spring 5, offering a RestTemplate alternative with support for synchronous, asynchronous, and streaming scenarios.
Non‑blocking I/O
Reactive back‑pressure
High concurrency with fewer resources
Functional, lambda‑friendly API
Supports both sync and async interactions
Streaming request/response bodies
Built‑in HTTP client options include Reactor Netty, JDK HttpClient, Jetty Reactive HttpClient, Apache HttpComponents, or any custom ClientHttpConnector.
Simple request example:
<code>WebClient client = WebClient.create("http://localhost:8002");
client.get()
.uri("/api/data")
.retrieve()
.bodyToMono(String.class)
.subscribe(System.out::println);
</code>Configuration with timeout and error handling:
<code>HttpClient httpClient = HttpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);
WebClient client = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
client.get()
.uri("http://localhost:8002/api/data")
.retrieve()
.onStatus(HttpStatusCode::is4xxClientError, resp -> Mono.error(new RuntimeException("Client error")))
.bodyToMono(String.class)
.subscribe(System.out::println);
System.in.read();
</code>2.7 RestClient (Spring 6.1+)
RestClient is a new thread‑safe API introduced in Spring 6.1.
<code>RestClient client = RestClient.create();
ParameterizedTypeReference<Map<String, Object>> bodyType = new ParameterizedTypeReference<>() {};
Map<String, Object> ret = client.get()
.uri(URI.create("http://localhost:8002/api/data"))
.retrieve()
.body(bodyType);
</code>Builder allows default headers, interceptors, and base URL configuration.
<code>RestClient client = RestClient.builder()
.defaultHeader("x-api-token", "aaabbbccc111222")
.requestInterceptor((request, body, execution) -> execution.execute(request, body))
.baseUrl("http://localhost:8002")
.build();
</code>2.8 Http Interface
Define a Java interface with @HttpExchange methods and create a proxy via HttpServiceProxyFactory, which uses RestClient or WebClient under the hood.
<code>// Interface definition
public interface RemoteClient {
@GetExchange("/api/data")
Map<String, Object> queryInfo();
}
// Invocation
RestClient restClient = RestClient.builder().baseUrl("http://localhost:8002").build();
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(RestClientAdapter.create(restClient)).build();
RemoteClient client = factory.createClient(RemoteClient.class);
System.out.println(client.queryInfo());
</code>2.9 OpenFeign (stand‑alone)
OpenFeign (not Spring Cloud OpenFeign) can be used directly.
<code><dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>13.2.1</version>
</dependency>
</code> <code>// Interface definition
public interface RemoteClient {
@RequestLine("GET /api/data")
Map<String, Object> queryInfo();
}
// Call
RemoteClient client = Feign.builder()
.decoder(new JacksonDecoder())
.target(RemoteClient.class, "http://localhost:8002");
Map<String, Object> ret = client.queryInfo();
</code>2.10 Gateway Proxy
Gateway MVC can act as a proxy using ProxyExchange.
<code><dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-mvc</artifactId>
</dependency>
</code> <code>private URI uri = URI.create("http://localhost:8002");
@GetMapping("/api")
public ResponseEntity<?> proxy(ProxyExchange<byte[]> proxy) throws Exception {
return proxy.uri(uri.toString() + "/api/data").get();
}
</code>Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.