【问题标题】:Sending HTTP POST Request In Java在 Java 中发送 HTTP POST 请求
【发布时间】:2011-03-20 11:27:45
【问题描述】:

让我们假设这个 URL...

http://www.example.com/page.php?id=10            

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

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

我如何在 Java 中做到这一点?

我试过这个:

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

但我仍然不知道如何通过 POST 发送它

【问题讨论】:

标签: java http post


【解决方案1】:

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

【讨论】:

  • 它 HttpURLConnection.setRequestMethod() :)
【解决方案2】:
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());

【讨论】:

  • 需要注意的重要一点:使用 String.getBytes() 以外的任何东西似乎都不起作用。例如,使用 PrintWriter 完全失败。
  • 以及如何设置2个post数据?用冒号、逗号分隔?
  • encode(String) 已弃用。您必须使用encode(String, String),它指定编码类型。示例:encode(rawData, "UTF-8").
  • 您可能想在最后关注。这将确保请求完成并且服务器有机会处理响应:conn.getResponseCode();
  • 不要编码整个字符串。你必须只编码每个参数的值
【解决方案3】:

更新答案:

由于原始答案中的某些类在较新版本的 Apache HTTP 组件中已弃用,因此我发布了此更新。

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

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
    }
}

原答案:

我推荐使用 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.

欲了解更多信息,请查看此网址:http://hc.apache.org/

【讨论】:

  • 在尝试了一段时间后我的手 PostMethod 似乎它现在实际上被称为 HttpPost 根据 stackoverflow.com/a/9242394/1338936 - 只是为了任何像我一样找到这个答案的人:)
  • @Juan(和 Martin Lyne)感谢 cmets。我刚刚更新了答案。
  • 你应该添加导入的库
  • 并且还给出了无法解析getEntity()的错误
  • 对于遇到与@AdarshSingh 相同问题的任何人,我在查看this 提供的示例后找到了解决方案。只需将 HttpClient 更改为 CloseableHttpClient,并将 HttpResponse 更改为 CloseableHttpResponse!
【解决方案4】:

第一个答案很好,但我不得不添加 try/catch 以避免 Java 编译器错误。
此外,我很难弄清楚如何使用 Java 库阅读 HttpResponse

这里是更完整的代码:

/*
 * 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();
}

【讨论】:

  • 抱歉,您没有发现任何错误,您已经介绍了它们。在无法处理的地方捕获异常是完全错误的,e.printStackTrace() 不会处理任何事情。
  • java.net.ConnectException:连接超时:连接
【解决方案5】:

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

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

看看Fluent API

【解决方案6】:

在 vanilla Java 中发送 POST 请求很容易。从URL 开始,我们不需要使用url.openConnection(); 将其转换为URLConnection。之后,我们需要将其转换为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);

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

发送一个简单的表格

来自 http 表单的普通 POST 具有 well defined 格式。我们需要将输入转换为这种格式:

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;

然后我们可以将表单内容附加到带有适当标头的 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()

发送 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()

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


使用 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));
}

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

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()

【讨论】:

  • 这篇文章很有用,但也有很大缺陷。我花了 2 天时间才让它工作。因此,要使其正常工作,您必须将 StandartCharsets.UTF8 替换为 StandardCharsets.UTF_8 。 boundaryBytes 和 finishBoundaryBytes 需要获取两个额外的连字符,它们不在 Content-Type 中传输,所以 boundaryBytes = ("--" + boundary + "\r\n").get... 你还需要传输一次 boundaryBytes BEFORE 第一个字段或第一个字段将被忽略!
  • 为什么需要out.write(finishBoundaryBytes);线? http.connect(); 会执行发送 POST,不是吗?
  • 考虑到它是Java,它比我预期的要容易:)
  • 神秘的 \r\n\r\n 表示 CRLF CRLF(回车 + 换行)。它创建 2x 新行。第一个新行是完成当前行。第二行是在请求中区分 http 标头和 http 正文。 HTTP 是基于 ASCII 的协议。这是插入\r\n的规则。
  • "Easy" 在其他语言中,这就像一个单线电话。为什么在 Java 中是 8-12 行? qr.ae/TWAQA6
【解决方案7】:

通过 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);

你已经完成了。现在您可以使用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.
}

【讨论】:

    【解决方案8】:

    我建议使用基于 apache http api 构建的 http-request

    HttpRequest<String> httpRequest = HttpRequestBuilder.createPost("http://www.example.com/page.php", String.class)
    .responseDeserializer(ResponseDeserializer.ignorableDeserializer()).build();
    
    public void send(){
       String response = httpRequest.execute("id", "10").get();
    }
    

    【讨论】:

      【解决方案9】:

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

      然后您会看到以下窗口,以选择您希望请求代码使用的语言:

      【讨论】:

        【解决方案10】:

        使用 okhttp :

        okhttp 的源代码可以在这里找到https://github.com/square/okhttp

        如果你正在编写一个 pom 项目,请添加此依赖项

        <dependency>
                <groupId>com.squareup.okhttp3</groupId>
                <artifactId>okhttp</artifactId>
                <version>4.2.2</version>
            </dependency>
        

        如果不是简单地在互联网上搜索“下载 okhttp”。将出现几个结果,您可以在其中下载 jar。

        你的代码:

        import okhttp3.*;
                
        import java.io.IOException;
        
        public class ClassName{
                private void sendPost() throws IOException {
                
                        // form parameters
                        RequestBody formBody = new FormBody.Builder()
                                .add("id", 10)
                                .build();
                
                        Request request = new Request.Builder()
                                .url("http://www.example.com/page.php")
                                .post(formBody)
                                .build();
        
        
                        OkHttpClient httpClient = new OkHttpClient();
                
                        try (Response response = httpClient.newCall(request).execute()) {
                
                            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
                
                            // Get response body
                            System.out.println(response.body().string());
                        }
                }
            }
        

        【讨论】:

          【解决方案11】:

          使用 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());
          

          这里有更多信息: https://openjdk.java.net/groups/net/httpclient/recipes.html#post

          【讨论】:

            猜你喜欢
            • 2018-08-09
            • 1970-01-01
            • 1970-01-01
            • 2013-11-13
            • 1970-01-01
            • 2022-08-11
            相关资源
            最近更新 更多