Torna al blog

Configurazione dei proxy nelle applicazioni Java: Spring Boot, OkHttp e RestTemplate - guida completa con codice

Guida completa alla configurazione dei proxy nelle applicazioni Java aziendali: Spring Boot, OkHttp, RestTemplate, WebClient - con esempi di codice e raccomandazioni per la scelta del proxy.

📅12 agosto 2026
```html

Le applicazioni Java aziendali accedono regolarmente a API esterne, analizzano dati o operano in reti aziendali isolate — e in ciascuno di questi casi, prima o poi, sorge la questione della routing del traffico attraverso un server proxy. Configurare un proxy in Java sembra un compito semplice, finché non ci si imbatte nel fatto che RestTemplate, OkHttp e WebClient si comportano in modo diverso e che le proprietà di sistema JVM non funzionano ovunque. In questa guida — esempi di codice concreti, spiegazione delle insidie e raccomandazioni sulla scelta del tipo di proxy per diverse esigenze.

Perché le applicazioni Java hanno bisogno di proxy

Java rimane uno dei principali linguaggi di sviluppo aziendale. I servizi Spring Boot, le architetture a microservizi, i task batch, i pipeline ETL — tutto ciò effettua regolarmente richieste HTTP verso il mondo esterno. E in ciascuno di questi scenari, il proxy risolve un compito specifico:

  • Reti aziendali con gateway proxy obbligatorio. In molte aziende, tutto il traffico in uscita passa attraverso un proxy aziendale (Squid, Zscaler, BlueCoat). Senza la sua configurazione, l'applicazione non potrà accedere a Internet.
  • Parsing e raccolta dati. I servizi che raccolgono dati da siti esterni (prezzi, quotazioni, notizie) utilizzano proxy per aggirare i limiti di richiesta e i blocchi per IP.
  • Geo-testing. I team QA verificano come l'API o il sito si comporta da diverse regioni — il proxy consente di emulare una richiesta dal paese desiderato.
  • Bypass delle restrizioni sul lato dell'API di destinazione. Alcune API esterne hanno limiti sul numero di richieste da un singolo IP. La rotazione dei proxy consente di distribuire il carico.
  • Sicurezza e anonimizzazione. Nascondere il reale IP dell'applicazione quando si accede a servizi esterni è una prassi standard per integrazioni sensibili.

A seconda del compito, gli approcci alla configurazione del proxy in Java variano notevolmente. Le proprietà di sistema JVM globali sono l'opzione più semplice, ma non funzionano con alcuni client HTTP. OkHttp e WebClient richiedono una configurazione esplicita. Analizziamo ciascun caso in ordine.

Impostazione globale tramite proprietà di sistema JVM

Il modo più veloce per indirizzare tutto il traffico HTTP dell'applicazione Java attraverso un proxy è utilizzare le proprietà di sistema JVM. Questo funziona per il HttpURLConnection standard e molte librerie che lo utilizzano sotto il cofano.

È possibile impostare il proxy in diversi modi:

1. Tramite argomenti JVM all'avvio:

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. Tramite codice dell'applicazione (ad esempio, nel metodo main o in @PostConstruct):

System.setProperty("http.proxyHost", "proxy.example.com");
System.setProperty("http.proxyPort", "8080");
System.setProperty("https.proxyHost", "proxy.example.com");
System.setProperty("https.proxyPort", "8080");
// Eccezioni — host che non devono passare attraverso il proxy
System.setProperty("http.nonProxyHosts", "localhost|127.0.0.1|*.internal.corp");

3. Tramite file application.properties in Spring Boot (con successiva applicazione tramite @PostConstruct):

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

⚠️ Importante sapere

Le proprietà di sistema JVM funzionano solo per HttpURLConnection. OkHttp, Apache HttpClient e Reactor Netty (WebClient) ignorano queste proprietà — per loro è necessaria una configurazione esplicita, descritta di seguito.

Se il proxy richiede autenticazione, utilizzare Authenticator:

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

Proxy in Spring Boot: RestTemplate e Apache HttpClient

RestTemplate è il client HTTP sincrono standard in Spring. Per impostazione predefinita utilizza SimpleClientHttpRequestFactory, che si basa su HttpURLConnection e legge le proprietà di sistema JVM. Tuttavia, per una configurazione più flessibile (timeout, pool di connessioni, proxy con autenticazione) è consigliabile utilizzare Apache HttpClient come backend.

Dipendenza in Maven:

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

Configurazione di RestTemplate con proxy tramite Apache HttpClient 5:

@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);
    }
}

Questa configurazione consente di estrarre i parametri del proxy in application.properties o variabili di ambiente, il che è critico per ambienti prod/staging/dev con proxy diversi.

Se è necessario che alcune richieste passino attraverso il proxy e altre direttamente, creare due bean separati RestTemplate con nomi diversi e utilizzare @Qualifier per iniettare quello necessario.

Proxy in Spring WebClient (stack reattivo)

WebClient è il client HTTP reattivo di Spring, costruito su Reactor Netty. Non legge le proprietà di sistema JVM per il proxy — la configurazione avviene tramite ProxyProvider durante la creazione del client.

Dipendenza (inclusa in spring-boot-starter-webflux):

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

Configurazione di WebClient con proxy HTTP:

@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();
    }
}

Per proxy SOCKS5 in WebClient:

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

💡 Consiglio per la configurazione

Nelle applicazioni reattive, è spesso necessario creare più istanze di WebClient con proxy diversi per diversi servizi esterni. Utilizzare WebClient.Builder come bean prototipo e sovrascrivere le impostazioni tramite .mutate().

Configurazione del proxy in OkHttp

OkHttp è una popolare libreria HTTP utilizzata da molte applicazioni Java e Android, nonché da alcune integrazioni Spring (ad esempio, Feign con backend OkHttp). Ha un proprio meccanismo di configurazione del proxy e non legge le proprietà di sistema JVM.

Impostazione di base del proxy HTTP/HTTPS in OkHttp:

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

// Creiamo il proxy
Proxy proxy = new Proxy(
    Proxy.Type.HTTP,
    new InetSocketAddress("proxy.example.com", 8080)
);

// Autenticazione del proxy
Authenticator proxyAuthenticator = (route, response) -> {
    String credential = Credentials.basic("username", "password");
    return response.request().newBuilder()
        .header("Proxy-Authorization", credential)
        .build();
};

// Creiamo il client
OkHttpClient client = new OkHttpClient.Builder()
    .proxy(proxy)
    .proxyAuthenticator(proxyAuthenticator)
    .connectTimeout(10, TimeUnit.SECONDS)
    .readTimeout(30, TimeUnit.SECONDS)
    .build();

// Esempio di richiesta
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());
}

Integrazione di OkHttp con Spring Boot tramite 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();
    }
}

Nota l'@ConditionalOnProperty — questo consente di abilitare il proxy solo negli ambienti necessari tramite configurazione, senza modificare il codice.

Se utilizzi OkHttp insieme a proxy residenziali per il parsing dei dati, è importante configurare correttamente il pool di connessioni. I proxy residenziali hanno spesso una latenza più alta rispetto a quelli dei data center, quindi aumenta i timeout e riduci la dimensione del pool per non esaurire le connessioni disponibili.

Proxy SOCKS5 in Java: caratteristiche ed esempi

SOCKS5 è un protocollo a livello inferiore rispetto al proxy HTTP. Funziona a livello di trasporto e supporta qualsiasi protocollo (HTTP, HTTPS, FTP, ecc.), oltre alla risoluzione DNS lato proxy. Per le applicazioni Java, SOCKS5 è particolarmente utile quando è necessario proxyare non solo HTTP, ma anche altre connessioni TCP.

SOCKS5 tramite proprietà di sistema JVM:

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");

SOCKS5 in OkHttp (tramite java.net.Proxy):

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

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

Caratteristica importante di SOCKS5 e DNS: Per impostazione predefinita, Java risolve DNS localmente e invia già l'indirizzo IP attraverso il proxy. Questo può rivelare la reale richiesta DNS. Per fare in modo che la risoluzione DNS avvenga anche tramite il proxy, utilizzare il seguente approccio con OkHttp:

// DNS personalizzato che forza la risoluzione tramite SOCKS5
OkHttpClient client = new OkHttpClient.Builder()
    .proxy(socks5Proxy)
    .dns(hostname -> {
        // Restituiamo l'host non risolto — OkHttp lo passerà al proxy
        return Collections.singletonList(InetAddress.getByName(hostname));
    })
    .build();

Quando scegliere SOCKS5 vs HTTP-proxy

Criterio HTTP-proxy SOCKS5-proxy
Protocolli HTTP/HTTPS Qualsiasi TCP/UDP
DNS tramite proxy Dipende dall'implementazione Supportato
Compatibilità con Java Nativa Nativa (java.net.Proxy.Type.SOCKS)
Utilizzo Gateway aziendali, web scraping Anonimizzazione, protocolli non standard

Rotazione dei proxy nelle applicazioni Java

Se l'applicazione effettua un gran numero di richieste a una singola risorsa, l'utilizzo di un solo IP proxy porterà rapidamente a un blocco. La rotazione dei proxy — il passaggio tra diversi indirizzi IP — risolve questo problema. In Java, questo può essere implementato in diversi modi.

Opzione 1: Rotazione tramite endpoint proxy rotante

L'approccio più semplice è utilizzare un fornitore di proxy con un unico endpoint, che cambia automaticamente IP ad ogni richiesta o dopo un intervallo specificato. Si specifica un host e una porta, e la rotazione avviene lato fornitore. Non è necessario scrivere alcun codice per la rotazione.

Opzione 2: Rotazione lato applicazione tramite lista di proxy

@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) {
        // Parsing della stringa nel formato "host:port" o "user:pass@host:port"
        String[] parts = proxyStr.split(":");
        return new ProxyConfig(parts[0], Integer.parseInt(parts[1]));
    }
}

Opzione 3: Rotazione tramite ProxySelector

Java fornisce un meccanismo integrato ProxySelector, che consente di scegliere dinamicamente il proxy in base all'URL di destinazione. Questo funziona con HttpURLConnection e Apache HttpClient:

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) {
        // È possibile aggiungere logica di selezione per dominio
        int i = idx.getAndIncrement() % proxyPool.size();
        return Collections.singletonList(proxyPool.get(i));
    }

    @Override
    public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
        // Logica di gestione del proxy non disponibile
        log.warn("Proxy failed: {}", sa);
    }
});

Quale tipo di proxy scegliere per le attività Java

La scelta del tipo di proxy dipende dal compito specifico. Per le applicazioni Java aziendali, si considerano generalmente tre tipi principali:

Tipo di proxy Velocità Anonimato Migliore per
Data center Alta Media Parsing di dati aperti, test di API, carichi elevati
Residenziali Media Alta Parsing di siti protetti, geo-testing, bypass di blocchi
Mobile Media Massima Integrazioni con API mobili, servizi con forte protezione antifrode

Raccomandazioni pratiche per i tipi di attività:

  • Gateway aziendale (Squid, Zscaler): Il tipo di proxy è determinato dal reparto IT. Utilizzare proxy HTTP con autenticazione tramite Apache HttpClient o proprietà di sistema JVM.
  • Parsing di dati pubblici (notizie, quotazioni, API aperte): I proxy dei data center sono la scelta ottimale per il rapporto velocità/costo.
  • Parsing di e-commerce (Wildberries, Ozon, Amazon): Proxy residenziali con rotazione. Queste piattaforme bloccano attivamente gli IP dei data center.
  • Geo-testing (verifica della localizzazione, prezzi per regione): Proxy residenziali con selezione di paese/città.
  • Integrazione con servizi e applicazioni mobili: I proxy mobili — IP da reti mobili reali imitano meglio gli utenti reali.

Errori comuni nella configurazione del proxy in Java e come risolverli

Anche gli sviluppatori esperti si imbattono negli stessi problemi durante la configurazione del proxy in Java. Analizziamo i più comuni.

1. Il proxy è configurato, ma il traffico va comunque direttamente

Motivo: Hai impostato le proprietà di sistema JVM, ma stai utilizzando OkHttp o Reactor Netty (WebClient), che le ignorano.
Soluzione: Configura esplicitamente il proxy nella configurazione del client HTTP specifico, come mostrato nelle sezioni precedenti.

2. javax.net.ssl.SSLHandshakeException durante HTTPS tramite proxy

Motivo: Il proxy aziendale esegue l'ispezione SSL (MITM), sostituendo il certificato. Java non si fida del CA aziendale.
Soluzione: Importa il certificato aziendale nel truststore di Java:

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

3. java.net.ConnectException: Connection refused

Motivi: Host o porta del proxy errati; il server proxy non è disponibile; firewall blocca la connessione.
Diagnosi:

# Verifica la disponibilità del proxy
curl -x http://proxy.example.com:8080 https://httpbin.org/ip

# Oppure tramite telnet
telnet proxy.example.com 8080

4. Il proxy funziona per HTTP, ma non per HTTPS

Motivo: Sono state impostate solo le proprietà http.proxyHost/Port, ma non https.proxyHost/Port.
Soluzione: Imposta entrambi i set di proprietà. Per HTTPS tramite proxy HTTP viene utilizzato il metodo di tunneling CONNECT — assicurati che il proxy lo supporti.

5. 407 Proxy Authentication Required

Motivo: Il proxy richiede autenticazione, ma non è configurata.
Soluzione: Aggiungi Authenticator per le proprietà di sistema JVM o configura CredentialsProvider per Apache HttpClient / proxyAuthenticator per OkHttp (esempi sopra).

6. Perdita di memoria durante la rotazione dei proxy

Motivo: Per ogni richiesta viene creato un nuovo istanza di OkHttpClient. Ogni client mantiene il proprio pool di thread e connessioni.
Soluzione: Riutilizza i client. Crea un pool di più client (uno per proxy) e ruotali, invece di crearne di nuovi.

7. Abilitazione della registrazione di debug per la diagnosi

# application.properties — attiviamo i log per la diagnosi del proxy
logging.level.org.apache.http=DEBUG
logging.level.org.apache.http.wire=DEBUG
logging.level.reactor.netty.http.client=DEBUG

# Per JVM — proprietà di sistema
-Djava.net.debug=all

Conclusione

Configurare un proxy nelle applicazioni Java richiede comprensione di quale client HTTP viene utilizzato sotto il cofano. Le proprietà di sistema JVM sono un avvio rapido per HttpURLConnection, ma OkHttp, WebClient e Apache HttpClient richiedono una configurazione esplicita. Per le applicazioni aziendali, è consigliabile estrarre i parametri del proxy in application.properties e utilizzare profili Spring per diversi ambienti. È meglio delegare la rotazione dei proxy a un fornitore con endpoint rotante — è più semplice e affidabile rispetto a implementarlo autonomamente.

Se la tua applicazione Java si occupa di parsing di dati da piattaforme protette o richiede alta anonimizzazione per le richieste esterne, ti consigliamo di considerare proxy residenziali — hanno IP reali di utenti domestici, il che riduce significativamente la probabilità di blocchi da parte dei sistemi antifrode. Per il parsing ad alto carico di dati aperti, i proxy dei data center sono ottimali — offrono la massima velocità a un costo inferiore del traffico.

```