1. 概要

このクイックチュートリアルでは、 JavaでHTTPリクエストを実行する方法 —組み込みのJavaクラスを使用する HttpUrlConnection。 

JDK 11以降、JavaはHTTPリクエストを実行するための新しいAPIを提供します。これは、 HttpUrlConnection、 HttpClientAPIの代わりとなるものです。

2. HttpUrlConnection

HttpUrlConnection クラスを使用すると、追加のライブラリを使用せずに基本HTTP要求を実行できます。必要なすべてのクラスはjava.netパッケージの一部です。 。

この方法を使用することの欠点は、コードが他のHTTPライブラリよりも煩雑になる可能性があることと、ヘッダーや認証を追加するための専用の方法など、より高度な機能を提供しないことです。

3. リクエストの作成

URLクラスのopenConnection()メソッドを使用してHttpUrlConnectionインスタンスを作成できます。このメソッドは接続オブジェクトを作成するだけで、まだ接続を確立していないことに注意してください。

HttpUrlConnection クラスは、 requestMethod 属性をGET、POST、HEAD、OPTIONS、PUT、DELETE、TRACEのいずれかの値に設定することにより、すべてのタイプのリクエストに使用されます。

GETメソッドを使用して特定のURLへの接続を作成しましょう。

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

4. リクエストパラメータの追加

リクエストにパラメータを追加する場合は、 doOutputプロパティをtrueに設定してから、param1=value¶m2=valueの形式の文字列をHttpUrlConnection[のOutputStreamに書き込みます。 X200X]インスタンス:

Map<String, String> 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();

パラメータマップの変換を容易にするために、を変換する静的メソッド getParamsString()を含むParameterStringBuilderというユーティリティクラスを作成しました。 を必要な形式のStringにマップします。

public class ParameterStringBuilder {
    public static String getParamsString(Map<String, String> params) 
      throws UnsupportedEncodingException{
        StringBuilder result = new StringBuilder();

        for (Map.Entry<String, String> 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. リクエストヘッダーの設定

リクエストにヘッダーを追加するには、 setRequestProperty()メソッドを使用します。

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

接続からヘッダーの値を読み取るには、 getHeaderField()メソッドを使用できます。

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

6. タイムアウトの構成

HttpUrlConnection クラスでは、接続と読み取りのタイムアウトを設定できます。これらの値は、サーバーへの接続が確立されるか、データが読み取り可能になるまで待機する時間間隔を定義します。

タイムアウト値を設定するには、 setConnectTimeout()および setReadTimeout()メソッドを使用できます。

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

この例では、両方のタイムアウト値を5秒に設定しています。

7. クッキーの取り扱い

java.net パッケージには、CookieManagerHttpCookieなどのCookieの操作を容易にするクラスが含まれています。

まず、応答から Cookieを読み取るために、 Set-Cookie ヘッダーの値を取得し、それをHttpCookieオブジェクトのリストに解析できます。

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

次に、CookieをCookieストアに追加します。

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

username というCookieが存在するかどうかを確認し、存在しない場合は、値「john」を使用してCookieストアに追加します。

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

最後に、リクエストにCookieを追加するには、接続を閉じて再度開いた後、Cookieヘッダーを設定する必要があります。

con.disconnect();
con = (HttpURLConnection) url.openConnection();

con.setRequestProperty("Cookie", 
  StringUtils.join(cookieManager.getCookieStore().getCookies(), ";"));

8. リダイレクトの処理

trueまたはfalseパラメーターを指定したsetInstanceFollowRedirects()メソッドを使用すると、特定の接続のリダイレクトに続いてを自動的に有効または無効にできます。

con.setInstanceFollowRedirects(false);

すべての接続の自動リダイレクトを有効または無効にすることもできます

HttpUrlConnection.setFollowRedirects(false);

デフォルトでは、動作は有効になっています。

リクエストがリダイレクトを示すステータスコード301または302を返すと、 Location ヘッダーを取得して、新しい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. 回答を読む

リクエストの応答の読み取りは、HttpUrlConnectionインスタンスのInputStreamを解析することで実行できます。

リクエストを実行するには、getResponseCode()、connect()、getInputStream()、またはgetOutputStream()メソッドを使用できます

int status = con.getResponseCode();

最後に、リクエストの応答を読み取り、content文字列に配置します。

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

接続を閉じるには、 disconnect()メソッドを使用できます。

con.disconnect();

10. 失敗したリクエストに対する応答の読み取り

リクエストが失敗した場合、HttpUrlConnectionインスタンスのInputStreamを読み取ろうとしても機能しません。 代わりに、 HttpUrlConnection.getErrorStream()。によって提供されるストリームを利用できます。

HTTPステータスコードを比較することで、使用するInputStreamを決定できます。

int status = con.getResponseCode();

Reader streamReader = null;

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

そして最後に、前のセクションと同じ方法でstreamReaderを読み取ることができます。

11. フルレスポンスの構築

HttpUrlConnectionインスタンスを使用して完全な応答表現を取得することはできません。

ただし、HttpUrlConnectionインスタンスが提供するいくつかのメソッドを使用してビルドできます

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

ここでは、ステータスコード、ステータスメッセージ、ヘッダーなどの応答の一部を読み取り、これらをStringBuilderインスタンスに追加しています。

まず、応答ステータス情報を追加しましょう

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

次に、getHeaderFields()を使用してヘッダーを取得し、HeaderName: HeaderValuesの形式で各ヘッダーをStringBuilderに追加します。

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

最後に、前と同じように応答コンテンツを読み取り、追加します。

getFullResponse メソッドは、 con.getInputStream()または con.getErrorStream()[を使用する必要があるかどうかを判断するために、要求が成功したかどうかを検証することに注意してください。 X197X]リクエストのコンテンツを取得します。

12. 結論

この記事では、HttpUrlConnectionクラスを使用してHTTPリクエストを実行する方法を示しました。

例の完全なソースコードは、GitHubにあります。