Jak uzyskać treść odpowiedzi http jako ciąg w języku Java?


155

Wiem, że kiedyś istniał sposób na uzyskanie tego za pomocą apache commons, jak udokumentowano tutaj: http://hc.apache.org/httpclient-legacy/apidocs/org/apache/commons/httpclient/HttpMethod.html i przykład tutaj:

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

ale uważam, że jest to przestarzałe. Czy istnieje inny sposób, aby żądanie HTTP get w java i uzyskać treść odpowiedzi jako ciąg znaków, a nie strumień?


1
Ponieważ pytanie i wszystkie odpowiedzi wydają się dotyczyć bibliotek Apache, należy to oznaczyć jako takie. Nie widzę niczego bez korzystania z bibliotek innych firm.
— eis

Odpowiedzi:


104

Każda biblioteka, o której przychodzi mi do głowy, zwraca strumień. Możesz użyć IOUtils.toString()z Apache Commons IO do wczytania InputStreamdo Stringwywołania metody w jednym. Na przykład:

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

Aktualizacja: Zmieniłem powyższy przykład, aby użyć kodowania treści z odpowiedzi, jeśli jest dostępne. W przeciwnym razie najlepszym rozwiązaniem będzie domyślny kod UTF-8, zamiast używania domyślnego systemu lokalnego.


4
w wielu przypadkach spowoduje to uszkodzenie tekstu, ponieważ metoda wykorzystuje domyślne systemowe kodowanie tekstu, które różni się w zależności od systemu operacyjnego i ustawień użytkownika.
— McDowell

1
@McDowell: oops dzięki, połączyłem javadoc dla metody z kodowaniem, ale zapomniałem go użyć w przykładzie. Dodałem na razie UTF-8 do przykładu, chociaż technicznie powinienem używać Content-Encodingnagłówka z odpowiedzi, jeśli jest dostępny.
— WhiteFang 34

Świetne wykorzystanie IOUtils. Niezłe, praktyczne podejście.
— Spidey

8
Właściwie charset jest określony w contentType, np. „Charset = ...”, ale nie w contentEncoding, który zawiera coś w rodzaju „gzip”
— Timur Yusupov,

1
ta funkcja powoduje zamknięcie strumienia wejściowego, czy jest sposób, @ WhiteFang34, mogę wydrukować swoją odpowiedź i nadal używać encji http
— amIT

274

Oto dwa przykłady z mojego projektu roboczego.

  1. Korzystanie EntityUtilsiHttpEntity

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

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

10
Jedynym problemem, z jakim miałem do czynienia w przypadku metody 1, jest to, że obiekt encji jest zużywany, gdy to robisz, response.getEntity()i jest teraz dostępny jako responseString. jeśli spróbujesz ponownie wykonać odpowiedź.getEntity (), to zwróci IllegalStateException.
— Tirtha,

Zadziałało w moim przypadku - pobieranie treści z odpowiedzi CloseableHttpClient.
— Jaroslav Štreit

1
Co to jest httpClient ?!
— Andreas L.

1
@AndreasL. httpClient jest typu HttpClient (pakiet org.apache.commons.httpclient)
— spishingweb

Często zdarza się, że zawartość odpowiedzi jest pobierana w postaci ciągu znaków, tablicy bajtów lub czegoś podobnego. Byłoby miło z interfejsem API bezpośrednio w Entity, aby to zapewnić. Konieczność szukania tego, aby znaleźć tę klasę użytkową.
— Claus Ibsen

52

Oto przykład z innego prostego projektu, nad którym pracowałem, używając biblioteki httpclient z 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);
}

po prostu użyj EntityUtils, aby pobrać treść odpowiedzi jako String. bardzo prosty.


28

Jest to stosunkowo proste w konkretnym przypadku, ale dość trudne w przypadku ogólnym.

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

Odpowiedź zależy od Content-Type nagłówka odpowiedzi HTTP .

Ten nagłówek zawiera informacje o ładunku i może definiować kodowanie danych tekstowych. Nawet jeśli przyjmiesz typ tekstu , może być konieczne zbadanie samej treści w celu określenia prawidłowego kodowania znaków. Np. Zobacz specyfikację HTML 4, aby dowiedzieć się, jak to zrobić dla tego konkretnego formatu.

Gdy kodowanie jest znane, do dekodowania danych można użyć InputStreamReader .

Ta odpowiedź zależy od tego, czy serwer postąpi właściwie - jeśli chcesz obsłużyć przypadki, w których nagłówki odpowiedzi nie są zgodne z dokumentem lub deklaracje dokumentu nie pasują do zastosowanego kodowania, to kolejny kocioł ryb.


jak zdobyć to jako HashMap? Otrzymuję odpowiedź jako Json, jak to przeczytać?
— user1735921

10

Poniżej znajduje się prosty sposób uzyskiwania dostępu do odpowiedzi jako ciągu znaków przy użyciu biblioteki klienta HTTP Apache.

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

A co powiesz na to?

org.apache.commons.io.IOUtils.toString(new URL("http://www.someurl.com/"));

9

Odpowiedź McDowella jest poprawna. Jeśli jednak spróbujesz innych sugestii w kilku z powyższych postów.

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

Wtedy otrzymasz wyjątek nielegalnyStateException stwierdzający, że zawartość jest już wykorzystana.


3

Możemy również użyć poniższego kodu, aby uzyskać odpowiedź HTML w 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);

    }
}

To bardzo dobra odpowiedź, to właśnie muszę wyświetlić, odpowiedź po przesłaniu danych na serwer. Dobra robota.
— SlimenTN

0

Oto prosty sposób, aby to zrobić:

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

Oczywiście responseStringz odpowiedzią strony internetowej i typem odpowiedzi HttpResponsezwróconym przezHttpClient.execute(request)


0

Poniżej znajduje się fragment kodu, który pokazuje lepszy sposób obsługi treści odpowiedzi jako ciągu, niezależnie od tego, czy jest to poprawna odpowiedź, czy odpowiedź błędu dla żądania 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

Możesz użyć biblioteki innej firmy, która wysyła żądanie HTTP i obsługuje odpowiedź. Jednym z dobrze znanych produktów byłby Apache commons HTTPClient: HttpClient javadoc , HttpClient Maven artefact . Istnieje znacznie mniej znany, ale znacznie prostszy HTTPClient (część napisanej przeze mnie biblioteki MgntUtils typu open source): MgntUtils HttpClient javadoc , MgntUtils maven artefact , MgntUtils Github . Korzystając z jednej z tych bibliotek, możesz wysłać żądanie REST i otrzymać odpowiedź niezależnie od Springa w ramach logiki biznesowej


0

Jeśli używasz Jacksona do deserializacji treści odpowiedzi, jednym bardzo prostym rozwiązaniem jest użycie request.getResponseBodyAsStream()zamiastrequest.getResponseBodyAsString()

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.