Of course! In Java, there are several ways to send a request to a URL, ranging from the classic, built-in libraries to modern, third-party libraries that are more powerful and easier to use.

Here's a comprehensive guide covering the most common methods, from basic to advanced.
Summary of Methods
| Method | Library | Pros | Cons | Best For |
|---|---|---|---|---|
HttpURLConnection |
Built-in (Java 1.1+) | No external dependencies, good for simple GET/POST. | Verbose, clunky API, requires manual stream handling. | Simple scripts, environments where you can't add dependencies. |
HttpClient |
Built-in (Java 11+) | Modern, fluent API, supports HTTP/2, asynchronous requests. | Still requires some manual handling of JSON/XML. | The modern standard for Java applications. Recommended for new projects. |
OkHttp |
Third-Party (Square) | Very easy to use, great features (connection pooling, retries), excellent documentation. | Adds an external dependency. | Most applications, especially Android or microservices. |
RestTemplate |
Spring Framework | Simple declarative model, integrates with Spring ecosystem. | Synchronous-only, considered legacy in newer Spring versions. | Legacy Spring applications. |
WebClient |
Spring Framework | Modern, non-blocking, reactive, great for performance-critical apps. | Steeper learning curve (reactive programming). | New Spring applications, especially Spring WebFlux. |
Using HttpURLConnection (The Classic Built-in Way)
This is the most basic way, available in all standard Java distributions. It's verbose but gets the job done for simple requests.
Example: Simple GET Request
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpURLConnectionExample {
public static void main(String[] args) {
try {
// 1. Create a URL object
URL url = new URL("https://jsonplaceholder.typicode.com/posts/1");
// 2. Open a connection to the URL
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 3. Set the request method
connection.setRequestMethod("GET");
// 4. Set request headers (optional)
connection.setRequestProperty("User-Agent", "MyJavaApp/1.0");
connection.setRequestProperty("Accept", "application/json");
// 5. Get the response code
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
// 6. Read the response
if (responseCode == HttpURLConnection.HTTP_OK) { // success
BufferedReader in = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// print result
System.out.println("Response Body: " + response.toString());
} else {
System.out.println("GET request failed");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Example: POST Request with JSON Body
// ... (imports are the same as above)
public class HttpURLConnectionPostExample {
public static void main(String[] args) {
try {
URL url = new URL("https://jsonplaceholder.typicode.com/posts");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json; utf-8");
connection.setRequestProperty("Accept", "application/json");
connection.setDoOutput(true); // This is crucial for POST requests
// JSON payload
String jsonInputString = "{\"title\": \"foo\", \"body\": \"bar\", \"userId\": 1}";
try (OutputStream os = connection.getOutputStream()) {
byte[] input = jsonInputString.getBytes("utf-8");
os.write(input, 0, input.length);
}
int responseCode = connection.getResponseCode();
System.out.println("POST Response Code: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_OK) {
try (BufferedReader br = new BufferedReader(
new InputStreamReader(connection.getInputStream(), "utf-8"))) {
StringBuilder response = new StringBuilder();
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
System.out.println("POST Response Body: " + response.toString());
}
} else {
System.out.println("POST request did not work.");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Using HttpClient (The Modern Built-in Way - Java 11+)
Java 11 introduced a new java.net.http.HttpClient that is modern, supports HTTP/2, and has a much cleaner API. This is the recommended built-in approach for new projects.
Example: Simple GET Request
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class HttpClientExample {
public static void main(String[] args) {
// 1. Create an HttpClient
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.connectTimeout(Duration.ofSeconds(10))
.build();
// 2. Create an HttpRequest
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
.header("Accept", "application/json")
.GET() // This is the default, but can be omitted
.build();
try {
// 3. Send the request and get the response
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// 4. Process the response
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response Body: " + response.body());
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
Example: Asynchronous GET Request
A key feature of HttpClient is its support for non-blocking asynchronous requests.
// ... (imports are the same as above)
public class HttpClientAsyncExample {
public static void main(String[] args) {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
.build();
// Send the request asynchronously
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body) // Process the body when received
.thenAccept(System.out::println) // Print the body
.join(); // Wait for the asynchronous operation to complete
}
}
Using OkHttp (The Popular Third-Party Library)
OkHttp is a fantastic, easy-to-use library from Square. It's widely used in the Android community and is a great choice for any Java project. It handles many complexities like connection pooling and retries automatically.
First, add the dependency to your project:
Maven (pom.xml):
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version> <!-- Use the latest version -->
</dependency>
Gradle (build.gradle):
implementation 'com.squareup.okhttp3:okhttp:4.12.0' // Use the latest version
Example: Simple GET Request
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
public class OkHttpExample {
public static void main(String[] args) {
// 1. Create an OkHttpClient
OkHttpClient client = new OkHttpClient();
// 2. Create a Request
Request request = new Request.Builder()
.url("https://jsonplaceholder.typicode.com/posts/1")
.build();
try (Response response = client.newCall(request).execute()) {
// 3. Execute the request
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
// 4. Get the response body
String responseBody = response.body().string();
System.out.println("Response Body: " + responseBody);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Example: POST Request with JSON Body
import okhttp3.*;
import java.io.IOException;
public class OkHttpPostExample {
public static void main(String[] args) {
OkHttpClient client = new OkHttpClient();
// JSON payload
String json = "{\"title\": \"foo\", \"body\": \"bar\", \"userId\": 1}";
MediaType JSON = MediaType.get("application/json; charset=utf-8");
RequestBody body = RequestBody.create(json, JSON);
Request request = new Request.Builder()
.url("https://jsonplaceholder.typicode.com/posts")
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
System.out.println("Response Body: " + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}
Using Spring Framework Libraries (RestTemplate & WebClient)
If you are working in a Spring Boot application, you have two excellent options.
RestTemplate (Legacy but still common)
RestTemplate is a synchronous HTTP client with a simple template method API. It's being replaced by WebClient but is still prevalent in existing code.
Note: RestTemplate is not enabled by default in Spring Boot 3+. You need to add @Bean to enable it.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
// Enable RestTemplate
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@RestController
class MyController {
private final RestTemplate restTemplate;
// Constructor injection is recommended
public MyController(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@GetMapping("/fetch-data")
public String fetchData() {
String url = "https://jsonplaceholder.typicode.com/posts/1";
// For simple JSON, RestTemplate can directly map to a POJO
// For a String response, use String.class
String result = restTemplate.getForObject(url, String.class);
return "Fetched Data: " + result;
}
}
WebClient (Modern & Recommended for Spring)
WebClient is a non-blocking, reactive HTTP client introduced in Spring 5. It's the future of HTTP communication in Spring and is ideal for building high-performance, scalable applications.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@SpringBootApplication
public class MyWebClientApplication {
public static void main(String[] args) {
SpringApplication.run(MyWebClientApplication.class, args);
}
}
@RestController
class MyWebController {
// WebClient is a bean, you can inject it directly
private final WebClient webClient;
public MyWebController(WebClient.Builder webClientBuilder) {
// Create a WebClient instance
this.webClient = webClientBuilder.baseUrl("https://jsonplaceholder.typicode.com").build();
}
@GetMapping("/fetch-data-reactive")
public Mono<String> fetchDataReactive() {
return this.webClient.get()
.uri("/posts/1")
.retrieve()
.bodyToMono(String.class);
}
}
Which One Should I Choose?
- For a quick, simple script or a legacy project:
HttpURLConnectionis fine, butHttpClient(Java 11+) is much better if you can. - For any new Java project (non-Spring):
OkHttpis the easiest and most feature-rich choice. If you can't add dependencies, useHttpClient. - For a new Spring Boot project: Use
WebClient. It's modern, performant, and the direction the Spring framework is heading. UseRestTemplateonly if you're maintaining an older application.
