Как я могу получить тело ответа http в виде строки в Java?

155

Я знаю, что раньше был способ получить его с помощью Apache Commons, как описано здесь: http://hc.apache.org/httpclient-legacy/apidocs/org/apache/commons/httpclient/HttpMethod.html и пример здесь:

http://www.kodejava.org/examples/416.html

но я считаю, что это не рекомендуется. Есть ли другой способ сделать http get запрос в Java и получить тело ответа в виде строки, а не потока?

Danish94
источник
1
Поскольку вопрос и все ответы, похоже, касаются библиотек apache, его следует пометить как таковой. Я ничего не вижу без использования сторонних библиотек.
Eis
связанные: stackoverflow.com/questions/21574478
tkruse

Ответы:

104

Каждая библиотека, о которой я могу думать, возвращает поток. Вы можете использовать IOUtils.toString()из Apache Commons IO для чтения InputStreamв Stringвызов метода in. Например:

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, а не локальная система по умолчанию.

WhiteFang34
источник
4
во многих случаях это приведет к повреждению текста, так как метод использует системную кодировку текста по умолчанию, которая зависит от ОС и пользовательских настроек.
Макдауэлл
1
@McDowell: упс, спасибо, я связал javadoc для метода с кодировкой, но я забыл использовать его в примере. На данный момент я добавил UTF-8 в пример, хотя технически должен использовать Content-Encodingзаголовок из ответа, если он доступен.
WhiteFang34
Отличное использование IOUtils. Хороший практический подход.
Spidey
8
На самом деле charset указывается в contentType как «charset = ...», но не в contentEncoding, который содержит что-то вроде «gzip»
Тимур Юсупов
1
эта функция вызывает закрытие входного потока, есть ли способ @ WhiteFang34, я могу напечатать свой ответ и продолжить использовать объект http
amIT
275

Вот два примера из моего рабочего проекта.

  1. Использование EntityUtilsиHttpEntity

    HttpResponse response = httpClient.execute(new HttpGet(URL));
    HttpEntity entity = response.getEntity();
    String responseString = EntityUtils.toString(entity, "UTF-8");
    System.out.println(responseString);
  2. С помощью BasicResponseHandler

    HttpResponse response = httpClient.execute(new HttpGet(URL));
    String responseString = new BasicResponseHandler().handleResponse(response);
    System.out.println(responseString);
spideringweb
источник
10
Единственная проблема, с которой я столкнулся при использовании метода 1, заключается в том, что объект сущности потребляется, когда вы это делаете, response.getEntity()и теперь он доступен как responseString. если вы попытаетесь сделать response.getEntity () снова, он вернется IllegalStateException.
Тирта
Сработало в моем случае - получение тела от ответа CloseableHttpClient.
Ярослав Штрейт
1
Что такое httpClient ?!
Андреас Л.
1
@AndreasL. httpClient имеет тип HttpClient (пакет org.apache.commons.httpclient)
spideringweb
Очень часто можно получить содержимое ответа в виде строки или байтового массива или чего-то еще. Было бы неплохо с API прямо на Entity, чтобы дать вам это. Нужно искать это, чтобы найти этот класс утилит.
Клаус Ибсен
52

Вот пример из другого простого проекта, над которым я работал, используя библиотеку httpclient от Apache:

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, чтобы получить тело ответа в виде строки. очень просто.

moonlightcheese
источник
28

Это относительно просто в конкретном случае, но довольно сложно в общем случае.

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? Я получаю ответ как Джсон, как это читать?
user1735921
10

Ниже приведен простой способ доступа к ответу в виде строки с помощью клиентской библиотеки Apache HTTP.

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);
lkamal
источник
9

Как насчет этого?

org.apache.commons.io.IOUtils.toString(new URL("http://www.someurl.com/"));
Эрик Шленц
источник
9

Ответ Макдауэлла правильный. Однако, если вы попробуете другое предложение в нескольких постах выше.

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

Тогда это даст вам нелегальное состояние StateExtate о том, что контент уже используется.

Акшай
источник
3

Мы можем использовать приведенный ниже код также, чтобы получить ответ HTML в Java

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

    }
}
Subhasish Саху
источник
Это очень хороший ответ, это то, что мне нужно отобразить, ответ после отправки данных на сервер. Отлично сработано.
SlimenTN
0

Вот легкий способ сделать это:

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

Конечно, responseStringсодержит ответ веб-сайта и тип ответа HttpResponse, возвращаемыйHttpClient.execute(request)

Марко Зайц
источник
0

Ниже приведен фрагмент кода, который показывает лучший способ обработки тела ответа в виде строки, будь то действительный ответ или ответ об ошибке для запроса HTTP POST:

BufferedReader reader = null;
OutputStream os = null;
String payload = "";
try {
    URL url1 = new URL("YOUR_URL");
    HttpURLConnection postConnection = (HttpURLConnection) url1.openConnection();
    postConnection.setRequestMethod("POST");
    postConnection.setRequestProperty("Content-Type", "application/json");
    postConnection.setDoOutput(true);
    os = postConnection.getOutputStream();
    os.write(eventContext.getMessage().getPayloadAsString().getBytes());
    os.flush();

    String line;
    try{
        reader = new BufferedReader(new InputStreamReader(postConnection.getInputStream()));
    }
    catch(IOException e){
        if(reader == null)
            reader = new BufferedReader(new InputStreamReader(postConnection.getErrorStream()));
    }
    while ((line = reader.readLine()) != null)
        payload += line.toString();
}       
catch (Exception ex) {
            log.error("Post request Failed with message: " + ex.getMessage(), ex);
} finally {
    try {
        reader.close();
        os.close();
    } catch (IOException e) {
        log.error(e.getMessage(), e);
        return null;
    }
}
Крутик
источник
0

Вы можете использовать стороннюю библиотеку, которая отправляет запрос Http и обрабатывает ответ. Одним из известных продуктов будет Apache commons HTTPClient: HttpClient javadoc , HttpClient Maven . Существует гораздо менее известный, но гораздо более простой HTTPClient (часть написанной мной библиотеки MgntUtils с открытым исходным кодом): MgntUtils HttpClient javadoc , артефакт MgntUtils maven , MgntUtils Github . Используя любую из этих библиотек, вы можете отправлять свой запрос REST и получать ответ независимо от Spring как часть вашей бизнес-логики.

Майкл Гантман
источник
0

Если вы используете Джексона для десериализации тела ответа, одним из очень простых решений является использование request.getResponseBodyAsStream()вместоrequest.getResponseBodyAsString()

Vic Seedoubleyew
источник