- contexte d'utilisation
- passif technique de l'entreprise dans laquelle le projet sera réalisé
- ce que l'on attend de la librairie :
- facilité d'utilisation
- couverture et respect de la norme HTTP
- pipelining
- ...
Je ne vais pas ici faire de comparatifs des différentes librairies existantes : pour l'instant je n'ai surtout utilisé que celle d'apache. Par contre, il est des cas où l'on aimerait pouvoir se passer d'une dépendance à une librairie tierce. Or, depuis longtemps java intègre des possibilités de pouvoir faire des requêtes HTTP sans trop d'effort. Par contre, ce framework n'est pas trop bien documenté. Peut-être n'ai je pas frappé aux bonnes portes ; mais à l'époque ou j'ai du jouer avec les classes standards de Java j'ai eu du mal à trouver une bonne documentation. C'est pourquoi je me suis dis que j'allais présenter dans ce billet les quelques leçons que j'ai tiré de mon expérience.
Créer une connection au site distant (URLConnection)
Tout commence par la création d'une instance de la classe java.net.URL à partir de laquelle on pourra créer un object URLConnection représentant la connection applicative. Exemple de code :
URL url = new URL("http://www.google.fr");
URLConnection openConnection = url.openConnection();
Lorsque l'URL est une URL HTTP l'objet URLConnection retourné sera en fait une instance HttpURLConnection. Il est important de noter, c'est clairement indiqué dans la javadoc qu'une instance d'HttpURLConnection ne servira à réaliser qu'une seule requête HTTP : "Each HttpURLConnection instance is used to make a single request but the underlying network connection to the HTTP server may be transparently shared by other instances".
Une simple requête GET
Le code
URL url = new URL("http://www.google.fr");
HttpURLConnection openConnection= (HttpURLConnection) url.openConnection();
openConnection.setRequestMethod("GET");
openConnection.setDoOutput(false);
openConnection.connect();
final int responseCode = openConnection.getResponseCode();
if (responseCode >= 200 && responseCode<300) {
int contentLength = openConnection.getContentLength();
String headerField = openConnection.getHeaderField("Transfer-Encoding");
byte[] ba;
try (InputStream is = openConnection.getInputStream()) {
if (headerField!=null && headerField.contains("chunked")) {
ba = readChunkedStream(is);
} else {
ba = readStream(contentLength, is);
}
}
}
else if (responseCode >= 400) {
int contentLength = openConnection.getContentLength();
String headerField = openConnection.getHeaderField("Transfer-Encoding");
byte[] ba;
try (InputStream is = openConnection.getErrorStream()) {
if (headerField!=null && headerField.contains("chunked")) {
ba = readChunkedStream(is);
} else {
ba = readStream(contentLength, is);
}
}
String st = new String(ba);
System.out.println("error page :"+st);
}
Les explications
Le code qui précède montre comment faire un simple GET. Lorsque l'on fait un GET sur une ressource HTTP on n'envoie pas de contenu au serveur ; c'est pourquoi avant la connection http est paramétrée ainsi :
openConnection.setDoOutput(false);
De manière générale, le paramétrage est à faire avant l'appel à la méthode connect() qui va non seulement établir la connexion physique mais aussi faire l'appel GET. En effet, on peut dès cet appel récupérer le code retour obtenu du serveur suite à cet appel.
Le point clé dans cet exemple est que en fonction du code retour le contenu éventuellement retourné par le serveur n'est pas consommé de la même façon :
Le point clé dans cet exemple est que en fonction du code retour le contenu éventuellement retourné par le serveur n'est pas consommé de la même façon :
- on utilise openConnection.getInputStream en cas de code retour de type 20x.
- si un code retour de classe 4xx ou 5xx est retourné il faut utiliser la méthode getErrorStream pour lire l'éventuel contenu retourné par le serveur.
Une autre chose à retenir est que les ressources prises par la connection doivent être libérées ; pour cela il faut absolument fermer le flux duquel la réponse va être lue (celui retourné soit par la méthode getInputStream ou celui retourné par la méthode getErrorStream). Si cela est fait, de manière transparente la connexion réelle sous-jacente (le socket) pourra être réutilisé pour une autre requête ; ce qui est très pratique pour obtenir de meilleures performances.




