Connessioni HTTP in Java

di  Antonio Coschignano, domenica 24 gennaio 2010
Tramite le librerie incluse nel package java.net è possibile gestire sia protocolli a livello di trasporto come TCP e UDP oppure ricorrere direttamente ad alcuni oggetti che si occupano di gestire connessioni di protocolli applicativi come l'HTTP (Hypertext Transfer Protocol). Con poche semplici operazioni è possibile accedere ad una risorsa web e gestire direttamente tutte le caratteristiche del protocollo HTTP.

Una connessione HTTP in java coinvolge semplicemente l'oggetto java.net.URL e java.net.HttpUrlConnection. L'oggetto URL (Uniform Resource Locator) raccoglie tutte le caratteristiche della locazione della risorsa e apre la connessione. Mentre l'oggetto HttpUrlConnection si occupa di gestire gli stream coinvolti nella connessione e costruire i parametri della richiesta. La classe URL contiene diversi costruttori poichè esistono diversi modi per specificare un url. In questo contesto ci limiteremo solo alla forma più semplice, cioè riferendoci al normale url in formato stringa. Voglio precisare che questa classe non gestisce solo ed esclusivamente connessioni di tipo HTTP, ma in questo articolo ci riferiremo solo a questo protocollo.

Vediamo adesso le fasi necessarie per effettuare il download di una pagina web. Per prima cosa è necessario creare un'istanza della classe URL dove passiamo nel costruttore l'url del sito web:
URL url = new URL("http://www.example.it/");
Una volta creata l'istanza è possibile aprire la connessione tramite il metodo openConnection() che ritorna un riferimento alla connessione appena creata. In particolare ritorna un oggetto di tipo URLConnection che è implementa i metodi necessari per intergire con il server. In questo caso per connessioni HTTP abbiamo in java HttpURLConnection che eredita questa classe. Quindi per ottenere un riferimento alla connessione bsiogna effettuare il cast alla chiamata del metodo openConnection():
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
La classe HttpURLConnection ci consente di leggere e scrivere sugli stream della connessione. Per il momento riprendendo il nostro esempio, per scaricare il codice html della pagina abbiamo bisogno solo di leggere dallo stream, richiamando il metodo getInputStream() che ritorna uno oggetto InputStream da gestire magari con un BufferedReader:
BufferedReader read = new BufferedReader(new InputStreamReader(connection.getInputStream()));
Questo è l'esempio completo, dove viene scaricata l'intera pagina una riga per volta e vengono gestite anche l'eccezioni:
try {
  URL url = new URL("http://www.google.it/");
  HttpURLConnection connection = (HttpURLConnection) url.openConnection();
  BufferedReader read = new BufferedReader(new InputStreamReader(connection.getInputStream()));
  String line = read.readLine();
  String html = "";
  while(line!=null) {
    html += line;
    line = read.readLine();
  }
} catch(MalformedURLException ex) {
	ex.printStackTrace();
} catch(IOException ioex) {
	ioex.printStackTrace();
}
Durante la creazione dell'istanza la classe URL può sollevare una eccezione del tipo MalformedURLException in quanto l'url della risorsa può essere sintatticamente errata.

Http Proxy

Il metodo openConnection() implementa anche la possibilità di utilizzare un server proxy nella richiesta HTTP. Basta passare nel metodo un'istanza della classe java.net.Proxy specificando il tipo di proxy (Proxy.Type.HTTP) e l'indirizzo dello stesso sottoforma id InetSocketAddress:
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("xxx.xxx.xxx.xxx.", 80));
HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxy);

Header HTTP

Per specificare gli header della richiesta HTTP bisogna agire sempre sull'oggetto HttpUrlConnection che ci mette a disposizione il metodo setRequestProperty() dove è possibile specificare una chiave e un valore. Ad esempio possiamo specificare nella richiesta l'user-agent (la stringa del browser web oppure di uno spider), oppure specificare il tipo di file che il client accetta nella risposta (accept) e via via tutti i tipi di header. Esempio:
...
URL url = new URL("http://www.google.it/");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("accept", "text/html");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; (R1 1.5))");
...

Tipi di richieste

Come sappiamo una richiesta HTTP è caratterizzata da diversi comandi che il client può inviare al server per specifiche richieste. I metodi possibili per il protocollo HTTP sono:
  • GET
  • POST
  • HEAD
  • PUT
  • DELETE
  • OPTIONS
  • TRACE
Senza addentrarci nei particolari di ciascun metodo, vediamo invece come comportarci per effettuare una chiamata utilizzando uno di questi metodi. Per una richiesta GET non è necessario aggiungere altro che le chiavi e i valori direttamente nell'URL. Ad esempio se dobbiamo lanciare una query di ricerca su Google:
URL url = new URL("http://www.google.it/?q=parola+chiave");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
BufferedReader read = new BufferedReader(new InputStreamReader(connection.getInputStream()));
...
Per una richiesta POST il discorso è un po diverso in quanto oltre all'header bisogna specificare anche un corpo content abilitando la scrittura sullo stream della connessione.
...
  String data = "chiave1=valore1&chiave2=valore2\r\n"//corpo della richiesta
  connection.setDoOutput(true);//abilita la scrittura
  connection.setRequestMethod("POST");//settaggio del metodo
  OutputStreamWriter wr = new OutputStreamWriter(connection.getOutputStream());
  wr.write(data);//scrittura del content
  wr.flush();
...
Notate che il corpo della richiesta POST deve terminare con il Carriage Return (\r\n)

Http Status Code

Per concludere vediamo la gestione delle risposte dal server per quanto riguarda gli header che il server invia per notificare l'esito della richiesta. Il metodo in questione è getResponseCode():
URL url = new URL("http://www.google.it/");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
int code = connection.getResponseCode();
L' intero ritornato rappresenta il codice di risposta relativo all'esito della richiesta:
  • ...
  • 200: Richiesta riuscita
  • 404: Pagina non trovata
  • 500: Errore interno del server
  • ...
Per un approfondimento sui codici di stato HTTP consultare la guida Http Status Code si questo sito.
Altri link che potrebbero interessarti
  • Una lista concatenata in java
  • Tutorial JFileChooser in Java Swing
  • La gestione delle Stringhe in java
  • La gestione degli eventi in java Swing
  • La classe Collections
  • Java Generics
  • Gestire la System Tray in Java
  • Gestire la clipboard in Java Swing