Як я можу отримати тіло відповіді http як рядок на Java?


155

Я знаю, що раніше це було способом отримати це за допомогою апаш-спільних записів, як це зафіксовано тут: http://hc.apache.org/httpclient-legacy/apidocs/org/apache/commons/httpclient/HttpMethod.html та прикладом тут:

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

але я вважаю, що це застаріло. Чи є інший спосіб зробити http отримання запиту в java та отримати тіло відповіді як рядок, а не потік?


1
Оскільки питання і всі відповіді, мабуть, стосуються бібліотек apache, це слід позначати як таке. Я нічого не бачу, не використовуючи губ 3rdparty.
ей

Відповіді:


104

Кожна бібліотека, яку я можу придумати, повертає потік. Ви можете використовувати 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
це пошкодить текст у багатьох випадках, оскільки метод використовує системне кодування тексту за замовчуванням, яке змінюється залежно від налаштувань ОС та користувача.
МакДауелл

1
@McDowell: ой, дякую, я зв’язав javadoc за метод з кодуванням, але я забув використовувати його у прикладі. Я зараз додав UTF-8 до прикладу, хоча технічно слід використовувати Content-Encodingзаголовок відповіді, якщо такий є.
WhiteFang34

Велике використання IOUtils. Хороший практичний підхід.
Spidey

8
Насправді charset вказаний у contentType типу "charset = ...", але не у contentEncoding, який містить щось на кшталт "gzip"
Тимур Юсупов

1
ця функція спричиняє закриття вхідного потоку, чи є спосіб @ WhiteFang34 я можу надрукувати свою відповідь і продовжувати використовувати об'єкт http
amIT

274

Ось два приклади з мого робочого проекту.

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

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, щоб схопити тіло відповіді як рядка. дуже просто.


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? Я отримую відповідь як Json, як це читати?
користувач1735921

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


9

Відповідь МакДауелла є правильною. Однак якщо ви спробуйте іншу пропозицію в декількох публікаціях вище.

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

Тоді він надасть вам незаконнийStateException із зазначенням, що вміст уже споживається.


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

    }
}

Це дуже хороша відповідь, це те, що мені потрібно показати, відповідь після публікації даних на сервері. Молодці.
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

Ви можете використовувати 3-d бібліотеку партії, яка надсилає Http-запит та обробляє відповідь. Одним з відомих продуктів був би Apache, який представляє HTTPClient: HttpClient javadoc , артефакт HttpClient Maven . Є набагато менш відомий, але набагато простіший HTTPClient (частина бібліотеки MgntUtils з відкритим кодом, написана мною): MgntUtils HttpClient javadoc , MgntUtils maven артефакт , MgntUtils Github . Використовуючи будь-яку з цих бібліотек, ви можете відправити свій REST-запит і отримати відповідь незалежно від Spring як частина вашої бізнес-логіки


0

Якщо ви використовуєте Джексона для десеріалізації тіла реагування, request.getResponseBodyAsStream()замість цього потрібно використовувати одне дуже просте рішенняrequest.getResponseBodyAsString()

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.