Faceți o cerere HTTP simplă în Java

1. Prezentare generală

În acest tutorial rapid, vă prezentăm o modalitate de a efectua cereri HTTP în Java - utilizând clasa Java încorporată HttpUrlConnection.

Rețineți că , începând cu JDK 11, Java oferă un nou API pentru efectuarea de cereri HTTP, care este menit ca un înlocuitor pentru HttpUrlConnection, httpclient API.

2. HttpUrlConnection

HttpUrlConnection Clasa ne permite să efectuați de bază cereri HTTP fără utilizarea unor biblioteci suplimentare. Toate clasele de care avem nevoie fac parte din pachetul java.net .

Dezavantajele utilizării acestei metode sunt că codul poate fi mai greoi decât alte biblioteci HTTP și că nu oferă funcționalități mai avansate, cum ar fi metode dedicate pentru adăugarea de antete sau autentificare.

3. Crearea unei cereri

Putem crea o instanță HttpUrlConnection folosind metoda openConnection () a clasei URL . Rețineți că această metodă creează doar un obiect de conexiune, dar nu stabilește încă conexiunea.

HttpUrlConnection Clasa este utilizat pentru toate tipurile de cereri prin setarea requestMethod atributul la una dintre valorile: GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE.

Să creăm o conexiune la o anumită adresă URL folosind metoda GET:

URL url = new URL("//example.com"); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("GET");

4. Adăugarea parametrilor cererii

Dacă dorim să adăugăm parametri la o cerere, trebuie să setăm proprietatea doOutput la adevărat , apoi să scriem un Șir de formă param1 = valoare¶m2 = valoare în OutputStream al instanței HttpUrlConnection :

Map parameters = new HashMap(); parameters.put("param1", "val"); con.setDoOutput(true); DataOutputStream out = new DataOutputStream(con.getOutputStream()); out.writeBytes(ParameterStringBuilder.getParamsString(parameters)); out.flush(); out.close();

Pentru a facilita transformarea parametrului Map , am scris o clasă de utilitate numită ParameterStringBuilder care conține o metodă statică, getParamsString () , care transformă o hartă într-un șir de formatul necesar:

public class ParameterStringBuilder { public static String getParamsString(Map params) throws UnsupportedEncodingException{ StringBuilder result = new StringBuilder(); for (Map.Entry entry : params.entrySet()) { result.append(URLEncoder.encode(entry.getKey(), "UTF-8")); result.append("="); result.append(URLEncoder.encode(entry.getValue(), "UTF-8")); result.append("&"); } String resultString = result.toString(); return resultString.length() > 0 ? resultString.substring(0, resultString.length() - 1) : resultString; } }

5. Setarea antetelor cererii

Adăugarea de antete la o cerere poate fi realizată utilizând metoda setRequestProperty () :

con.setRequestProperty("Content-Type", "application/json");

Pentru a citi valoarea unui antet dintr-o conexiune, putem folosi metoda getHeaderField () :

String contentType = con.getHeaderField("Content-Type");

6. Configurarea expirărilor

Clasa HttpUrlConnection permite setarea timpilor de conectare și citire. Aceste valori definesc intervalul de timp de așteptare pentru stabilirea conexiunii la server sau datele disponibile pentru citire.

Pentru a seta valorile de expirare, putem folosi metodele setConnectTimeout () și setReadTimeout () :

con.setConnectTimeout(5000); con.setReadTimeout(5000);

În exemplu, setăm ambele valori de expirare la cinci secunde.

7. Manipularea cookie-urilor

Java.net Pachetul contine clase care lucreaza cu probleme cookie - uri , cum ar fi CookieManager și HttpCookie .

În primul rând, pentru a citi cookie-urile dintr-un răspuns , putem prelua valoarea antetului Set-Cookie și o putem analiza într-o listă de obiecte HttpCookie :

String cookiesHeader = con.getHeaderField("Set-Cookie"); List cookies = HttpCookie.parse(cookiesHeader);

Apoi, vom adăuga cookie-urile în magazinul de cookie-uri :

cookies.forEach(cookie -> cookieManager.getCookieStore().add(null, cookie));

Să verificăm dacă este prezent un cookie numit nume de utilizator și, dacă nu, îl vom adăuga în magazinul de cookie-uri cu valoarea „john”:

Optional usernameCookie = cookies.stream() .findAny().filter(cookie -> cookie.getName().equals("username")); if (usernameCookie == null) { cookieManager.getCookieStore().add(null, new HttpCookie("username", "john")); }

