如何使用Apache HttpClient发送POST JSON请求?

112

我有如下代码:

final String url = "http://example.com";

final HttpClient httpClient = new HttpClient();
final PostMethod postMethod = new PostMethod(url);
postMethod.addRequestHeader("Content-Type", "application/json");
postMethod.addParameters(new NameValuePair[]{
        new NameValuePair("name", "value)
});
httpClient.executeMethod(httpMethod);
postMethod.getResponseBodyAsStream();
postMethod.releaseConnection();

它一直返回500错误。服务提供商说我需要发送JSON。如何在Apache HttpClient 3.1+中完成这个任务?


2
你的 NameValuePair 只是添加了一个请求参数,代码中没有发送任何 JSON。服务端期望接收什么样的 JSON 结构?你要发送的数据是什么?你需要使用 postMethod.setRequestEntity() 和包含你的 JSON 的 StringRequestEntity - Philipp Reichart
4个回答

212

Apache HttpClient不了解JSON,因此您需要单独构建JSON对象。为此,我建议查看来自json.org的简单JSON-java库。(如果"JSON-java"不适合您,json.org有一个大列表列出了不同语言可用的库。)

生成JSON后,您可以使用以下代码之类的内容来进行POST传输:

StringRequestEntity requestEntity = new StringRequestEntity(
    JSON_STRING,
    "application/json",
    "UTF-8");

PostMethod postMethod = new PostMethod("http://example.com/action");
postMethod.setRequestEntity(requestEntity);

int statusCode = httpClient.executeMethod(postMethod);

编辑

注意 - 上述答案按照问题所要求的是针对 Apache HttpClient 3.1 的。然而,为了帮助那些寻找最新 Apache 客户端实现的人:

StringEntity requestEntity = new StringEntity(
    JSON_STRING,
    ContentType.APPLICATION_JSON);

HttpPost postMethod = new HttpPost("http://example.com/action");
postMethod.setEntity(requestEntity);

HttpResponse rawResponse = httpclient.execute(postMethod);

如何将 JSON 追加到 geturl? - Mr Lou
1
一直想知道是否可以向POSTMethod添加一个parameter,同时将RequestEntity设置为它?我知道这听起来不合逻辑,但只是好奇。 - asgs
38
对于那些想知道的人,StringRequestEntity已被StringEntity替代。 - Alex
9
随着HttpClient的后续版本发布,PostMethod已被HttpPost所替代。 - Aviro
1
JSON 参考链接已损坏。 - Simon K.
谢谢@SimonK。链接已修复。 - janoside

32

对于Apache HttpClient 4.5或更新版本:

    CloseableHttpClient httpclient = HttpClients.createDefault();
    HttpPost httpPost = new HttpPost("http://targethost/login");
    String JSON_STRING="";
    HttpEntity stringEntity = new StringEntity(JSON_STRING,ContentType.APPLICATION_JSON);
    httpPost.setEntity(stringEntity);
    CloseableHttpResponse response2 = httpclient.execute(httpPost);

注意:

1 为了使代码编译通过,需要导入httpclienthttpcore包。

2 try-catch块已被省略。

参考资料Apache官方指南

Commons HttpClient项目已经停止维护,不再开发。它已被Apache HttpComponents项目中的HttpClient和HttpCore模块所取代。


11

正如janoside的优秀答案中所提到的,您需要构建JSON字符串并将其设置为StringEntity

要构建JSON字符串,您可以使用任何您熟悉的库或方法。Jackson库是一个简单的示例:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;

ObjectMapper mapper = new ObjectMapper();
ObjectNode node = mapper.createObjectNode();
node.put("name", "value"); // repeat as needed
String JSON_STRING = node.toString();
postMethod.setEntity(new StringEntity(JSON_STRING, ContentType.APPLICATION_JSON));

3
我使用JACKSON库将对象转换为JSON并设置请求正文如下。以下是完整示例。
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {

    HttpPost httpPost = new HttpPost("https://jsonplaceholder.typicode.com/posts");

    Post post = new Post("foo", "bar", 1);
    ObjectWriter ow = new ObjectMapper().writer();
    String strJson = ow.writeValueAsString(post);
    System.out.println(strJson);

    StringEntity strEntity = new StringEntity(strJson, ContentType.APPLICATION_JSON);
    httpPost.setEntity(strEntity);
    httpPost.setHeader("Content-type", "application/json");

    try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
        System.out.println(response.getCode() + " " + response.getReasonPhrase());

        HttpEntity entity = response.getEntity();
        String result = EntityUtils.toString(entity);
        System.out.println(result);

        EntityUtils.consume(entity);
    } catch (ParseException e) {
        e.printStackTrace();
    }

} catch (IOException e) {
    System.out.println(e.getMessage());
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接