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ń?

Duński94
źródło
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.

WhiteFang34
źródło
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);
spishingweb
źródło
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.

ser księżycowy
źródło
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.

McDowell
źródło
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);
lkamal
źródło
9

A co powiesz na to?

org.apache.commons.io.IOUtils.toString(new URL("http://www.someurl.com/"));
Eric Schlenz
źródło
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.

Akshay
źródło
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);

    }
}
Subhasish Sahu
źródło
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)

Marko Zajc
źródło
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;
    }
}
Krutik
źródło
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

Michael Gantman
źródło
0

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

Vic Seedoubleyew
źródło