在Java中发送HTTP POST请求

Jaz*_*azz 280 java post http

我们假设这个URL ...

http://www.example.com/page.php?id=10            
Run Code Online (Sandbox Code Playgroud)

(这里需要在POST请求中发送id)

我想发送id = 10到服务器page.php,它在POST方法中接受它.

我怎样才能从Java中做到这一点?

我试过这个:

URL aaa = new URL("http://www.example.com/page.php");
URLConnection ccc = aaa.openConnection();
Run Code Online (Sandbox Code Playgroud)

但我仍然无法弄清楚如何通过POST发送它

mhs*_*ams 320

更新答案:

由于在最初的答案中,某些类在较新版本的Apache HTTP Components中已弃用,因此我发布此更新.

顺便说一句,您可以在此处访问完整文档以获取更多示例.

HttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost("http://www.a-domain.com/foo/");

// Request parameters and other properties.
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
params.add(new BasicNameValuePair("param-1", "12345"));
params.add(new BasicNameValuePair("param-2", "Hello!"));
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));

//Execute and get the response.
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();

if (entity != null) {
    try (InputStream instream = entity.getContent()) {
        // do something useful
    }
}
Run Code Online (Sandbox Code Playgroud)

原答案:

我建议使用Apache HttpClient.它更快,更容易实现.

HttpPost post = new HttpPost("http://jakarata.apache.org/");
NameValuePair[] data = {
    new NameValuePair("user", "joe"),
    new NameValuePair("password", "bloggs")
};
post.setRequestBody(data);
// execute method and handle any error responses.
...
InputStream in = post.getResponseBodyAsStream();
// handle response.
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请查看此URL:http://hc.apache.org/

  • 在尝试了一段时间后,我的手上了`PostMethod`它似乎实际上现在被称为`HttpPost`,根据http://stackoverflow.com/a/9242394/1338936 - 只是为了找到这个答案的人,就像我做的那样:) (25认同)
  • 你应该添加导入的库 (6认同)
  • 我希望这个答案更新,因为它真的很有用. (2认同)

Fer*_*big 185

在vanilla Java中发送POST请求很容易.从a开始URL,我们需要将其转换为URLConnection使用url.openConnection();.之后,我们需要将其转换为a HttpURLConnection,因此我们可以访问其setRequestMethod()方法来设置我们的方法.我们最后说我们将通过连接发送数据.

URL url = new URL("https://www.example.com/login");
URLConnection con = url.openConnection();
HttpURLConnection http = (HttpURLConnection)con;
http.setRequestMethod("POST"); // PUT is another valid option
http.setDoOutput(true);
Run Code Online (Sandbox Code Playgroud)

然后我们需要说明我们要发送的内容:

发送一个简单的表格

来自http表单的普通POST具有明确定义的格式.我们需要将输入转换为以下格式:

Map<String,String> arguments = new HashMap<>();
arguments.put("username", "root");
arguments.put("password", "sjh76HSn!"); // This is a fake password obviously
StringJoiner sj = new StringJoiner("&");
for(Map.Entry<String,String> entry : arguments.entrySet())
    sj.add(URLEncoder.encode(entry.getKey(), "UTF-8") + "=" 
         + URLEncoder.encode(entry.getValue(), "UTF-8"));
byte[] out = sj.toString().getBytes(StandardCharsets.UTF_8);
int length = out.length;
Run Code Online (Sandbox Code Playgroud)

然后,我们可以使用正确的标头将表单内容附加到http请求并发送它.

http.setFixedLengthStreamingMode(length);
http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
http.connect();
try(OutputStream os = http.getOutputStream()) {
    os.write(out);
}
// Do something with http.getInputStream()
Run Code Online (Sandbox Code Playgroud)

发送JSON

我们也可以使用java发送json,这也很简单:

byte[] out = "{\"username\":\"root\",\"password\":\"password\"}" .getBytes(StandardCharsets.UTF_8);
int length = out.length;

http.setFixedLengthStreamingMode(length);
http.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
http.connect();
try(OutputStream os = http.getOutputStream()) {
    os.write(out);
}
// Do something with http.getInputStream()
Run Code Online (Sandbox Code Playgroud)

请记住,不同的服务器接受json的不同内容类型,请参阅问题.


使用java post发送文件

