如何将HTTP响应正文作为字符串获取?

192

1
由于问题和所有答案似乎都涉及到Apache库,因此应该将其标记为此类。我没有看到任何不使用第三方库的东西。 - eis
请参考以下链接:https://dev59.com/pGEi5IYBdhLWcg3wJpcl - tkruse
13个回答

334

以下是我工作项目中的两个示例。

  1. Using EntityUtils and HttpEntity

    HttpResponse response = httpClient.execute(new HttpGet(URL));
    HttpEntity entity = response.getEntity();
    String responseString = EntityUtils.toString(entity, "UTF-8");
    System.out.println(responseString);
    
  2. Using BasicResponseHandler

    HttpResponse response = httpClient.execute(new HttpGet(URL));
    String responseString = new BasicResponseHandler().handleResponse(response);
    System.out.println(responseString);
    

14
使用方法1时唯一的问题是,当你执行response.getEntity()时,实体对象被消耗并且现在可以作为 responseString 使用。如果你尝试再次执行 response.getEntity(),它将返回 IllegalStateException - Tirtha
2
httpClient 是什么? - Andreas L.
1
@AndreasL。httpClient 的类型是 HttpClient(org.apache.commons.httpclient 包)。 - spideringweb
1
获取响应内容通常是字符串或字节数组等。如果实体直接提供API以便获取响应内容,那将非常方便。而现在需要查找此实用程序类才能找到它。 - Claus Ibsen
1
我点了赞。请考虑添加完整的“导入”语句。 - granadaCoder
显示剩余5条评论

120

我所知道的每个库都会返回一个流。您可以使用IOUtils.toString(),这是来自Apache Commons IO的一个方法调用,将InputStream读取为String。例如:

URL url = new URL("http://www.example.com/");
URLConnection con = url.openConnection();
InputStream in = con.getInputStream();
String encoding = con.getContentEncoding();
encoding = encoding == null ? "UTF-8" : encoding;
String body = IOUtils.toString(in, encoding);
System.out.println(body);

更新: 我修改了上面的示例以使用响应中提供的内容编码(如果可用)。否则,它将默认为UTF-8作为最佳猜测,而不是使用本地系统默认值。


4
这会在许多情况下破坏文本,因为该方法使用系统默认的文本编码,其根据操作系统和用户设置而异。 - McDowell
1
@McDowell:糟糕,谢谢提醒。我已经链接了带有编码的方法的javadoc,但是我忘记在示例中使用它。我现在将UTF-8添加到示例中,尽管如果可用,技术上应该使用响应中的“Content-Encoding”头。 - WhiteFang34
IOUtils的使用非常棒。很实用的方法。 - Spidey
8
实际上,字符集是在contentType中指定的,例如“charset=...”,而不是在contentEncoding中指定,后者包含类似于“gzip”的内容。 - Timur Yusupov
1
这个函数会导致输入流关闭,@WhiteFang34,有没有办法可以在打印响应后继续使用HTTP实体? - amIT
显示剩余2条评论

53

这是我在使用Apache的httpclient库时从另一个简单项目中提取的示例:

String response = new String();
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("j", request));
HttpEntity requestEntity = new UrlEncodedFormEntity(nameValuePairs);

HttpPost httpPost = new HttpPost(mURI);
httpPost.setEntity(requestEntity);
HttpResponse httpResponse = mHttpClient.execute(httpPost);
HttpEntity responseEntity = httpResponse.getEntity();
if(responseEntity!=null) {
    response = EntityUtils.toString(responseEntity);
}

只需使用 EntityUtils 将响应主体作为字符串获取即可,非常简单。


30

在特定情况下,这相对简单,但在一般情况下相当棘手。

HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet("http://stackoverflow.com/");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
System.out.println(EntityUtils.getContentMimeType(entity));
System.out.println(EntityUtils.getContentCharSet(entity));
答案取决于 Content-Type HTTP响应头信息。该头信息包含有关有效负载的信息,并可能定义了文本数据的编码方式。即使您假设文本类型,您也可能需要检查内容本身以确定正确的字符编码方式。例如,请参阅HTML 4规范了解如何在特定格式中进行此操作的详细信息。 一旦确定了编码方式,可以使用InputStreamReader对数据进行解码。 这个答案取决于服务器是否执行正确的操作 - 如果您想处理响应头不匹配文档或文档声明不匹配所使用的编码的情况,那就是另一回事了。

如何将其转换为HashMap?我得到的响应是Json,如何读取它? - user1735921

11

以下是使用Apache HTTP Client库以字符串形式访问响应的简单方法。

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;

//... 

HttpGet get;
HttpClient httpClient;

// initialize variables above

ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseBody = httpClient.execute(get, responseHandler);

10

麦克道尔的回答是正确的。然而,如果你尝试上面一些帖子中的其他建议。

HttpEntity responseEntity = httpResponse.getEntity();
if(responseEntity!=null) {
   response = EntityUtils.toString(responseEntity);
   S.O.P (response);
}

然后它将会抛出IllegalStateException,说明内容已经被消费。


9
如何只是这个?
org.apache.commons.io.IOUtils.toString(new URL("http://www.someurl.com/"));

3
我们也可以使用下面的代码在Java中获取HTML响应。
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.HttpResponse;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import org.apache.log4j.Logger;

public static void main(String[] args) throws Exception {
    HttpClient client = new DefaultHttpClient();
    //  args[0] :-  http://hostname:8080/abc/xyz/CheckResponse
    HttpGet request1 = new HttpGet(args[0]);
    HttpResponse response1 = client.execute(request1);
    int code = response1.getStatusLine().getStatusCode();

    try (BufferedReader br = new BufferedReader(new InputStreamReader((response1.getEntity().getContent())));) {
        // Read in all of the post results into a String.
        String output = "";
        Boolean keepGoing = true;
        while (keepGoing) {
            String currentLine = br.readLine();

            if (currentLine == null) {
                keepGoing = false;
            } else {
                output += currentLine;
            }
        }

        System.out.println("Response-->" + output);
    } catch (Exception e) {
        System.out.println("Exception" + e);

    }
}

这是一个非常好的响应,这正是我需要显示的,在向服务器提交数据后得到的响应。干得好。 - SlimenTN

1
这是一种轻量级的方法:

这样做:

String responseString = "";
for (int i = 0; i < response.getEntity().getContentLength(); i++) { 
    responseString +=
    Character.toString((char)response.getEntity().getContent().read()); 
}

当然,responseString 包含网站的响应,而 HttpResponse 是由 HttpClient.execute(request) 返回的响应类型。


1
这里是一个纯Java的答案:
import java.net.http.HttpClient;
import java.net.http.HttpResponse;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;

...
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
  .uri(targetUrl)
  .header("Content-Type", "application/json")
  .POST(BodyPublishers.ofString(requestBody))
  .build();
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
String responseString = (String) response.body();

一个更正!使用.uri(URI.create(targetUrl)),而不是.uri(targetUrl) - undefined

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