Gör en enkel HTTP-begäran i Java

1. Översikt

I den här snabbhandledningen presenterar vi ett sätt att utföra HTTP-förfrågningar i Java - med hjälp av den inbyggda Java-klassen HttpUrlConnection.

Observera att börja med JDK 11, Java ger en ny API för att utföra HTTP-förfrågningar, som är tänkt som en ersättning för HttpUrlConnection, den Httpclient API.

2. HttpUrlConnection

Den HttpUrlConnection klassen ger oss möjlighet att utföra grundläggande HTTP förfrågningar utan användning av ytterligare bibliotek. Alla klasser som vi behöver ingår i java.net- paketet.

Nackdelarna med att använda denna metod är att koden kan vara mer besvärlig än andra HTTP-bibliotek och att den inte ger mer avancerade funktioner såsom dedikerade metoder för att lägga till rubriker eller autentisering.

3. Skapa en begäran

Vi kan skapa en HttpUrlConnection- instans med metoden openConnection () i URL- klassen. Observera att den här metoden bara skapar ett anslutningsobjekt men inte upprättar anslutningen ännu.

Den HttpUrlConnection klass används för alla typer av förfrågningar genom att ange requestMethod attribut till en av följande värden: GET, POST, HEAD, optioner, PUT, DELETE, spåra.

Låt oss skapa en anslutning till en viss URL med GET-metoden:

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

4. Lägga till begäran Parametrar

Om vi ​​vill lägga till parametrar i en begäran måste vi ställa in egenskapen doOutput till true och sedan skriva en sträng av formuläret param1 = värde¶m2 = värde till OutputStream för HttpUrlConnection- instansen:

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

För att underlätta omvandlingen av parametern Map har vi skrivit en verktygsklass som heter ParameterStringBuilder som innehåller en statisk metod, getParamsString () , som förvandlar en Map till en String av önskat format:

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. Ställa in begäran rubriker

Att lägga till rubriker i en begäran kan uppnås med metoden setRequestProperty () :

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

För att läsa värdet på en rubrik från en anslutning kan vi använda metoden getHeaderField () :

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

6. Konfigurera timeouts

HttpUrlConnection- klassen tillåter inställning av timeout för anslutning och läsning. Dessa värden definierar tidsintervallet för att vänta på att anslutningen till servern ska upprättas eller data ska vara tillgängliga för läsning.

För att ställa in timeout-värdena kan vi använda metoderna setConnectTimeout () och setReadTimeout () :

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

I exemplet sätter vi båda timeoutvärdena till fem sekunder.

7. Hantering av kakor

Den java.net paketet innehåller klasser som underlättar arbetet med cookies som CookieManager och HttpCookie .

För att först läsa kakorna från ett svar kan vi hämta värdet för Set-Cookie- rubriken och analysera det till en lista med HttpCookie- objekt:

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

Därefter lägger vi till kakorna i cookiebutiken :

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

Låt oss kontrollera om det finns en cookie med namnet användarnamn , och om inte, lägger vi till den i cookiebutiken med värdet "john":

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

Slutligen, för att lägga till cookies i begäran , måste vi ställa in cookie- rubriken efter att anslutningen har stängts och öppnats igen:

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

8. Hantering av omdirigeringar

Vi kan aktivera eller inaktivera automatiskt efter omdirigeringar för en specifik anslutning med metoden setInstanceFollowRedirects () med parametern true eller false :

con.setInstanceFollowRedirects(false);

Det är också möjligt att aktivera eller inaktivera automatisk omdirigering för alla anslutningar :

HttpUrlConnection.setFollowRedirects(false);

Som standard är beteendet aktiverat.

När en begäran returnerar statuskoden 301 eller 302, vilket indikerar en omdirigering kan vi hämta plats header och skapa en ny begäran till den nya 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. Läser svaret

Att läsa svaret på begäran kan göras genom att analysera InputStream för instansen HttpUrlConnection .

För att utföra begäran kan vi använda getResponseCode () , connect () , getInputStream () eller getOutputStream () metoder :

int status = con.getResponseCode();

Slutligen, låt oss läsa svaret på begäran och placera den i en innehållssträng :

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

För att stänga anslutningen kan vi använda metoden disconnect () :

con.disconnect(); 

10. Läser svaret på misslyckade förfrågningar

Om begäran misslyckas fungerar inte försöket att läsa InputStream för HttpUrlConnection- instansen. Istället kan vi konsumera strömmen från 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");

Därefter får vi rubrikerna med getHeaderFields () och lägger till var och en av dem i vår StringBuilder i formatet 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"); });

Slutligen läser vi svarsinnehållet som tidigare och lägger till det.

Observera att getFullResponse- metoden kommer att validera om begäran lyckades eller inte för att avgöra om den behöver använda con.getInputStream () eller con.getErrorStream () för att hämta begärans innehåll.

12. Slutsats

I den här artikeln visade vi hur vi kan utföra HTTP-förfrågningar med klassen HttpUrlConnection .

Den fullständiga källkoden för exemplen finns på GitHub.