由于格式更复杂,因此可以认为发送文件更具挑战性.我们还将添加支持将文件作为字符串发送,因为我们不希望将文件完全缓冲到内存中.

为此,我们定义了一些辅助方法:

private void sendFile(OutputStream out, String name, InputStream in, String fileName) {
    String o = "Content-Disposition: form-data; name=\"" + URLEncoder.encode(name,"UTF-8") 
             + "\"; filename=\"" + URLEncoder.encode(filename,"UTF-8") + "\"\r\n\r\n";
    out.write(o.getBytes(StandardCharsets.UTF_8));
    byte[] buffer = new byte[2048];
    for (int n = 0; n >= 0; n = in.read(buffer))
        out.write(buffer, 0, n);
    out.write("\r\n".getBytes(StandardCharsets.UTF_8));
}

private void sendField(OutputStream out, String name, String field) {
    String o = "Content-Disposition: form-data; name=\"" 
             + URLEncoder.encode(name,"UTF-8") + "\"\r\n\r\n";
    out.write(o.getBytes(StandardCharsets.UTF_8));
    out.write(URLEncoder.encode(field,"UTF-8").getBytes(StandardCharsets.UTF_8));
    out.write("\r\n".getBytes(StandardCharsets.UTF_8));
}
Run Code Online (Sandbox Code Playgroud)

然后,我们可以使用这些方法创建一个多部分发布请求,如下所示:

String boundary = UUID.randomUUID().toString();
byte[] boundaryBytes = 
           ("--" + boundary + "\r\n").getBytes(StandardCharsets.UTF_8);
byte[] finishBoundaryBytes = 
           ("--" + boundary + "--").getBytes(StandardCharsets.UTF_8);
http.setRequestProperty("Content-Type", 
           "multipart/form-data; charset=UTF-8; boundary=" + boundary);

// Enable streaming mode with default settings
http.setChunkedStreamingMode(0); 

// Send our fields:
try(OutputStream out = http.getOutputStream()) {
    // Send our header (thx Algoman)
    out.write(boundaryBytes);

    // Send our first field
    sendField(out, "username", "root");

    // Send a seperator
    out.write(boundaryBytes);

    // Send our second field
    sendField(out, "password", "toor");

    // Send another seperator
    out.write(boundaryBytes);

    // Send our file
    try(InputStream file = new FileInputStream("test.txt")) {
        sendFile(out, "identification", file, "text.txt");
    }

    // Finish the request
    out.write(finishBoundaryBytes);
}


// Do something with http.getInputStream()
Run Code Online (Sandbox Code Playgroud)

  • _"在vanilla Java中发送POST请求很简单."_然后**几十行**代码,比如`requests.post('http://httpbin.org/post',data = Python中的''key':'value'})`我是Java的新手,所以这对我来说是一个非常奇怪的"简单"这个词:) (12认同)
  • 这篇文章很有用,但很有缺陷.我用了2天才开始工作.因此,要使其正常工作,您必须使用StandardCharsets.UTF_8替换StandartCharsets.UTF8.boundaryBytes和finishBoundaryBytes需要得到另外两个不在Content-Type中传输的连字符,所以boundaryBytes =(" - "+ boundary +"\ r \n").get ...你还需要传输一次boundaryBytes在第一个字段或第一个字段之前将被忽略! (5认同)
  • “简单” 在其他语言中,这就像单线呼叫。为什么Java中是8-12行?https://qr.ae/TWAQA6 (4认同)
  • 考虑到它是 Java 的,它比我预期的要容易一些:) (3认同)

Dud*_*lul 98

String rawData = "id=10";
String type = "application/x-www-form-urlencoded";
String encodedData = URLEncoder.encode( rawData, "UTF-8" ); 
URL u = new URL("http://www.example.com/page.php");
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty( "Content-Type", type );
conn.setRequestProperty( "Content-Length", String.valueOf(encodedData.length()));
OutputStream os = conn.getOutputStream();
os.write(encodedData.getBytes());
Run Code Online (Sandbox Code Playgroud)

  • 不推荐使用`encode(String)`.你必须使用`encode(String,String)`,它指定编码类型.示例:`encode(rawData,"UTF-8")`. (10认同)
  • 以及如何设置2个帖子数据?用冒号分隔,逗号? (5认同)
  • 您最后可能想要关注.这将确保请求完成,服务器有机会处理响应:conn.getResponseCode(); (3认同)
  • 不要编码整个字符串..你必须只编码每个参数的值 (3认同)

