질문자 :Community Wiki
java.net.URLConnection
사용은 여기에서 꽤 자주 질문되며 Oracle 자습서 는 이에 대해 너무 간결합니다.
이 튜토리얼은 기본적으로 GET 요청을 실행하고 응답을 읽는 방법만 보여줍니다. POST 요청을 수행하고, 요청 헤더를 설정하고, 응답 헤더를 읽고, 쿠키를 처리하고, HTML 양식을 제출하고, 파일을 업로드하는 등의 작업에 사용하는 방법은 어디에도 설명하지 않습니다.
그렇다면 어떻게 java.net.URLConnection
을 사용하여 "고급" HTTP 요청을 실행하고 처리할 수 있습니까?
먼저 면책 조항입니다. 게시된 코드 스니펫은 모두 기본적인 예입니다. NullPointerException
, ArrayIndexOutOfBoundsException
및 consorts와 같은 IOException
및 RuntimeException
을 처리해야 합니다.
Java 대신 Android용으로 개발하는 경우 API 레벨 28이 도입된 이후로 일반 텍스트 HTTP 요청은 기본적으로 비활성화되어 있습니다. HttpsURLConnection
을 사용하는 것이 좋지만 실제로 필요한 경우 애플리케이션 매니페스트에서 일반 텍스트를 활성화할 수 있습니다.
준비 중
먼저 최소한 URL과 문자 집합을 알아야 합니다. 매개변수는 선택 사항이며 기능 요구 사항에 따라 다릅니다.
String url = "http://example.com"; String charset = "UTF-8"; // Or in Java 7 and later, use the constant: java.nio.charset.StandardCharsets.UTF_8.name() String param1 = "value1"; String param2 = "value2"; // ... String query = String.format("param1=%s¶m2=%s", URLEncoder.encode(param1, charset), URLEncoder.encode(param2, charset));
쿼리 매개변수는 name=value
형식이어야 하고 &
로 연결되어야 합니다. 일반적으로 URLEncoder#encode()
사용하여 지정된 문자 집합으로 쿼리 매개변수를 URL 인코딩 합니다.
String#format()
은 편의를 위한 것입니다. +
두 번 이상 필요할 때 선호합니다.
사소한 작업입니다. 기본 요청 방법입니다.
URLConnection connection = new URL(url + "?" + query).openConnection(); connection.setRequestProperty("Accept-Charset", charset); InputStream response = connection.getInputStream(); // ...
?
사용하여 URL에 연결해야 합니다. . Accept-Charset
헤더는 매개변수가 어떤 인코딩인지 서버에 힌트를 줄 수 있습니다. 쿼리 문자열을 보내지 않으면 Accept-Charset
헤더를 그대로 둘 수 있습니다. 헤더를 설정할 필요가 없으면 URL#openStream()
바로 가기 메서드를 사용할 수도 있습니다.
InputStream response = new URL(url).openStream(); // ...
어느 쪽이든 상대방이 HttpServlet
이면 해당 doGet()
메서드가 호출되고 매개변수는 HttpServletRequest#getParameter()
사용할 수 있습니다.
테스트 목적으로 응답 본문을 아래와 같이 표준 출력으로 인쇄할 수 있습니다.
try (Scanner scanner = new Scanner(response)) { String responseBody = scanner.useDelimiter("\\A").next(); System.out.println(responseBody); }
URLConnection#setDoOutput()
을 true
설정하면 암시적으로 요청 메서드가 POST로 설정됩니다. 웹 양식과 같은 표준 HTTP POST는 application/x-www-form-urlencoded
유형이며 여기서 쿼리 문자열은 요청 본문에 기록됩니다.
URLConnection connection = new URL(url).openConnection(); connection.setDoOutput(true); // Triggers POST. connection.setRequestProperty("Accept-Charset", charset); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset); try (OutputStream output = connection.getOutputStream()) { output.write(query.getBytes(charset)); } InputStream response = connection.getInputStream(); // ...
참고 : 프로그래밍 방식으로 HTML 양식을 작성하여 제출하고 싶습니다 때마다 수행하는 것을 잊지 마세요 name=value
어떤 쌍 <input type="hidden">
쿼리 문자열에 물론 또한 요소 name=value
의 쌍 <input type="submit">
요소(이는 일반적으로 서버 측에서 버튼이 눌렸는지, 눌렸는지 구별하기 위해 사용되었기 때문입니다).
획득한 URLConnection
을 HttpURLConnection
캐스팅하고 대신 해당 HttpURLConnection#setRequestMethod()
를 사용할 수도 있습니다. 그러나 출력에 연결을 사용하려는 경우 여전히 URLConnection#setDoOutput()
을 true
로 설정해야 합니다.
HttpURLConnection httpConnection = (HttpURLConnection) new URL(url).openConnection(); httpConnection.setRequestMethod("POST"); // ...
어느 쪽이든 다른 쪽이 HttpServlet
이면 해당 doPost()
메서드가 호출되고 매개변수는 HttpServletRequest#getParameter()
사용할 수 있습니다.
실제로 HTTP 요청 실행
URLConnection#connect()
하여 HTTP 요청을 명시적으로 실행할 수 URLConnection#getInputStream()
등을 사용하는 응답 본문과 같이 HTTP 응답에 대한 정보를 얻으려는 경우 요청이 자동으로 시작됩니다. 위의 예는 정확히 그렇게 하므로 connect()
호출은 실제로 불필요합니다.
HTTP 응답 정보 수집
- HTTP 응답 상태 :
여기 HttpURLConnection
이 필요합니다. 필요한 경우 먼저 캐스팅하십시오.
int status = httpConnection.getResponseCode();
HTTP 응답 헤더 :
for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) { System.out.println(header.getKey() + "=" + header.getValue()); }
HTTP 응답 인코딩 :
Content-Type
charset
매개변수가 포함된 경우 응답 본문은 텍스트 기반일 가능성이 높으며 서버 측에서 지정한 문자 인코딩으로 응답 본문을 처리하려고 합니다.
String contentType = connection.getHeaderField("Content-Type"); String charset = null; for (String param : contentType.replace(" ", "").split(";")) { if (param.startsWith("charset=")) { charset = param.split("=", 2)[1]; break; } } if (charset != null) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(response, charset))) { for (String line; (line = reader.readLine()) != null;) { // ... System.out.println(line)? } } } else { // It's likely binary content, use InputStream/OutputStream. }
세션 유지
서버 측 세션은 일반적으로 쿠키로 지원됩니다. 일부 웹 양식은 로그인이 필요하거나 세션에서 추적해야 합니다. CookieHandler
API를 사용하여 쿠키를 유지할 수 있습니다. 모든 HTTP 요청을 보내기 전에 CookiePolicy
가 ACCEPT_ALL
CookieManager
를 준비해야 합니다.
// First set the default cookie manager. CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL)); // All the following subsequent URLConnections will use the same cookie manager. URLConnection connection = new URL(url).openConnection(); // ... connection = new URL(url).openConnection(); // ... connection = new URL(url).openConnection(); // ...
이것은 모든 상황에서 항상 제대로 작동하지 않는 것으로 알려져 있습니다. 실패하면 쿠키 헤더를 수동으로 수집하고 설정하는 것이 가장 좋습니다. 기본적으로 로그인 또는 첫 번째 GET
Set-Cookie
헤더를 가져온 다음 후속 요청을 통해 전달해야 합니다.
// Gather all cookies on the first request. URLConnection connection = new URL(url).openConnection(); List<String> cookies = connection.getHeaderFields().get("Set-Cookie"); // ... // Then use the same cookies on all subsequent requests. connection = new URL(url).openConnection(); for (String cookie : cookies) { connection.addRequestProperty("Cookie", cookie.split(";", 2)[0]); } // ...
split(";", 2)[0]
expires
, path
등과 같이 서버 측과 관련이 없는 쿠키 속성을 제거하기 위해 존재합니다. 또는 cookie.substring(0, cookie.indexOf(';'))
대신 split()
.
스트리밍 모드
HttpURLConnection
기본적 사실 관계없이 사용하여 고정 컨텐츠 길이를 직접 설정 한 여부를 보내기 전에 전체 요청 본문 버퍼 것 connection.setRequestProperty("Content-Length", contentLength);
. 이로 인해 대용량 POST 요청(예: 파일 업로드)을 동시에 보낼 때마다 OutOfMemoryException
이 발생할 수 있습니다. HttpURLConnection#setFixedLengthStreamingMode()
를 설정하고 싶습니다.
httpConnection.setFixedLengthStreamingMode(contentLength);
그러나 콘텐츠 길이를 미리 알 수 없는 경우 HttpURLConnection#setChunkedStreamingMode()
적절하게 설정하여 청크 스트리밍 모드를 사용할 수 있습니다. 이것은 HTTPTransfer-Encoding
헤더를 chunked
로 설정하여 요청 본문을 청크로 보내도록 합니다. 아래 예에서는 본문을 1KB 청크로 보냅니다.
httpConnection.setChunkedStreamingMode(1024);
사용자 에이전트
실제 웹 브라우저에서는 제대로 작동하지만 요청이 예기치 않은 응답을 반환하는 경우가 발생할 수 있습니다.User-Agent
요청 헤더를 기반으로 요청을 차단하고 있을 것입니다. URLConnection
은 기본적으로 마지막 부분이 분명히 JRE 버전인 Java/1.6.0_19
다음과 같이 재정의할 수 있습니다.
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"); // Do as if you're using Chrome 41 on Windows 7.
최근 브라우저 의 User-Agent 문자열을 사용하십시오.
오류 처리
HTTP 응답 코드가 4nn
(클라이언트 오류) 또는 5nn
(서버 오류)이면 HttpURLConnection#getErrorStream()
을 읽고 서버가 유용한 오류 정보를 보냈는지 확인할 수 있습니다.
InputStream error = ((HttpURLConnection) connection).getErrorStream();
HTTP 응답 코드가 -1이면 연결 및 응답 처리에 문제가 있는 것입니다. HttpURLConnection
구현은 연결을 유지하는 데 약간 버그가 있는 이전 JRE에 있습니다. http.keepAlive
시스템 속성을 false
로 설정하여 이 기능을 끌 수 있습니다. 다음과 같이 애플리케이션 시작 시 프로그래밍 방식으로 이 작업을 수행할 수 있습니다.
System.setProperty("http.keepAlive", "false");
파일 업로드
일반적으로 혼합 POST 콘텐츠(이진 및 문자 데이터)에 대해 multipart/form-data
인코딩은 RFC2388에 자세히 설명되어 있습니다.
String param = "value"; File textFile = new File("/path/to/file.txt"); File binaryFile = new File("/path/to/file.bin"); String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value. String CRLF = "\r\n"; // Line separator required by multipart/form-data. URLConnection connection = new URL(url).openConnection(); connection.setDoOutput(true); connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); try ( OutputStream output = connection.getOutputStream(); PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true); ) { // Send normal param. writer.append("--" + boundary).append(CRLF); writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF); writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF); writer.append(CRLF).append(param).append(CRLF).flush(); // Send text file. writer.append("--" + boundary).append(CRLF); writer.append("Content-Disposition: form-data; name=\"textFile\"; filename=\"" + textFile.getName() + "\"").append(CRLF); writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF); // Text file itself must be saved in this charset! writer.append(CRLF).flush(); Files.copy(textFile.toPath(), output); output.flush(); // Important before continuing with writer! writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary. // Send binary file. writer.append("--" + boundary).append(CRLF); writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + binaryFile.getName() + "\"").append(CRLF); writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(binaryFile.getName())).append(CRLF); writer.append("Content-Transfer-Encoding: binary").append(CRLF); writer.append(CRLF).flush(); Files.copy(binaryFile.toPath(), output); output.flush(); // Important before continuing with writer! writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary. // End of multipart/form-data. writer.append("--" + boundary + "--").append(CRLF).flush(); }
다른 쪽이 HttpServlet
이면 해당 doPost()
메서드가 호출되고 해당 부분은 HttpServletRequest#getPart()
의해 사용 가능합니다(참고로 getParameter()
등이 아닙니다 !). 그러나 getPart()
메서드는 비교적 새로운 방법으로 Servlet 3.0(Glassfish 3, Tomcat 7 등)에 도입되었습니다. Servlet 3.0 이전에는 Apache Commons FileUpload multipart/form-data
요청을 구문 분석하는 것이 가장 좋습니다. 또한 FileUpload 및 Servelt 3.0 접근 방식의 예에 대해서는 이 답변 을 참조하십시오.
신뢰할 수 없거나 잘못 구성된 HTTPS 사이트 처리
Java 대신 Android용으로 개발하는 경우 주의 하십시오. 개발 중에 배포된 올바른 인증서가 없는 경우 아래 해결 방법으로 시간을 절약할 수 있습니다. 그러나 생산에 사용해서는 안됩니다. 요즘(2021년 4월) Google은 안전하지 않은 호스트 이름 확인 프로그램을 감지하는 경우 Play 스토어에서 앱 배포를 허용하지 않습니다( https://support.google.com/faqs/answer/7188426 참조).
웹 스크레이퍼를 작성 중이기 때문에 때때로 HTTPS URL을 연결해야 합니다. 이 경우 javax.net.ssl.SSLException: SSL 인증서를 최신 상태로 유지하지 않는 일부 HTTPS 사이트에서 javax.net.ssl.SSLException: Not trusted server certificate
java.security.cert.CertificateException: No subject alternative DNS name matching [hostname] found
일부 잘못 구성된 HTTPS 사이트 java.security.cert.CertificateException: No subject alternative DNS name matching [hostname] found
또는 javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name
웹 스크레이퍼 클래스에서 다음과 같은 일회성 static
HttpsURLConnection
보다 관대하게 만들어 해당 예외를 더 이상 발생시키지 않아야 합니다.
static { TrustManager[] trustAllCertificates = new TrustManager[] { new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return null; // Not relevant. } @Override public void checkClientTrusted(X509Certificate[] certs, String authType) { // Do nothing. Just allow them all. } @Override public void checkServerTrusted(X509Certificate[] certs, String authType) { // Do nothing. Just allow them all. } } }; HostnameVerifier trustAllHostnames = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; // Just allow them all. } }; try { System.setProperty("jsse.enableSNIExtension", "false"); SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCertificates, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier(trustAllHostnames); } catch (GeneralSecurityException e) { throw new ExceptionInInitializerError(e); } }
마지막 말
Apache HttpComponents HttpClient 는 이 모든 면에서 훨씬 더 편리합니다. :)
HTML 구문 분석 및 추출
원하는 것이 HTML에서 데이터를 구문 분석하고 추출하는 것이라면 Jsoup 과 같은 HTML 파서를 사용하는 것이 좋습니다.
Community WikiHTTP 작업 할 때 그것은을 참조 거의 항상 더 유용 HttpURLConnection
기본 클래스보다는 URLConnection
(이후 URLConnection
당신이 요청하는 경우 추상 클래스입니다 URLConnection.openConnection()
HTTP를 URL에 당신이 어쨌든 다시 얻을 것이다 기능).
그런 다음 URLConnection#setDoOutput(true)
에 의존하여 요청 메서드를 POST 로 암시적으로 설정하는 대신 httpURLConnection.setRequestMethod("POST")
를 수행할 수 있습니다. 이 작업은 일부가 더 자연스럽거나 다음과 같은 다른 요청 메서드를 지정할 수도 있습니다. 넣기 , 삭제 , ...).
또한 유용한 HTTP 상수를 제공하므로 다음을 수행할 수 있습니다.
int responseCode = httpURLConnection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) {
Community WikiStack Overflow에 대한 이 질문과 다른 질문에서 영감을 받아 여기에서 찾을 수 있는 대부분의 기술을 구현 하는 최소한의 오픈 소스 basic-http-client를 만들었습니다.
google-http-java-client 도 훌륭한 오픈 소스 리소스입니다.
Community Wikikevinsawicki/http-request 의 코드를 살펴보는 것이 좋습니다. HttpUrlConnection
위에 있는 래퍼입니다. 지금 바로 요청하거나 소스를 살펴볼 수 있는 경우에 대비하여 훨씬 간단한 API를 제공합니다. (너무 크지는 않음) 연결이 처리되는 방법을 살펴보십시오.
예: application/json
및 일부 쿼리 매개변수를 사용 GET
요청을 수행합니다.
// GET http://google.com?q=baseball%20gloves&size=100 String response = HttpRequest.get("http://google.com", true, "q", "baseball gloves", "size", 100) .accept("application/json") .body(); System.out.println("Response was: " + response);
Community Wiki업데이트
새로운 HTTP 클라이언트는 Java 9와 함께 제공되지만 jdk.incubator.httpclient
라는 인큐베이터 모듈의 일부로 제공됩니다. 인큐베이터 모듈은 API가 향후 릴리스에서 완료 또는 제거를 향해 진행되는 동안 최종 API가 아닌 API를 개발자에게 제공하는 수단입니다.
Java 9에서는 다음과 같은 GET
// GET HttpResponse response = HttpRequest .create(new URI("http://www.stackoverflow.com")) .headers("Foo", "foovalue", "Bar", "barvalue") .GET() .response();
그런 다음 반환된 HttpResponse
검사할 수 있습니다.
int statusCode = response.statusCode(); String responseBody = response.body(HttpResponse.asString());
이 새로운 HTTP 클라이언트는 java.httpclient
jdk.incubator.httpclient
module-info.java
파일에서 이 종속성을 선언해야 합니다.
module com.foo.bar { requires jdk.incubator.httpclient; }
Community WikiHTTP URL 조회수에는 GET / POST의 두 가지 옵션이 있습니다.
요청 받기:
HttpURLConnection.setFollowRedirects(true); // Defaults to true String url = "https://name_of_the_url"; URL request_url = new URL(url); HttpURLConnection http_conn = (HttpURLConnection)request_url.openConnection(); http_conn.setConnectTimeout(100000); http_conn.setReadTimeout(100000); http_conn.setInstanceFollowRedirects(true); System.out.println(String.valueOf(http_conn.getResponseCode()));
POST 요청:
HttpURLConnection.setFollowRedirects(true); // Defaults to true String url = "https://name_of_the_url" URL request_url = new URL(url); HttpURLConnection http_conn = (HttpURLConnection)request_url.openConnection(); http_conn.setConnectTimeout(100000); http_conn.setReadTimeout(100000); http_conn.setInstanceFollowRedirects(true); http_conn.setDoOutput(true); PrintWriter out = new PrintWriter(http_conn.getOutputStream()); if (urlparameter != null) { out.println(urlparameter); } out.close(); out = null; System.out.println(String.valueOf(http_conn.getResponseCode()));
Community Wiki저 역시 이 반응에 많은 영감을 받았습니다.
나는 종종 일부 HTTP를 수행해야 하는 프로젝트에 참여하고 있으며 많은 타사 종속성을 가져오고 싶지 않을 수 있습니다.
나는 이 대화의 일부를 기반으로 내 자신의 유틸리티를 작성하기 시작했습니다.
package org.boon.utils; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.Map; import static org.boon.utils.IO.read; public class HTTP {
그런 다음 무리 또는 정적 메서드만 있습니다.
public static String get( final String url) { Exceptions.tryIt(() -> { URLConnection connection; connection = doGet(url, null, null, null); return extractResponseString(connection); }); return null; } public static String getWithHeaders( final String url, final Map<String, ? extends Object> headers) { URLConnection connection; try { connection = doGet(url, headers, null, null); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String getWithContentType( final String url, final Map<String, ? extends Object> headers, String contentType) { URLConnection connection; try { connection = doGet(url, headers, contentType, null); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String getWithCharSet( final String url, final Map<String, ? extends Object> headers, String contentType, String charSet) { URLConnection connection; try { connection = doGet(url, headers, contentType, charSet); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } }
그럼 포스팅...
public static String postBody( final String url, final String body) { URLConnection connection; try { connection = doPost(url, null, "text/plain", null, body); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String postBodyWithHeaders( final String url, final Map<String, ? extends Object> headers, final String body) { URLConnection connection; try { connection = doPost(url, headers, "text/plain", null, body); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String postBodyWithContentType( final String url, final Map<String, ? extends Object> headers, final String contentType, final String body) { URLConnection connection; try { connection = doPost(url, headers, contentType, null, body); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String postBodyWithCharset( final String url, final Map<String, ? extends Object> headers, final String contentType, final String charSet, final String body) { URLConnection connection; try { connection = doPost(url, headers, contentType, charSet, body); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } private static URLConnection doPost(String url, Map<String, ? extends Object> headers, String contentType, String charset, String body ) throws IOException { URLConnection connection;/* Handle output. */ connection = new URL(url).openConnection(); connection.setDoOutput(true); manageContentTypeHeaders(contentType, charset, connection); manageHeaders(headers, connection); IO.write(connection.getOutputStream(), body, IO.CHARSET); return connection; } private static void manageHeaders(Map<String, ? extends Object> headers, URLConnection connection) { if (headers != null) { for (Map.Entry<String, ? extends Object> entry : headers.entrySet()) { connection.setRequestProperty(entry.getKey(), entry.getValue().toString()); } } } private static void manageContentTypeHeaders(String contentType, String charset, URLConnection connection) { connection.setRequestProperty("Accept-Charset", charset == null ? IO.CHARSET : charset); if (contentType!=null && !contentType.isEmpty()) { connection.setRequestProperty("Content-Type", contentType); } } private static URLConnection doGet(String url, Map<String, ? extends Object> headers, String contentType, String charset) throws IOException { URLConnection connection;/* Handle output. */ connection = new URL(url).openConnection(); manageContentTypeHeaders(contentType, charset, connection); manageHeaders(headers, connection); return connection; } private static String extractResponseString(URLConnection connection) throws IOException { /* Handle input. */ HttpURLConnection http = (HttpURLConnection)connection; int status = http.getResponseCode(); String charset = getCharset(connection.getHeaderField("Content-Type")); if (status==200) { return readResponseBody(http, charset); } else { return readErrorResponseBody(http, status, charset); } } private static String readErrorResponseBody(HttpURLConnection http, int status, String charset) { InputStream errorStream = http.getErrorStream(); if ( errorStream!=null ) { String error = charset== null ? read( errorStream ) : read( errorStream, charset ); throw new RuntimeException("STATUS CODE =" + status + "\n\n" + error); } else { throw new RuntimeException("STATUS CODE =" + status); } } private static String readResponseBody(HttpURLConnection http, String charset) throws IOException { if (charset != null) { return read(http.getInputStream(), charset); } else { return read(http.getInputStream()); } } private static String getCharset(String contentType) { if (contentType==null) { return null; } String charset = null; for (String param : contentType.replace(" ", "").split(";")) { if (param.startsWith("charset=")) { charset = param.split("=", 2)[1]; break; } } charset = charset == null ? IO.CHARSET : charset; return charset; }
글쎄, 당신은 아이디어를 얻을....
테스트는 다음과 같습니다.
static class MyHandler implements HttpHandler { public void handle(HttpExchange t) throws IOException { InputStream requestBody = t.getRequestBody(); String body = IO.read(requestBody); Headers requestHeaders = t.getRequestHeaders(); body = body + "\n" + copy(requestHeaders).toString(); t.sendResponseHeaders(200, body.length()); OutputStream os = t.getResponseBody(); os.write(body.getBytes()); os.close(); } } @Test public void testHappy() throws Exception { HttpServer server = HttpServer.create(new InetSocketAddress(9212), 0); server.createContext("/test", new MyHandler()); server.setExecutor(null); // creates a default executor server.start(); Thread.sleep(10); Map<String,String> headers = map("foo", "bar", "fun", "sun"); String response = HTTP.postBodyWithContentType("http://localhost:9212/test", headers, "text/plain", "hi mom"); System.out.println(response); assertTrue(response.contains("hi mom")); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.postBodyWithCharset("http://localhost:9212/test", headers, "text/plain", "UTF-8", "hi mom"); System.out.println(response); assertTrue(response.contains("hi mom")); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.postBodyWithHeaders("http://localhost:9212/test", headers, "hi mom"); System.out.println(response); assertTrue(response.contains("hi mom")); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.get("http://localhost:9212/test"); System.out.println(response); response = HTTP.getWithHeaders("http://localhost:9212/test", headers); System.out.println(response); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.getWithContentType("http://localhost:9212/test", headers, "text/plain"); System.out.println(response); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.getWithCharSet("http://localhost:9212/test", headers, "text/plain", "UTF-8"); System.out.println(response); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); Thread.sleep(10); server.stop(0); } @Test public void testPostBody() throws Exception { HttpServer server = HttpServer.create(new InetSocketAddress(9220), 0); server.createContext("/test", new MyHandler()); server.setExecutor(null); // creates a default executor server.start(); Thread.sleep(10); Map<String,String> headers = map("foo", "bar", "fun", "sun"); String response = HTTP.postBody("http://localhost:9220/test", "hi mom"); assertTrue(response.contains("hi mom")); Thread.sleep(10); server.stop(0); } @Test(expected = RuntimeException.class) public void testSad() throws Exception { HttpServer server = HttpServer.create(new InetSocketAddress(9213), 0); server.createContext("/test", new MyHandler()); server.setExecutor(null); // creates a default executor server.start(); Thread.sleep(10); Map<String,String> headers = map("foo", "bar", "fun", "sun"); String response = HTTP.postBodyWithContentType("http://localhost:9213/foo", headers, "text/plain", "hi mom"); System.out.println(response); assertTrue(response.contains("hi mom")); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); Thread.sleep(10); server.stop(0); }
나머지는 여기에서 찾을 수 있습니다.
https://github.com/RichardHightower/boon
내 목표는 좀 더 쉬운 방법으로 하고 싶은 일반적인 것들을 제공하는 것입니다....
Community WikiHttpClient
를 선호 하는 이 기사에 의해 잘못 인도되었습니다.
HttpURLConnection
이 이 기사 에서 남을 것이라는 것을 깨달았습니다.
Google 블로그 :
Apache HTTP 클라이언트는 Eclair 및 Froyo에서 버그가 더 적습니다. 이 릴리스에 대한 최선의 선택입니다. Gingerbread의 경우 HttpURLConnection이 최선의 선택입니다. 간단한 API와 작은 크기로 Android에 적합합니다.
투명한 압축 및 응답 캐싱은 네트워크 사용을 줄이고 속도를 개선하며 배터리를 절약합니다. 새 응용 프로그램은 HttpURLConnection을 사용해야 합니다. 앞으로 우리가 에너지를 소비할 곳입니다.
이 기사 와 흐름 질문에 대한 다른 스택을 읽은 후 HttpURLConnection
이 더 오랜 기간 동안 유지될 것이라고 확신합니다.
HttpURLConnections
선호하는 SE 질문 중 일부:
Android에서는 UrlEncodedFormEntity를 사용하지 않고 URL 인코딩된 양식 데이터로 POST 요청을 수행합니다.
HttpPost는 Java 프로젝트에서 작동하지만 Android에서는 작동하지 않습니다.
Community Wiki기본적으로 효율적인 HTTP 클라이언트인 OkHttp 도 있습니다.
- HTTP/2 지원을 통해 동일한 호스트에 대한 모든 요청이 소켓을 공유할 수 있습니다.
- 연결 풀링은 요청 대기 시간을 줄입니다(HTTP/2를 사용할 수 없는 경우).
- 투명 GZIP은 다운로드 크기를 줄입니다.
- 응답 캐싱은 반복 요청에 대해 네트워크를 완전히 피합니다.
OkHttpClient
의 인스턴스를 만듭니다.
OkHttpClient client = new OkHttpClient();
그런 다음 GET
요청을 준비합니다.
Request request = new Request.Builder() .url(url) .build();
마지막으로 OkHttpClient
를 사용하여 준비된 Request
를 보냅니다.
Response response = client.newCall(request).execute();
자세한 내용은 OkHttp의 설명서를 참조하세요.
Community Wikijcabi-http JdkRequest
를 사용할 수도 있습니다. 이 모든 작업은 HttpURLConnection 데코레이팅, HTTP 요청 실행 및 응답 구문 분석과 같은 모든 작업을 수행합니다. 예를 들면 다음과 같습니다.
String html = new JdkRequest("http://www.google.com").fetch().body();
자세한 내용은 이 블로그 게시물을 확인하십시오. http://www.yegor256.com/2014/04/11/jcabi-http-intro.html
Community WikiHTTP GET을 사용하는 경우 다음 행을 제거하십시오.
urlConnection.setDoOutput(true);
Community Wiki출처 : http:www.stackoverflow.com/questions/2793150/how-to-use-java-net-urlconnection-to-fire-and-handle-http-requests