URLConnection, HttpURLConnection ve HttpClient
URL'leri ayrıştırmayı öğrendik; şimdi onlara bağlanıp veri alıp vermeyi ele alıyoruz. Bir mobil uygulamanın API'ye istek atması, bir servisin başka bir servisi çağırması — hepsi HTTP üzerinden olur. Java bunu üç katma…
URLConnection, HttpURLConnection ve HttpClient
URL'leri ayrıştırmayı öğrendik; şimdi onlara bağlanıp veri alıp vermeyi ele alıyoruz. Bir
mobil uygulamanın API'ye istek atması, bir servisin başka bir servisi çağırması — hepsi HTTP
üzerinden olur. Java bunu üç katmanda sunar: düşük seviyeli URLConnection, HTTP'ye özel
HttpURLConnection (klasik) ve modern java.net.http.HttpClient (Java 11+). Örneklerin hepsi,
internet gerektirmesin diye aynı JVM'de yerel bir HTTP sunucusu (JDK'nin HttpServer'ı)
başlatıp ona bağlanır — yani gördüğün her şey gerçek bir HTTP istek/cevabıdır.
HttpURLConnection (klasik)
Java'nın uzun yıllar standart HTTP istemcisi. Akış: URI → URL → openConnection(). GET için:
URI uri = URI.create("http://localhost:" + port + "/merhaba"); HttpURLConnection con = (HttpURLConnection) uri.toURL().openConnection(); con.setRequestMethod("GET"); con.setRequestProperty("Accept", "application/json"); // istek başlığı int kod = con.getResponseCode(); // 200, 404 ... String govde = new String(con.getInputStream().readAllBytes(), StandardCharsets.UTF_8); con.disconnect();
Örnek 1 (./Ornek1.java) yerel bir sunucuya GET isteği atar; durum kodunu, Content-Type
başlığını ve JSON yanıt gövdesini okur.
POST (veri gönderme)
Gövde göndermek için setDoOutput(true) ile çıkış akışı açılır ve istek gövdesi yazılır:
con.setRequestMethod("POST"); con.setRequestProperty("Content-Type", "application/json"); con.setDoOutput(true); try (OutputStream os = con.getOutputStream()) { os.write("{\"urun\":\"Klavye\"}".getBytes(StandardCharsets.UTF_8)); }
Örnek 2 (./Ornek2.java) bir JSON gövdesini POST eder; sunucu 201 Created döndürüp gövdeyi
yansıtır. PUT/DELETE için setRequestMethod("PUT"/"DELETE") kullanılır.
HttpURLConnectionişini görür ama hantaldır: stream yönetimi, hata gövdesini ayrı okuma (getErrorStream), zaman aşımı ayarları... Modern projelerdeHttpClienttercih edilir.
HttpClient (modern, Java 11+)
Java 11 ile gelen java.net.http.HttpClient, temiz bir builder API'si, HTTP/2 desteği, zaman
aşımı ve asenkron istek sunar. Üç ana tip: HttpClient (bir kez oluştur, paylaş),
HttpRequest (istek), HttpResponse (yanıt):
HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build(); HttpRequest get = HttpRequest.newBuilder(URI.create(url)).GET().build(); HttpResponse<String> cevap = client.send(get, HttpResponse.BodyHandlers.ofString()); cevap.statusCode(); cevap.body(); HttpRequest post = HttpRequest.newBuilder(URI.create(url)) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{...}")) .build();
sendAsync(...) ise bloklamadan, bir CompletableFuture döndürür. Örnek 3 (./Ornek3.java)
GET, POST ve asenkron GET'i yerel sunucuya karşı gösterir.
| HttpURLConnection | HttpClient (11+) | |
|---|---|---|
| API | Eski, hantal | Temiz, builder |
| HTTP/2 | Yok | Var |
| Asenkron | Yok | sendAsync + CompletableFuture |
| Timeout | Sınırlı | Yerleşik |
| Öneri | Legacy | Yeni projeler |
Bu katman ile uygulama çatıları
Bu sınıflar HTTP'nin "ham" Java karşılığıdır. Üretimde genelde daha üst seviye istemciler
kullanılır: Spring'de RestClient (yeni), WebClient (reaktif) veya RestTemplate (klasik);
bu araçlar JSON↔nesne dönüşümünü, hata yönetimini ve yapılandırmayı senin için yapar. Ama hepsinin
altında işte bu HttpClient/HttpURLConnection mekanizması vardır.
Önemli ayrıntılar
- Hata gövdesi:
HttpURLConnection'da 4xx/5xx durumundagetInputStream()exception atar; hata gövdesinigetErrorStream()ile okursun.HttpClientbu ayrımı yapmaz (gövdeyi her durumda verir). - Zaman aşımı: Üretimde mutlaka bağlantı ve okuma zaman aşımı ayarla; aksi halde yavaş bir sunucu uygulamanı kilitleyebilir.
- Kaynak kapatma:
HttpURLConnection'da stream'leri kapat /disconnect()çağır.
Özet
HTTP kaynaklarına bağlanmayı üç yolla gördük: klasik HttpURLConnection ile GET (Örnek 1) ve POST
(Örnek 2), modern HttpClient ile GET/POST/asenkron (Örnek 3) — hepsi yerel bir HTTP sunucusuna
karşı, gerçek istek/cevaplarla. Yeni projelerde HttpClient'ı (ve uygulama düzeyinde Spring'in
RestClient/WebClient'ını) tercih et. Bu, Java ağ programlama bölümünü tamamlıyor: adresleri
çözmekten (InetAddress), soketlerle ham iletişime (TCP/UDP), URL'leri ayrıştırmaya ve HTTP
istemcilerine kadar.
▶ Kod Örnekleri(3)
Ornek1
çalıştırılabilir1// Ornek1: HttpURLConnection ile GET — bir HTTP kaynağını okumak.
2// İnternet gerekmesin diye, aynı JVM'de yerel bir HTTP sunucusu (JDK'nin HttpServer'ı) başlatıp ona bağlanırız.
3// Çalıştırma: java Ornek1.java
4import com.sun.net.httpserver.HttpServer;
5import java.io.OutputStream;
6import java.net.HttpURLConnection;
7import java.net.InetSocketAddress;
8import java.net.URI;
9import java.nio.charset.StandardCharsets;
10
11public class Ornek1 {
12
13 public static void main(String[] args) throws Exception {
14 // --- Yerel HTTP sunucusu (gerçek bir web sunucusunu taklit eder) ---
15 HttpServer sunucu = HttpServer.create(new InetSocketAddress("localhost", 0), 0);
16 int port = sunucu.getAddress().getPort();
17 sunucu.createContext("/merhaba", exchange -> {
18 String cevap = "{\"mesaj\":\"Merhaba HTTP!\"}";
19 byte[] govde = cevap.getBytes(StandardCharsets.UTF_8);
20 exchange.getResponseHeaders().add("Content-Type", "application/json; charset=utf-8");
21 exchange.sendResponseHeaders(200, govde.length); // 200 OK + içerik uzunluğu
22 try (OutputStream os = exchange.getResponseBody()) { os.write(govde); }
23 });
24 sunucu.start();
25 System.out.println("Yerel HTTP sunucusu: http://localhost:" + port + "/merhaba\n");
26
27 // --- HttpURLConnection ile GET isteği ---
28 URI uri = URI.create("http://localhost:" + port + "/merhaba");
29 HttpURLConnection con = (HttpURLConnection) uri.toURL().openConnection();
30 con.setRequestMethod("GET");
31 con.setRequestProperty("Accept", "application/json"); // istek başlığı (header)
32
33 int kod = con.getResponseCode();
34 System.out.println("Durum kodu : " + kod + " " + con.getResponseMessage());
35 System.out.println("Content-Type : " + con.getHeaderField("Content-Type"));
36
37 String govde = new String(con.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
38 System.out.println("Yanıt gövdesi : " + govde);
39 con.disconnect();
40
41 sunucu.stop(0);
42 System.out.println("""
43
44 --- HttpURLConnection ile GET ---
45 Akış: URI -> URL -> openConnection() -> HttpURLConnection.
46 setRequestMethod("GET"), setRequestProperty(...) ile başlık eklenir.
47 getResponseCode() durum kodunu, getInputStream() yanıt gövdesini verir.
48 Bu, Java'nın klasik HTTP istemcisidir; biraz hantaldır (sonraki örnekte modern HttpClient).""");
49 }
50}Ornek2
çalıştırılabilir1// Ornek2: HttpURLConnection ile POST — sunucuya veri göndermek.
2// Yerel sunucu gelen gövdeyi geri yansıtır (echo). (İnternet gerekmez.)
3// Çalıştırma: java Ornek2.java
4import com.sun.net.httpserver.HttpServer;
5import java.io.OutputStream;
6import java.net.HttpURLConnection;
7import java.net.InetSocketAddress;
8import java.net.URI;
9import java.nio.charset.StandardCharsets;
10
11public class Ornek2 {
12
13 public static void main(String[] args) throws Exception {
14 HttpServer sunucu = HttpServer.create(new InetSocketAddress("localhost", 0), 0);
15 int port = sunucu.getAddress().getPort();
16 // POST handler: gelen gövdeyi okuyup "alındı: ..." olarak geri döner.
17 sunucu.createContext("/siparis", exchange -> {
18 String gelen = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
19 String cevap = "{\"durum\":\"alindi\",\"echo\":" + gelen + "}";
20 byte[] govde = cevap.getBytes(StandardCharsets.UTF_8);
21 exchange.getResponseHeaders().add("Content-Type", "application/json; charset=utf-8");
22 exchange.sendResponseHeaders(201, govde.length); // 201 Created
23 try (OutputStream os = exchange.getResponseBody()) { os.write(govde); }
24 });
25 sunucu.start();
26
27 URI uri = URI.create("http://localhost:" + port + "/siparis");
28 HttpURLConnection con = (HttpURLConnection) uri.toURL().openConnection();
29 con.setRequestMethod("POST");
30 con.setRequestProperty("Content-Type", "application/json; charset=utf-8");
31 con.setDoOutput(true); // gövde göndereceğiz -> çıkış akışını aç
32
33 String istekGovdesi = "{\"urun\":\"Klavye\",\"adet\":2}";
34 try (OutputStream os = con.getOutputStream()) {
35 os.write(istekGovdesi.getBytes(StandardCharsets.UTF_8)); // gövdeyi yaz
36 }
37
38 System.out.println("Gönderilen: " + istekGovdesi);
39 System.out.println("Durum kodu: " + con.getResponseCode() + " " + con.getResponseMessage());
40 String cevap = new String(con.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
41 System.out.println("Yanıt : " + cevap);
42 con.disconnect();
43 sunucu.stop(0);
44
45 System.out.println("""
46
47 --- HttpURLConnection ile POST ---
48 setDoOutput(true) ile gövde gönderimi açılır; getOutputStream()'e istek gövdesi yazılır.
49 Content-Type başlığı, gönderdiğin verinin türünü belirtir (burada JSON).
50 Sunucu 201 Created döndürür ve gövdemizi yansıtır.
51 PUT/DELETE için setRequestMethod("PUT"/"DELETE") kullanılır.""");
52 }
53}Ornek3
çalıştırılabilir1// Ornek3: Modern HttpClient (Java 11) — HttpURLConnection'a temiz, güçlü alternatif.
2// Çalıştırma: java Ornek3.java
3import com.sun.net.httpserver.HttpServer;
4import java.io.OutputStream;
5import java.net.InetSocketAddress;
6import java.net.URI;
7import java.net.http.HttpClient;
8import java.net.http.HttpRequest;
9import java.net.http.HttpResponse;
10import java.nio.charset.StandardCharsets;
11import java.time.Duration;
12
13public class Ornek3 {
14
15 public static void main(String[] args) throws Exception {
16 HttpServer sunucu = HttpServer.create(new InetSocketAddress("localhost", 0), 0);
17 int port = sunucu.getAddress().getPort();
18 sunucu.createContext("/api", exchange -> {
19 String metot = exchange.getRequestMethod();
20 String gelen = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
21 String cevap = "{\"metot\":\"" + metot + "\",\"echo\":\"" + gelen + "\"}";
22 byte[] b = cevap.getBytes(StandardCharsets.UTF_8);
23 exchange.getResponseHeaders().add("Content-Type", "application/json");
24 exchange.sendResponseHeaders(200, b.length);
25 try (OutputStream os = exchange.getResponseBody()) { os.write(b); }
26 });
27 sunucu.start();
28 String taban = "http://localhost:" + port + "/api";
29
30 // HttpClient bir kez oluşturulur, yeniden kullanılır (HTTP/2, bağlantı havuzu, timeout...).
31 HttpClient client = HttpClient.newBuilder()
32 .connectTimeout(Duration.ofSeconds(5))
33 .build();
34
35 // --- GET ---
36 HttpRequest get = HttpRequest.newBuilder(URI.create(taban))
37 .header("Accept", "application/json")
38 .GET()
39 .build();
40 HttpResponse<String> getCevap = client.send(get, HttpResponse.BodyHandlers.ofString());
41 System.out.println("GET -> " + getCevap.statusCode() + " | " + getCevap.body());
42
43 // --- POST ---
44 HttpRequest post = HttpRequest.newBuilder(URI.create(taban))
45 .header("Content-Type", "application/json")
46 .POST(HttpRequest.BodyPublishers.ofString("{\"urun\":\"Mouse\"}"))
47 .build();
48 HttpResponse<String> postCevap = client.send(post, HttpResponse.BodyHandlers.ofString());
49 System.out.println("POST -> " + postCevap.statusCode() + " | " + postCevap.body());
50
51 // --- Asenkron istek (sendAsync + CompletableFuture) ---
52 client.sendAsync(get, HttpResponse.BodyHandlers.ofString())
53 .thenApply(HttpResponse::body)
54 .thenAccept(b -> System.out.println("Async GET -> " + b))
55 .join();
56
57 sunucu.stop(0);
58 System.out.println("""
59
60 --- Modern HttpClient (Java 11+) ---
61 HttpURLConnection'a göre çok daha temiz: builder API, HTTP/2, timeout, asenkron (sendAsync).
62 HttpClient (bir kez oluştur, paylaş) + HttpRequest (istek) + HttpResponse (yanıt).
63 BodyHandlers/BodyPublishers ile gövde okuma/yazma. Yeni projelerde tercih edilen yol budur.
64 (Spring tarafında bunun karşılığı RestClient/WebClient/RestTemplate'tir.)""");
65 }
66}