Mar*_*Cnu 22

第一个答案很棒,但我必须添加try/catch以避免Java编译器错误.
另外,我在如何阅读HttpResponseJava库时遇到了麻烦.

这是更完整的代码:

/*
 * Create the POST request
 */
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://example.com/");
// Request parameters and other properties.
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("user", "Bob"));
try {
    httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
} catch (UnsupportedEncodingException e) {
    // writing error to Log
    e.printStackTrace();
}
/*
 * Execute the HTTP Request
 */
try {
    HttpResponse response = httpClient.execute(httpPost);
    HttpEntity respEntity = response.getEntity();

    if (respEntity != null) {
        // EntityUtils to get the response content
        String content =  EntityUtils.toString(respEntity);
    }
} catch (ClientProtocolException e) {
    // writing exception to log
    e.printStackTrace();
} catch (IOException e) {
    // writing exception to log
    e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)

  • 抱歉,你没有发现任何错误,你介绍了它们.在无法处理它们的地方捕获异常是完全错误的,并且`e.printStackTrace()`不处理任何事情. (6认同)

Mat*_*Bak 17

使用Apache HTTP组件的一种简单方法是

Request.Post("http://www.example.com/page.php")
            .bodyForm(Form.form().add("id", "10").build())
            .execute()
            .returnContent();
Run Code Online (Sandbox Code Playgroud)

看看Fluent API

  • 只是为了方便;依赖项设置/信息:http://hc.apache.org/httpcomponents-client-4.5.x/httpclient/dependency-info.html和http://hc.apache.org/httpcomponents-client-4.5.x/ fluent-hc / dependency-info.html (3认同)

小智 11

我建议使用Postman来生成请求代码。只需使用 Postman 发出请求,然后点击代码选项卡:

代码选项卡

然后您将看到以下窗口来选择您希望请求代码使用的语言: 请求代码生成

  • 很好,但它使用非标准的 OkHttpClient 类,并且不会为您提供所需的导入:( (2认同)

cha*_*mar 5

使用post请求发送参数的最简单方法:

String postURL = "http://www.example.com/page.php";

HttpPost post = new HttpPost(postURL);

List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("id", "10"));

UrlEncodedFormEntity ent = new UrlEncodedFormEntity(params, "UTF-8");
post.setEntity(ent);

HttpClient client = new DefaultHttpClient();
HttpResponse responsePOST = client.execute(post);
Run Code Online (Sandbox Code Playgroud)

你做完了.现在你可以使用了responsePOST.获取响应内容为字符串:

BufferedReader reader = new BufferedReader(new  InputStreamReader(responsePOST.getEntity().getContent()), 2048);

if (responsePOST != null) {
    StringBuilder sb = new StringBuilder();
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(" line : " + line);
        sb.append(line);
    }
    String getResponseString = "";
    getResponseString = sb.toString();
//use server output getResponseString as string value.
}
Run Code Online (Sandbox Code Playgroud)


小智 5

使用 java.net 很容易:

public void post(String uri, String data) throws Exception {
HttpClient client = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create(uri))
        .POST(BodyPublishers.ofString(data))
        .build();

HttpResponse<?> response = client.send(request, BodyHandlers.discarding());
System.out.println(response.statusCode());
Run Code Online (Sandbox Code Playgroud)

以下是更多信息: https://openjdk.java.net/groups/net/httpclient/recipes.html#post


bur*_*sik 5

从java 11开始,可以使用java.net.http.HttpClient以更少的代码发出HTTP请求。

    var values = new HashMap<String, Integer>() {{
        put("id", 10);
    }};
    
    var objectMapper = new ObjectMapper();
    String requestBody = objectMapper
            .writeValueAsString(values);
    
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("http://www.example.com/abc"))
            .POST(HttpRequest.BodyPublishers.ofString(requestBody))
            .build();
    
    HttpResponse<String> response = client.send(request,
            HttpResponse.BodyHandlers.ofString());
    
    System.out.println(response.body());
Run Code Online (Sandbox Code Playgroud)


use*_*421 1

Call HttpURLConnection.setRequestMethod("POST")andHttpURLConnection.setDoOutput(true);实际上只需要后者,因为 POST 然后成为默认方法。