【Java】Java11でのHTTPリクエスト
JavaでHTTPリクエストをしたい場合HttpURLConnectionクラスを使うと簡単に処理できますが、Java11からはHttpClientなど、java.net.httpパッケージのクラスが使用できるようになりました。
今回は、この新しく追加されたjava.net.httpパッケージのクラスでHTTPリクエストを実行していってみましょう。
使用するクラス群
HttpClient
HTTPリクエストの処理を行うクラスです。
send(HttpRequest,BodyHandler)メソッドでHTTPリクエストを送信します。
戻り値はHttpResponseです。
HttpRequest
HTTPリクエストの送信内容を設定するクラスです。
HttpRequest.BodyPublisher
HTTPリクエストbodyを作成するクラスです。
HttpResponse
HTTPレスポンスの内容が集約されたクラスです。
HttpResponse.BodyHandler
HTTPレスポンスbodyを取得するためのクラスです。
HTTPリクエストサンプル
試しにgoogleの検索ページを取得するリクエストを送信してみましょう。
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandler; import java.nio.charset.StandardCharsets; public class TestClient2 { public static void main(String[] args) { try { HttpRequest request = HttpRequest .newBuilder(URI.create("http://google.com")) .build(); BodyHandler<String> bodyHandler = HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8); HttpResponse<String> response = HttpClient.newBuilder().build().send(request, bodyHandler); System.out.println(response.body()); } catch (Exception e) { e.printStackTrace(); } } }
<HTML><HEAD><meta http-equiv=”content-type” content=”text/html;charset=utf-8″>
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF=”http://www.google.com/”>here</A>.
</BODY></HTML><HTML><HEAD><meta http-equiv=”content-type” content=”text/html;charset=utf-8″>
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF=”http://www.google.com/”>here</A>.
</BODY></HTML>
検索ページのHTMLが返されれば成功です。
自分でHTTPサーバーを用意してHTTPリクエストを試す
既存のサイトへリクエストを飛ばすことでもテストは可能ですが、HTTPのことをより理解するために自力でHTTPサーバーを用意して試す方法もやってみました。
サーバーも自分で用意するほうが各種メソッドの動きなどが調べやすい・・・かもしれませんよね?
ServerSocketを使用したサーバーとApacheTomcatを使用した、本番に近いサーバーを使ってみます。
ServerSocketを使用した簡易HTTPサーバーでテスト
ServerSocketでHTTPサーバーを作るのは面倒なので、ちゃんとしたレベルまでは作りません。とりあえずブラウザに表示できるとこまでを作りました。
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; public class TestSocketServer2 { public static void main(String[] args) { ServerSocket ss; try { ss = new ServerSocket(80); while(true) { Socket sock = ss.accept(); InputStream is = sock.getInputStream(); while(is.available()==0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } byte[] readData = new byte[20000]; is.read(readData); String requestData = new String(readData,StandardCharsets.UTF_8); if ( requestData != null && requestData.length() > 0 && requestData.indexOf("\n") != -1) { String[] firstHead = requestData.substring(0, requestData.indexOf("\n")).split(" "); String path = firstHead[1]; System.out.println("=======リクエストデータ======="); System.out.println(requestData); System.out.println("=======リクエストデータ======="); OutputStream os = sock.getOutputStream(); os.write("HTTP/1.1 200 OK\n".getBytes(StandardCharsets.UTF_8)); os.write("Content-Type: ".getBytes(StandardCharsets.UTF_8)); os.write("text/html; charset=UTF-8;\n".getBytes(StandardCharsets.UTF_8)); String responseHTML = "<html><body><div style='background-color:red;color:white;'>不明なページ</div></body></html>"; if ( path.endsWith("aaa") ) { responseHTML = "<html><body><div style='background-color:green;color:white;'>ああああ</div></body></html>"; } byte[] responseBody = responseHTML.getBytes(StandardCharsets.UTF_8); os.write(("Content-Length: "+responseBody.length+"\n").getBytes(StandardCharsets.UTF_8)); os.write(("\n").getBytes(StandardCharsets.UTF_8)); os.write(responseBody); os.close(); } is.close(); sock.close(); } } catch (IOException e) { e.printStackTrace(); } } }
ブラウザでのアクセステスト
「localhost/何かの文字列」でアクセスできます。
表示できましたね。
それでは、HTTPリクエストの機能を使ってみましょう。
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpClient.Version; import java.net.http.HttpRequest; import java.net.http.HttpRequest.BodyPublishers; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandler; import java.nio.charset.StandardCharsets; public class TestClient2 { public static void main(String[] args) { try { HttpRequest request = HttpRequest .newBuilder(URI.create("http://localhost/aaa")) .POST(BodyPublishers.ofString("p1=きゃぷてんファルコン&p2=さすがFC")) .setHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8") .build(); BodyHandler<String> bodyHandler = HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8); HttpResponse<String> response = HttpClient.newBuilder().version(Version.HTTP_1_1).build().send(request, bodyHandler); System.out.println(response.body()); } catch (Exception e) { e.printStackTrace(); } } }
<html><body><div style=’background-color:green;color:white;’>ああああ</div></body></html>
=======リクエストデータ=======
POST /aaa HTTP/1.1
Content-Length: 48
Host: localhost
User-Agent: Java-http-client/11.0.3
Content-Type: application/x-www-form-urlencoded; charset=utf-8
p1=きゃぷてんファルコン&p2=さすがFC
=======リクエストデータ=======
ApacheTomcatを使用したHTTPサーバーでテスト
ApacheTomcat版はファイルが多少多くなるので、私がgitにアップしているテスト用のHTTPサーバープログラムを使用します。
設定方法とか、わかる方はご自由に、お使いいただいて結構です。(動的Webプロジェクトで作成したものとなります。)
import java.io.IOException; import java.io.PrintWriter; import java.util.Arrays; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServer2 extends HttpServlet { protected void doGet(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException { try { process(arg0,arg1); } catch (Exception e) { e.printStackTrace(); } } protected void doPost(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException { try { process(arg0,arg1); } catch (Exception e) { e.printStackTrace(); } } void process(HttpServletRequest req, HttpServletResponse res) throws Exception { System.out.println("========リクエスト処理の開始========"); System.out.println("========受信パラメータ========"); Map<String, String[]> map = req.getParameterMap(); for ( Map.Entry<String, String[]> e : map.entrySet() ) { System.out.println(e.getKey()+"="+Arrays.toString(e.getValue())); } System.out.println("========受信パラメータ========"); String path = req.getRequestURI(); res.setCharacterEncoding("UTF-8"); res.setContentType("text/html"); PrintWriter out = res.getWriter(); System.out.println("========レスポンスデータ作成========"); if (path.endsWith("zugo")) { String html = "<html><body><div>ずごー!</div></body></html>"; out.println(html); System.out.println(html); } else { String html = "<html><body><div style='background-color:red;'>不明なぺーじ</div></body></html>"; out.println(html); System.out.println(html); } System.out.println("========レスポンスデータ作成========"); System.out.println("========リクエスト処理の終了========"); } }
ブラウザでのアクセステスト
「localhost:8080/TestServer2/test2/何かの文字列」でアクセスできます。
うまく機能しているようです。
では、このサーバープログラムに対して下記のようなリクエストプログラムを実行して試してみましょう。
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpRequest.BodyPublishers; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandler; import java.nio.charset.StandardCharsets; public class TestClient2 { public static void main(String[] args) { try { HttpRequest request = HttpRequest .newBuilder(URI.create("http://localhost:8080/TestServer2/test2/zugo")) .POST(BodyPublishers.ofString("p1=まりお&p2=ひげ&p3=はながでかい")) .setHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8") .build(); BodyHandler<String> bodyHandler = HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8); HttpResponse<String> response = HttpClient.newBuilder().build().send(request, bodyHandler); System.out.println(response.body()); } catch (Exception e) { e.printStackTrace(); } } }
<html><body><div>ずごー!</div></body></html>
========リクエスト処理の開始========
========受信パラメータ========
p1=[まりお]
p2=[ひげ]
p3=[はながでかい]
========受信パラメータ========
========レスポンスデータ作成========
<html><body><div>ずごー!</div></body></html>
========レスポンスデータ作成========
========リクエスト処理の終了========
予想されている動作となっているようです。
よし!これからは新しいほうをどんどん使っていくぞ!
・・・多分
ディスカッション
コメント一覧
I really like your writing style, excellent info, thank you for posting
:D.
I’m honored. I will continue to write in this style as much as possible for programming. thank you for your comment.
Hi there just wanted to give you a quick heads up. The words in your
content seem to be running off the screen in Safari.
I’m not sure if this is a format issue or something
to do with internet browser compatibility but I thought I’d
post to let you know. The layout look great though!
Hope you get the issue solved soon. Many thanks
Thank you for your advice.
Made adjustments in Safari.
I didn’t point out the model, so I checked with three models: MAC, iPad, and iPhone.
I have received many comments, but I am not good at English.
You cannot reply to everything.
I’m sorry.
Perfectly pent subject material, thank you for information.
thank you.
I’d constantly want to be update on new content on this internet site,
saved to favorites!
Thank you!
Hi there, just wanted to mention, I loved this post.
It was funny. Keep on posting!