Bloga geri dön

Java Uygulamalarında Proxy Ayarları: Spring Boot, OkHttp ve RestTemplate - Kod ile Tam Kılavuz

Kurumsal Java uygulamalarında proxy ayarları için kapsamlı rehber: Spring Boot, OkHttp, RestTemplate, WebClient — kod örnekleri ve proxy seçimi için önerilerle.

📅12 Ağustos 2026
```html

Kurumsal Java uygulamaları düzenli olarak dış API'lere erişir, veri ayrıştırır veya izole kurumsal ağlarda çalışır — ve bu durumların her birinde, bir noktada trafiğin bir proxy sunucusu üzerinden yönlendirilmesi sorunu ortaya çıkar. Java'da proxy ayarlamak basit bir görev gibi görünse de, RestTemplate, OkHttp ve WebClient'in farklı davrandığını ve JVM sistem özelliklerinin her yerde çalışmadığını gördüğünüzde işler karmaşıklaşır. Bu kılavuzda, belirli kod örnekleri, dikkat edilmesi gereken noktalar ve farklı görevler için uygun proxy türü seçimi hakkında öneriler bulacaksınız.

Java uygulamalarının proxyye neden ihtiyacı var

Java, kurumsal geliştirme için en önemli dillerden biri olmaya devam ediyor. Spring Boot hizmetleri, mikro hizmet mimarileri, batch görevleri, ETL boru hatları — bunların hepsi düzenli olarak dış dünyaya HTTP istekleri gönderir. Ve bu senaryoların her birinde, proxy belirli bir sorunu çözer:

  • Proxy geçidi zorunlu kurumsal ağlar. Birçok şirkette, tüm çıkış trafiği kurumsal bir proxy (Squid, Zscaler, BlueCoat) üzerinden geçer. Bu ayar yapılmadan uygulama internete çıkamaz.
  • Veri ayrıştırma ve toplama. Dış sitelerden veri toplayan hizmetler (fiyatlar, alıntılar, haberler), rate-limit ve IP engellerini aşmak için proxy kullanır.
  • Coğrafi test. QA ekipleri, API veya web sitesinin farklı bölgelerden nasıl davrandığını kontrol eder — proxy, gerekli ülkeden gelen isteği taklit etmeyi sağlar.
  • Hedef API tarafındaki kısıtlamaların aşılması. Bazı dış API'ler, bir IP'den gelen istek sayısına sınırlamalar koyar. Proxy döngüsü, yükü dağıtmaya yardımcı olur.
  • Güvenlik ve anonimlik. Dış hizmetlere erişirken uygulamanın gerçek IP'sini gizlemek, hassas entegrasyonlar için standart bir uygulamadır.

Göreve bağlı olarak, Java'da proxy ayarlama yaklaşımları önemli ölçüde farklılık gösterir. JVM küresel sistem özellikleri en basit seçenektir, ancak bazı HTTP istemcileriyle çalışmaz. OkHttp ve WebClient, açık bir yapılandırma gerektirir. Her durumu sırayla inceleyelim.

JVM sistem özellikleri ile küresel ayarlama

Java uygulamasının tüm HTTP trafiğini bir proxy üzerinden yönlendirmenin en hızlı yolu, JVM sistem özelliklerini kullanmaktır. Bu, standart HttpURLConnection ve bunu arka planda kullanan birçok kütüphane için çalışır.

Proxy ayarlamak için birkaç yol vardır:

1. JVM argümanları ile başlatma sırasında:

java -Dhttp.proxyHost=proxy.example.com \
     -Dhttp.proxyPort=8080 \
     -Dhttps.proxyHost=proxy.example.com \
     -Dhttps.proxyPort=8080 \
     -Dhttp.nonProxyHosts="localhost|127.0.0.1|*.internal.corp" \
     -jar myapp.jar

2. Uygulama kodu üzerinden (örneğin, main metodunda veya @PostConstruct içinde):

System.setProperty("http.proxyHost", "proxy.example.com");
System.setProperty("http.proxyPort", "8080");
System.setProperty("https.proxyHost", "proxy.example.com");
System.setProperty("https.proxyPort", "8080");
// Hariç tutulanlar — proxy üzerinden geçmemesi gereken hostlar
System.setProperty("http.nonProxyHosts", "localhost|127.0.0.1|*.internal.corp");

3. Spring Boot'taki application.properties dosyası üzerinden (sonrasında @PostConstruct ile uygulanır):

# application.properties
proxy.host=proxy.example.com
proxy.port=8080
proxy.username=user
proxy.password=secret

⚠️ Bilinmesi gerekenler

JVM sistem özellikleri yalnızca HttpURLConnection için çalışır. OkHttp, Apache HttpClient ve Reactor Netty (WebClient) bu özellikleri görmezden gelir — bunlar için aşağıda açıklanan açık bir yapılandırma gereklidir.

Proxy kimlik doğrulaması gerektiriyorsa, Authenticator kullanın:

Authenticator.setDefault(new Authenticator() {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        if (getRequestorType() == RequestorType.PROXY) {
            return new PasswordAuthentication("username", "password".toCharArray());
        }
        return null;
    }
});

Spring Boot'ta proxy: RestTemplate ve Apache HttpClient

RestTemplate, Spring'deki standart senkron HTTP istemcisidir. Varsayılan olarak SimpleClientHttpRequestFactory kullanır, bu da HttpURLConnection'a dayanır ve JVM sistem özelliklerini okur. Ancak daha esnek bir yapılandırma (zaman aşımı, bağlantı havuzu, kimlik doğrulamalı proxy) için Apache HttpClient kullanılması önerilir.

Maven bağımlılığı:

<dependency>
    <groupId>org.apache.httpcomponents.client5</groupId>
    <artifactId>httpclient5</artifactId>
    <version>5.3.1</version>
</dependency>

Apache HttpClient 5 ile proxy ile RestTemplate yapılandırması:

@Configuration
public class RestTemplateConfig {

    @Value("${proxy.host}")
    private String proxyHost;

    @Value("${proxy.port}")
    private int proxyPort;

    @Value("${proxy.username:}")
    private String proxyUsername;

    @Value("${proxy.password:}")
    private String proxyPassword;

    @Bean
    public RestTemplate restTemplate() {
        HttpHost proxy = new HttpHost("http", proxyHost, proxyPort);

        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        if (!proxyUsername.isEmpty()) {
            credentialsProvider.setCredentials(
                new AuthScope(proxyHost, proxyPort),
                new UsernamePasswordCredentials(proxyUsername, proxyPassword.toCharArray())
            );
        }

        CloseableHttpClient httpClient = HttpClients.custom()
            .setProxy(proxy)
            .setDefaultCredentialsProvider(credentialsProvider)
            .build();

        HttpComponentsClientHttpRequestFactory factory =
            new HttpComponentsClientHttpRequestFactory(httpClient);
        factory.setConnectTimeout(5000);
        factory.setReadTimeout(10000);

        return new RestTemplate(factory);
    }
}

Bu yapılandırma, proxy parametrelerini application.properties veya ortam değişkenlerine taşımayı sağlar; bu, farklı proxy'lere sahip prod/staging/dev ortamları için kritik öneme sahiptir.

Bazı isteklerin proxy üzerinden, diğerlerinin ise doğrudan gitmesini istiyorsanız, farklı isimlere sahip iki ayrı RestTemplate bean'i oluşturun ve gerekli olanı enjekte etmek için @Qualifier kullanın.

Spring WebClient'ta proxy (reaktif yığın)

WebClient, Reactor Netty üzerine inşa edilmiş reaktif bir HTTP istemcisidir. JVM sistem özelliklerini proxy için okumaz — yapılandırma, istemci oluşturulurken ProxyProvider aracılığıyla yapılır.

Bağımlılık (spring-boot-starter-webflux içinde bulunur):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

HTTP proxy ile WebClient yapılandırması:

@Configuration
public class WebClientConfig {

    @Bean
    public WebClient webClient() {
        HttpClient httpClient = HttpClient.create()
            .proxy(proxy -> proxy
                .type(ProxyProvider.Proxy.HTTP)
                .host("proxy.example.com")
                .port(8080)
                .username("user")
                .password(user -> "password")
            );

        ClientHttpConnector connector =
            new ReactorClientHttpConnector(httpClient);

        return WebClient.builder()
            .clientConnector(connector)
            .build();
    }
}

WebClient'ta SOCKS5 proxy için:

HttpClient httpClient = HttpClient.create()
    .proxy(proxy -> proxy
        .type(ProxyProvider.Proxy.SOCKS5)
        .host("socks5.proxy.example.com")
        .port(1080)
        .username("user")
        .password(user -> "password")
    );

💡 Yapılandırma önerisi

Reaktif uygulamalarda, farklı dış hizmetler için farklı proxy'lerle birden fazla WebClient örneği oluşturmak sıkça gereklidir. WebClient.Builder'ı prototip bean olarak kullanın ve ayarları .mutate() ile geçersiz kılın.

OkHttp'de proxy ayarlama

OkHttp, birçok Java ve Android uygulaması tarafından kullanılan popüler bir HTTP kütüphanesidir ve bazı Spring entegrasyonları (örneğin, OkHttp arka ucu ile Feign) tarafından da kullanılmaktadır. Kendi proxy ayarlama mekanizmasına sahiptir ve JVM sistem özelliklerini de okumaz.

OkHttp'de HTTP/HTTPS proxy için temel ayar:

import okhttp3.*;
import java.net.InetSocketAddress;
import java.net.Proxy;

// Proxy oluşturma
Proxy proxy = new Proxy(
    Proxy.Type.HTTP,
    new InetSocketAddress("proxy.example.com", 8080)
);

// Proxy kimlik doğrulaması
Authenticator proxyAuthenticator = (route, response) -> {
    String credential = Credentials.basic("username", "password");
    return response.request().newBuilder()
        .header("Proxy-Authorization", credential)
        .build();
};

// İstemciyi oluşturma
OkHttpClient client = new OkHttpClient.Builder()
    .proxy(proxy)
    .proxyAuthenticator(proxyAuthenticator)
    .connectTimeout(10, TimeUnit.SECONDS)
    .readTimeout(30, TimeUnit.SECONDS)
    .build();

// İstek örneği
Request request = new Request.Builder()
    .url("https://api.example.com/data")
    .build();

try (Response response = client.newCall(request).execute()) {
    System.out.println(response.body().string());
}

Spring Boot ile OkHttp entegrasyonu üzerinden bean:

@Configuration
@ConditionalOnProperty(name = "proxy.enabled", havingValue = "true")
public class OkHttpConfig {

    @Value("${proxy.host}")
    private String proxyHost;

    @Value("${proxy.port}")
    private int proxyPort;

    @Bean
    public OkHttpClient okHttpClient() {
        Proxy proxy = new Proxy(
            Proxy.Type.HTTP,
            new InetSocketAddress(proxyHost, proxyPort)
        );

        return new OkHttpClient.Builder()
            .proxy(proxy)
            .connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES))
            .build();
    }
}

@ConditionalOnProperty özelliğine dikkat edin — bu, kodu değiştirmeden proxy'yi yalnızca gerekli ortamlarda etkinleştirmeyi sağlar.

Eğer OkHttp'yi konut proxy'leri ile veri ayrıştırma için kullanıyorsanız, bağlantı havuzunu doğru bir şekilde ayarlamak önemlidir. Konut proxy'leri genellikle veri merkezi proxy'lerine göre daha yüksek gecikmeye sahiptir, bu nedenle zaman aşımını artırın ve havuz boyutunu azaltın, böylece mevcut bağlantıları tüketmeyin.

Java'da SOCKS5 proxy: özellikler ve örnekler

SOCKS5, HTTP proxy'ye göre daha düşük seviyeli bir protokoldür. Taşıma katmanında çalışır ve her türlü protokolü (HTTP, HTTPS, FTP vb.) destekler ve ayrıca proxy tarafında DNS çözümlemesi yapar. Java uygulamaları için SOCKS5, yalnızca HTTP'yi değil, diğer TCP bağlantılarını da proxy'lemek gerektiğinde özellikle faydalıdır.

SOCKS5, JVM sistem özellikleri üzerinden:

System.setProperty("socksProxyHost", "socks5.proxy.example.com");
System.setProperty("socksProxyPort", "1080");
System.setProperty("java.net.socks.username", "user");
System.setProperty("java.net.socks.password", "password");

OkHttp'de SOCKS5 (java.net.Proxy üzerinden):

Proxy socks5Proxy = new Proxy(
    Proxy.Type.SOCKS,
    new InetSocketAddress("socks5.proxy.example.com", 1080)
);

OkHttpClient client = new OkHttpClient.Builder()
    .proxy(socks5Proxy)
    .build();

SOCKS5 ve DNS ile ilgili önemli bir özellik: Java varsayılan olarak DNS'i yerel olarak çözer ve proxy üzerinden yalnızca IP adresini gönderir. Bu, gerçek DNS isteğini açığa çıkarabilir. DNS çözümlemesinin de proxy üzerinden gitmesini istiyorsanız, OkHttp ile aşağıdaki yaklaşımı kullanın:

// SOCKS5 üzerinden çözümlemeyi zorlayan özel DNS
OkHttpClient client = new OkHttpClient.Builder()
    .proxy(socks5Proxy)
    .dns(hostname -> {
        // Çözülmemiş hostu döndür — OkHttp bunu proxy'ye iletecek
        return Collections.singletonList(InetAddress.getByName(hostname));
    })
    .build();

SOCKS5 ve HTTP proxy'yi ne zaman seçmeli

Kriter HTTP Proxy SOCKS5 Proxy
Protokoller HTTP/HTTPS Herhangi bir TCP/UDP
Proxy üzerinden DNS Uygulamaya bağlı Destekleniyor
Java ile uyumluluk Yerel Yerel (java.net.Proxy.Type.SOCKS)
Kullanım Kurumsal geçitler, web ayrıştırma Anonimlik, standart dışı protokoller

Java uygulamalarında proxy döngüsü

Uygulama bir kaynağa çok sayıda istek gönderiyorsa, tek bir proxy IP'sinin kullanılması hızlı bir şekilde engellemeye neden olur. Proxy döngüsü — farklı IP adresleri arasında geçiş yapmak — bu sorunu çözer. Java'da bu birkaç şekilde uygulanabilir.

Seçenek 1: Döngüsel proxy uç noktası üzerinden döngü

En basit yaklaşım, her istekte veya belirli bir aralıkta IP'yi otomatik olarak değiştiren tek bir uç noktaya sahip bir proxy sağlayıcısı kullanmaktır. Tek bir host ve port belirtirsiniz ve döngü sağlayıcı tarafında gerçekleşir. Döngü için herhangi bir kod yazmanıza gerek yoktur.

Seçenek 2: Proxy listesi üzerinden uygulama tarafında döngü

@Component
public class ProxyRotator {

    private final List<ProxyConfig> proxies;
    private final AtomicInteger counter = new AtomicInteger(0);

    public ProxyRotator(@Value("${proxy.list}") List<String> proxyList) {
        this.proxies = proxyList.stream()
            .map(this::parseProxy)
            .collect(Collectors.toList());
    }

    public OkHttpClient getClientWithNextProxy() {
        int index = counter.getAndIncrement() % proxies.size();
        ProxyConfig config = proxies.get(index);

        Proxy proxy = new Proxy(
            Proxy.Type.HTTP,
            new InetSocketAddress(config.getHost(), config.getPort())
        );

        return new OkHttpClient.Builder()
            .proxy(proxy)
            .build();
    }

    private ProxyConfig parseProxy(String proxyStr) {
        // "host:port" veya "user:pass@host:port" biçimindeki dizeyi ayrıştırma
        String[] parts = proxyStr.split(":");
        return new ProxyConfig(parts[0], Integer.parseInt(parts[1]));
    }
}

Seçenek 3: ProxySelector üzerinden döngü

Java, ProxySelector adında yerleşik bir mekanizma sağlar; bu, hedef URL'ye göre dinamik olarak proxy seçmeyi mümkün kılar. Bu, HttpURLConnection ve Apache HttpClient ile çalışır:

ProxySelector.setDefault(new ProxySelector() {
    private final List<Proxy> proxyPool = Arrays.asList(
        new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy1.example.com", 8080)),
        new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy2.example.com", 8080)),
        new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy3.example.com", 8080))
    );
    private final AtomicInteger idx = new AtomicInteger(0);

    @Override
    public List<Proxy> select(URI uri) {
        // Alan adına göre seçim mantığı eklenebilir
        int i = idx.getAndIncrement() % proxyPool.size();
        return Collections.singletonList(proxyPool.get(i));
    }

    @Override
    public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
        // Erişilemeyen proxy için işleme mantığı
        log.warn("Proxy failed: {}", sa);
    }
});

Java görevleri için hangi proxy türünü seçmeli

Proxy türü seçimi, belirli bir göreve bağlıdır. Kurumsal Java uygulamaları için genellikle üç ana tür düşünülmektedir:

Proxy Türü Hız Anonimlik En iyi kullanım alanı
Veri merkezi Yüksek Orta Açık veri ayrıştırma, API test etme, yüksek yük
Konut Orta Yüksek Korunan sitelerden veri ayrıştırma, coğrafi test, engelleri aşma
Mobil Orta Maksimum Mobil API'lerle entegrasyon, sıkı anti-fraud korumalı hizmetler

Görev türleri için pratik öneriler:

  • Kurumsal geçit (Squid, Zscaler): Proxy türü IT departmanı tarafından belirlenir. Apache HttpClient veya JVM sistem özellikleri aracılığıyla kimlik doğrulamalı HTTP proxy kullanın.
  • Açık veri ayrıştırma (haberler, alıntılar, açık API'ler): Veri merkezi proxy'leri, hız ve maliyet açısından en iyi seçimdir.
  • E-ticaret ayrıştırma (Wildberries, Ozon, Amazon): Döngü ile konut proxy'leri. Bu platformlar, veri merkezi IP'lerini aktif olarak engeller.
  • Coğrafi test (yerelleştirme kontrolü, bölgelere göre fiyatlar): Ülke/şehir seçimi ile konut proxy'leri.
  • Mobil hizmetler ve uygulamalarla entegrasyon: Mobil proxy'ler — gerçek mobil ağlardan IP'ler, gerçek kullanıcıları en iyi şekilde taklit eder.

Java'da proxy ayarlarken sık karşılaşılan hatalar ve nasıl düzeltileceği

Deneyimli geliştiriciler bile Java'da proxy ayarlarken aynı sorunlarla karşılaşabilir. En yaygın sorunları inceleyelim.

1. Proxy ayarlandı, ancak trafik yine de doğrudan gidiyor

Sebep: JVM sistem özelliklerini ayarladınız, ancak OkHttp veya Reactor Netty (WebClient) kullanıyorsunuz, bu da onları görmezden geliyor.
Çözüm: Proxy'yi açıkça belirli bir HTTP istemcisinin yapılandırmasında ayarlayın, yukarıdaki bölümlerde gösterildiği gibi.

2. HTTPS üzerinden proxy ile javax.net.ssl.SSLHandshakeException

Sebep: Kurumsal proxy, SSL denetimi (MITM) yaparak sertifikayı değiştirir. Java, kurumsal CA'ya güvenmez.
Çözüm: Kurumsal sertifikayı Java truststore'a içe aktarın:

keytool -import -trustcacerts \
  -alias corporate-ca \
  -file corporate-ca.crt \
  -keystore $JAVA_HOME/lib/security/cacerts \
  -storepass changeit

3. java.net.ConnectException: Bağlantı reddedildi

Sebep: Proxy'nin yanlış host veya portu; proxy sunucusu erişilemez; güvenlik duvarı bağlantıyı engelliyor.
Tanı:

# Proxy'nin erişilebilirliğini kontrol etme
curl -x http://proxy.example.com:8080 https://httpbin.org/ip

# Ya da telnet ile
telnet proxy.example.com 8080

4. Proxy HTTP için çalışıyor, ancak HTTPS için çalışmıyor

Sebep: Sadece http.proxyHost/Port özellikleri ayarlandı, ancak https.proxyHost/Port ayarlanmadı.
Çözüm: Her iki özellik setini de ayarlayın. HTTPS üzerinden HTTP proxy ile CONNECT tünelleme yöntemi kullanılır — proxy'nin bunu desteklediğinden emin olun.

5. 407 Proxy Kimlik Doğrulaması Gerekiyor

Sebep: Proxy kimlik doğrulaması gerektiriyor, ancak ayarlanmamış.
Çözüm: JVM sistem özellikleri için Authenticator ekleyin veya Apache HttpClient için CredentialsProvider veya OkHttp için proxyAuthenticator ayarlayın (örnekler yukarıda).

6. Proxy döngüsünde bellek sızıntısı

Sebep: Her istekte yeni bir OkHttpClient örneği oluşturuluyor. Her istemci kendi bağlantı ve thread havuzunu tutar.
Çözüm: İstemcileri yeniden kullanın. Birkaç istemciden (her proxy için bir tane) oluşan bir havuz oluşturun ve bunları döndürün, yeni istemciler oluşturmayın.

7. Tanılama için hata ayıklama kaydını etkinleştirme

# application.properties — proxy tanılama için logları etkinleştir
logging.level.org.apache.http=DEBUG
logging.level.org.apache.http.wire=DEBUG
logging.level.reactor.netty.http.client=DEBUG

# JVM için — sistem özelliği
-Djava.net.debug=all

Sonuç

Java uygulamalarında proxy ayarlamak, arka planda hangi HTTP istemcisinin kullanıldığını anlamayı gerektirir. JVM sistem özellikleri, HttpURLConnection için hızlı bir başlangıçtır, ancak OkHttp, WebClient ve Apache HttpClient açık bir yapılandırma gerektirir. Kurumsal uygulamalar için proxy parametrelerini application.properties dosyasına taşımak ve farklı ortamlar için Spring profilleri kullanmak önerilir. Proxy döngüsünü, döngüsel uç noktaya sahip bir sağlayıcıya devretmek — bunu kendiniz uygulamaktan daha kolay ve güvenilir.

Eğer Java uygulamanız korunan platformlardan veri ayrıştırıyorsa veya dış isteklere yüksek anonimlik gerektiriyorsa, konut proxy'lerini değerlendirmenizi öneririz — bunlar gerçek ev kullanıcılarının IP'lerine sahiptir, bu da anti-fraud sistemleri tarafından engellenme olasılığını önemli ölçüde azaltır. Yüksek hacimli açık veri ayrıştırma için en iyi seçenek veri merkezi proxy'leridir — bunlar, daha düşük trafik maliyeti ile maksimum hız sağlar.

```