如何在Java发送HTTP请求?

在Java中,如何撰写HTTP请求消息并将其发送到HTTP web服务器?

1101658 次浏览

你可以使用java.net.HttpUrlConnection

示例(从这里),经过改进。包括在链接腐烂的情况下:

public static String executePost(String targetURL, String urlParameters) {
HttpURLConnection connection = null;


try {
//Create connection
URL url = new URL(targetURL);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");


connection.setRequestProperty("Content-Length",
Integer.toString(urlParameters.getBytes().length));
connection.setRequestProperty("Content-Language", "en-US");


connection.setUseCaches(false);
connection.setDoOutput(true);


//Send request
DataOutputStream wr = new DataOutputStream (
connection.getOutputStream());
wr.writeBytes(urlParameters);
wr.close();


//Get Response
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
StringBuilder response = new StringBuilder(); // or StringBuffer if Java version 5+
String line;
while ((line = rd.readLine()) != null) {
response.append(line);
response.append('\r');
}
rd.close();
return response.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (connection != null) {
connection.disconnect();
}
}
}

Oracle java教程

import java.net.*;
import java.io.*;


public class URLConnectionReader {
public static void main(String[] args) throws Exception {
URL yahoo = new URL("http://www.yahoo.com/");
URLConnection yc = yahoo.openConnection();
BufferedReader in = new BufferedReader(
new InputStreamReader(
yc.getInputStream()));
String inputLine;


while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
}

我知道其他人会推荐Apache的http-客户端,但是它增加了复杂性(例如,更多可能出错的东西),这是很少被保证的。对于简单的任务,java.net.URL就可以了。

URL url = new URL("http://www.y.com/url");
InputStream is = url.openStream();
try {
/* Now read the retrieved document from the stream. */
...
} finally {
is.close();
}

Apache HttpComponents。这两个模块的例子——HttpCoreHttpClient会让你马上开始。

并不是说HttpUrlConnection是一个糟糕的选择,HttpComponents将抽象出大量繁琐的编码。如果你真的想用最少的代码来支持大量的HTTP服务器/客户端,我推荐这样做。顺便说一下,HttpCore可以用于功能最少的应用程序(客户端或服务器),而HttpClient用于需要支持多种身份验证方案、cookie支持等的客户端。

这里有一个很棒的链接,关于通过Example Depot发送一个POST请求在这里::

try {
// Construct data
String data = URLEncoder.encode("key1", "UTF-8") + "=" + URLEncoder.encode("value1", "UTF-8");
data += "&" + URLEncoder.encode("key2", "UTF-8") + "=" + URLEncoder.encode("value2", "UTF-8");


// Send data
URL url = new URL("http://hostname:80/cgi");
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();


// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
// Process line...
}
wr.close();
rd.close();
} catch (Exception e) {
}

如果您想发送一个GET请求,您可以稍微修改代码以满足您的需要。具体来说,您必须在URL的构造函数中添加参数。然后,也注释掉这个wr.write(data);

有一件事没有写下来,你应该注意,就是超时。特别是如果你想在WebServices中使用它,你必须设置超时,否则上面的代码将无限期地等待,或者至少等待很长时间,这可能是你不想要的。

超时设置如下conn.setReadTimeout(2000);,输入参数以毫秒为单位

这对你有帮助。不要忘记将JAR HttpClient.jar添加到类路径中。

import java.io.FileOutputStream;
import java.io.IOException;


import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;


public class MainSendRequest {


static String url =
"http://localhost:8080/HttpRequestSample/RequestSend.jsp";


public static void main(String[] args) {


//Instantiate an HttpClient
HttpClient client = new HttpClient();


//Instantiate a GET HTTP method
PostMethod method = new PostMethod(url);
method.setRequestHeader("Content-type",
"text/xml; charset=ISO-8859-1");


//Define name-value pairs to set into the QueryString
NameValuePair nvp1= new NameValuePair("firstName","fname");
NameValuePair nvp2= new NameValuePair("lastName","lname");
NameValuePair nvp3= new NameValuePair("email","email@email.com");


method.setQueryString(new NameValuePair[]{nvp1,nvp2,nvp3});


try{
int statusCode = client.executeMethod(method);


System.out.println("Status Code = "+statusCode);
System.out.println("QueryString>>> "+method.getQueryString());
System.out.println("Status Text>>>"
+HttpStatus.getStatusText(statusCode));


//Get data as a String
System.out.println(method.getResponseBodyAsString());


//OR as a byte array
byte [] res  = method.getResponseBody();


//write to file
FileOutputStream fos= new FileOutputStream("donepage.html");
fos.write(res);


//release connection
method.releaseConnection();
}
catch(IOException e) {
e.printStackTrace();
}
}
}

你可以使用Socket来实现

String host = "www.yourhost.com";
Socket socket = new Socket(host, 80);
String request = "GET / HTTP/1.0\r\n\r\n";
OutputStream os = socket.getOutputStream();
os.write(request.getBytes());
os.flush();


InputStream is = socket.getInputStream();
int ch;
while( (ch=is.read())!= -1)
System.out.print((char)ch);
socket.close();

下面是一个完整的Java 7程序:

class GETHTTPResource {
public static void main(String[] args) throws Exception {
try (java.util.Scanner s = new java.util.Scanner(new java.net.URL("http://example.com/").openStream())) {
System.out.println(s.useDelimiter("\\A").next());
}
}
}

新的try-with-resources将自动关闭Scanner,而Scanner将自动关闭InputStream。

谷歌Java HTTP客户端为http请求提供了很好的API。您可以轻松地添加JSON支持等。虽然对于简单的要求来说可能有点过分。

import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import java.io.IOException;
import java.io.InputStream;


public class Network {


static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();


public void getRequest(String reqUrl) throws IOException {
GenericUrl url = new GenericUrl(reqUrl);
HttpRequest request = HTTP_TRANSPORT.createRequestFactory().buildGetRequest(url);
HttpResponse response = request.execute();
System.out.println(response.getStatusCode());


InputStream is = response.getContent();
int ch;
while ((ch = is.read()) != -1) {
System.out.print((char) ch);
}
response.disconnect();
}
}

如果你正在使用Java 11或更新的类(Android除外),而不是遗留的HttpUrlConnection类,你可以使用Java 11新的HTTP客户端API

得到请求示例:

var uri = URI.create("https://httpbin.org/get?age=26&isHappy=true");
var client = HttpClient.newHttpClient();
var request = HttpRequest
.newBuilder()
.uri(uri)
.header("accept", "application/json")
.GET()
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());

同一请求异步执行:

var responseAsync = client
.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println);
// responseAsync.join(); // Wait for completion

帖子请求示例:

var request = HttpRequest
.newBuilder()
.uri(uri)
.version(HttpClient.Version.HTTP_2)
.timeout(Duration.ofMinutes(1))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer fake")
.POST(BodyPublishers.ofString("{ title: 'This is cool' }"))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());

要以多部分(multipart/form-data)或url编码(application/x-www-form-urlencoded)格式发送表单数据,请参见这个解决方案

有关HTTP客户端API的示例和更多信息,请参见这篇文章

对于Java标准库HTTP 服务器,请参见这篇文章