此处经常询问java.net.URLConnection
的使用情况,而Oracle tutorial 太简明扼要。
该教程基本上只显示如何触发GET请求并读取响应。它没有解释如何使用它来执行POST请求,设置请求标头,读取响应标头,处理cookie,提交HTML表单,上传文件等。
那么,我如何使用java.net.URLConnection
来触发和处理“高级”HTTP请求?
答案 0 :(得分:2629)
答案 1 :(得分:88)
使用HTTP时,引用HttpURLConnection
而不是基类URLConnection
几乎总是更有用(因为URLConnection
是一个抽象类,当你要求URLConnection.openConnection()
时在HTTP URL上,无论如何你都会得到它。)
然后你可以而不是依赖URLConnection#setDoOutput(true)
来隐式地将请求方法设置为 POST 而不是httpURLConnection.setRequestMethod("POST")
有些人可能会发现更自然(这也允许你指定其他请求方法,例如 PUT , DELETE ,...)。
它还提供了有用的HTTP常量,因此您可以执行以下操作:
int responseCode = httpURLConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
答案 2 :(得分:50)
受到关于SO的这个问题和其他问题的启发,我创建了一个最小的开源basic-http-client,它体现了这里发现的大部分技术。
google-http-java-client也是一个很好的开源资源。
答案 3 :(得分:23)
使用HTTP URL Hits有两个选项:GET / POST
GET请求: -
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()));
答案 4 :(得分:21)
我建议您查看kevinsawicki/http-request上的代码,它基本上是HttpUrlConnection
之上的包装器,它提供了一个更简单的API,以防您只是想立即发出请求或者您可以看看来源(它不是太大)来看看如何处理连接。
示例:发出内容类型为GET
的{{1}}请求和一些查询参数:
application/json
答案 5 :(得分:20)
我也对这种反应非常鼓舞。
我经常在我需要做一些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
我的目标是以更简单的方式提供想要做的常见事情....
答案 6 :(得分:20)
新的HTTP客户端随Java 9一起提供,但作为一部分 孵化器模块名为
jdk.incubator.httpclient
。孵化器模块是 一种将非最终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;
}
答案 7 :(得分:16)
最初我被这个article误导了HttpClient
。
后来我意识到HttpURLConnection
将会留在article
根据Google博客:
Apache HTTP客户端在Eclair和Froyo上的错误更少。它是这些版本的最佳选择。对于Gingerbread,HttpURLConnection是最佳选择。它简单的API和小巧的尺寸使其非常适合Android。
透明压缩和响应缓存可减少网络使用,提高速度并节省电池电量。新的应用程序应该使用HttpURLConnection;这是我们将继续投入精力的地方。
在阅读this article和其他一些堆叠问题之后,我确信HttpURLConnection
将会持续更长时间。
有些赞成HttpURLConnections
的SE问题:
On Android, make a POST request with URL Encoded Form data without using UrlEncodedFormEntity
答案 8 :(得分:13)
您还可以使用JdkRequest
中的jcabi-http(我是开发人员),它可以为您完成所有这些工作,解析HttpURLConnection,触发HTTP请求并解析响应,例如:
String html = new JdkRequest("http://www.google.com").fetch().body();
查看此博文以获取更多信息:http://www.yegor256.com/2014/04/11/jcabi-http-intro.html
答案 9 :(得分:13)
还有OkHttp,这是一个默认有效的HTTP客户端:
- 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's documentation
答案 10 :(得分:11)
如果您使用的是http,请删除此行
urlConnection.setDoOutput(true);