În cele din urmă, pentru a adăuga cookie-urile la cerere , trebuie să setăm antetul Cookie , după închiderea și redeschiderea conexiunii:

con.disconnect(); con = (HttpURLConnection) url.openConnection(); con.setRequestProperty("Cookie", StringUtils.join(cookieManager.getCookieStore().getCookies(), ";"));

8. Gestionarea redirecționărilor

Putem activa sau dezactiva automat următoarele redirecționări pentru o conexiune specifică utilizând metoda setInstanceFollowRedirects () cu parametru adevărat sau fals :

con.setInstanceFollowRedirects(false);

De asemenea, este posibil să activați sau să dezactivați redirecționarea automată pentru toate conexiunile :

HttpUrlConnection.setFollowRedirects(false);

În mod implicit, comportamentul este activat.

Când o cerere returnează un cod de stare 301 sau 302, indicând o redirecționare, putem prelua antetul Locație și putem crea o nouă solicitare la noua adresă URL:

if (status == HttpURLConnection.HTTP_MOVED_TEMP || status == HttpURLConnection.HTTP_MOVED_PERM) { String location = con.getHeaderField("Location"); URL newUrl = new URL(location); con = (HttpURLConnection) newUrl.openConnection(); }

9. Citirea răspunsului

Citirea răspunsului la cerere se poate face prin analizarea InputStream a instanței HttpUrlConnection .

Pentru a executa cererea, putem folosi metodele getResponseCode () , connect () , getInputStream () sau getOutputStream () :

int status = con.getResponseCode();

În cele din urmă, să citim răspunsul la cerere și să-l plasăm într-un șir de conținut :

BufferedReader in = new BufferedReader( new InputStreamReader(con.getInputStream())); String inputLine; StringBuffer content = new StringBuffer(); while ((inputLine = in.readLine()) != null) { content.append(inputLine); } in.close();

Pentru a închide conexiunea , putem folosi metoda disconnect () :

con.disconnect(); 

10. Citirea răspunsului la cererile nereușite

Dacă solicitarea eșuează, încercarea de a citi InputStream a instanței HttpUrlConnection nu va funcționa. În schimb, putem consuma fluxul furnizat de HttpUrlConnection.getErrorStream () .

We can decide which InputStream to use by comparing the HTTP status code:

int status = con.getResponseCode(); Reader streamReader = null; if (status > 299) { streamReader = new InputStreamReader(con.getErrorStream()); } else { streamReader = new InputStreamReader(con.getInputStream()); }

And finally, we can read the streamReader in the same way as the previous section.

11. Building the Full Response

It's not possible to get the full response representation using the HttpUrlConnection instance.

However, we can build it using some of the methods that the HttpUrlConnection instance offers:

public class FullResponseBuilder { public static String getFullResponse(HttpURLConnection con) throws IOException { StringBuilder fullResponseBuilder = new StringBuilder(); // read status and message // read headers // read response content return fullResponseBuilder.toString(); } }

Here, we're reading the parts of the responses, including the status code, status message and headers, and adding these to a StringBuilder instance.

First, let's add the response status information:

fullResponseBuilder.append(con.getResponseCode()) .append(" ") .append(con.getResponseMessage()) .append("\n");

Apoi, vom obține anteturile folosind getHeaderFields () și le vom adăuga pe fiecare în StringBuilder în format HeaderName: HeaderValues :

con.getHeaderFields().entrySet().stream() .filter(entry -> entry.getKey() != null) .forEach(entry -> { fullResponseBuilder.append(entry.getKey()).append(": "); List headerValues = entry.getValue(); Iterator it = headerValues.iterator(); if (it.hasNext()) { fullResponseBuilder.append(it.next()); while (it.hasNext()) { fullResponseBuilder.append(", ").append(it.next()); } } fullResponseBuilder.append("\n"); });

În cele din urmă, vom citi conținutul răspunsului așa cum am făcut anterior și îl vom adăuga.

Rețineți că metoda getFullResponse va valida dacă solicitarea a avut succes sau nu pentru a decide dacă trebuie să utilizeze con.getInputStream () sau con.getErrorStream () pentru a recupera conținutul cererii.

12. Concluzie

În acest articol, am arătat cum putem efectua cereri HTTP utilizând clasa HttpUrlConnection .

Codul sursă complet al exemplelor poate fi găsit pe GitHub.