Como posso obter um corpo de resposta http como uma string em Java?

155

Eu sei que costumava haver uma maneira de obtê-lo com o apache commons, conforme documentado aqui: http://hc.apache.org/httpclient-legacy/apidocs/org/apache/commons/httpclient/HttpMethod.html e um exemplo aqui:

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

mas acredito que isso foi preterido. Existe alguma outra maneira de fazer uma solicitação http get em java e obter o corpo da resposta como uma string e não um fluxo?

Dinamarquês94
fonte
1
Como a pergunta e todas as respostas parecem ser sobre bibliotecas apache, isso deve ser marcado como tal. Não vejo nada sem usar as bibliotecas de terceiros.
eis
relacionado: stackoverflow.com/questions/21574478
tkruse 13/03

Respostas:

104

Toda biblioteca em que consigo pensar retorna um fluxo. Você pode usar IOUtils.toString()a partir de Apache Commons IO para ler um InputStreampara um Stringem uma chamada de método. Por exemplo:

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

Atualização: alterei o exemplo acima para usar a codificação de conteúdo da resposta, se disponível. Caso contrário, o padrão será o UTF-8 como melhor sugestão, em vez de usar o padrão do sistema local.

WhiteFang34
fonte
4
isso corromperá o texto em muitos casos, pois o método usa a codificação de texto padrão do sistema, que varia de acordo com o sistema operacional e as configurações do usuário.
McDowell
1
@ McDowell: oops obrigado, vinculei o javadoc para o método com a codificação, mas esqueci de usá-lo no exemplo. Adicionei UTF-8 ao exemplo por enquanto, embora tecnicamente deva usar o Content-Encodingcabeçalho da resposta, se disponível.
precisa saber é o seguinte
Grande uso de IOUtils. Boa abordagem prática.
Spidey
8
Na verdade charset é especificado no contentType como "charset = ...", mas não em ContentEncoding, que contém algo como 'gzip'
Timur Yusupov
1
esta função faz com que o fluxo de entrada a ser fechado, há uma maneira @ WhiteFang34 Posso imprimir minha resposta e continuar a usar a entidade http
Amit
274

Aqui estão dois exemplos do meu projeto de trabalho.

  1. Usando EntityUtilseHttpEntity

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

    HttpResponse response = httpClient.execute(new HttpGet(URL));
    String responseString = new BasicResponseHandler().handleResponse(response);
    System.out.println(responseString);
teia de aranha
fonte
10
O único problema que enfrentei com o método 1 é que o objeto de entidade é consumido quando você faz response.getEntity()e agora está disponível como responseString. se você tentar fazer um response.getEntity () novamente, ele retornará IllegalStateException.
Tirtha
Funcionou no meu caso - obtendo o corpo da resposta CloseableHttpClient.
Jaroslav Štreit 17/10
1
O que é httpClient ?!
Andreas L.
1
@AndreasL. httpclient é do tipo HttpClient (pacote org.apache.commons.httpclient)
spideringweb
É tão comum obter o conteúdo da resposta como string ou matriz de bytes ou algo assim. Seria legal com uma API diretamente na Entidade dar a você isso. Ter que procurar por isso para encontrar esta classe util.
Claus Ibsen
52

Aqui está um exemplo de outro projeto simples no qual eu estava trabalhando usando a biblioteca httpclient do 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);
}

basta usar EntityUtils para pegar o corpo da resposta como uma String. muito simples.

moonlightcheese
fonte
28

Isso é relativamente simples no caso específico, mas bastante complicado no caso geral.

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

A resposta depende do Content-Type cabeçalho da resposta HTTP .

Este cabeçalho contém informações sobre a carga útil e pode definir a codificação de dados textuais. Mesmo que você assuma tipos de texto , pode ser necessário inspecionar o próprio conteúdo para determinar a codificação correta dos caracteres. Por exemplo, consulte a especificação do HTML 4 para obter detalhes sobre como fazer isso para esse formato específico.

Depois que a codificação é conhecida, um InputStreamReader pode ser usado para decodificar os dados.

Essa resposta depende do servidor fazer a coisa certa - se você deseja lidar com casos em que os cabeçalhos de resposta não coincidem com o documento ou as declarações do documento não coincidem com a codificação usada, isso é outra chaleira de peixe.

McDowell
fonte
como obtê-lo como HashMap? Recebo resposta como Json, como ler isso?
usar o seguinte comando
10

Abaixo está uma maneira simples de acessar a resposta como uma String usando a biblioteca do 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);
lkamal
fonte
9

Que tal exatamente isso?

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

A resposta de McDowell está correta. No entanto, se você tentar outra sugestão em algumas das postagens acima.

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

Em seguida, ele fornecerá ilegalStateException informando que o conteúdo já foi consumido.

Akshay
fonte
3

Também podemos usar o código abaixo para obter a resposta HTML em 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
fonte
Essa é uma resposta muito boa, é isso que eu preciso exibir, a resposta depois de postar dados no servidor. Bem feito.
precisa saber é o seguinte
0

Aqui está uma maneira leve de fazer isso:

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

Como é claro, responseStringcontendo a resposta do site e o tipo de resposta HttpResponse, retornado porHttpClient.execute(request)

Marko Zajc
fonte
0

A seguir, está o trecho de código que mostra a melhor maneira de manipular o corpo da resposta como uma String, seja uma resposta válida ou uma resposta de erro para a solicitação 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
fonte
0

Você pode usar uma biblioteca de terceiros que envia a solicitação HTTP e lida com a resposta. Um dos produtos conhecidos seria o Apache commons HTTPClient: HttpClient javadoc , artefato HttpClient Maven . Há HTTPClient muito menos conhecido, mas muito mais simples (parte de uma biblioteca MgntUtils de código aberto escrita por mim): MgntUtils javadoc HttpClient HttpClient , MgntUtils , MgntUtils Github . Usando uma dessas bibliotecas, você pode enviar sua solicitação REST e receber resposta independentemente do Spring como parte de sua lógica de negócios

Michael Gantman
fonte
0

Se você estiver usando Jackson para desserializar o corpo da resposta, uma solução muito simples é usar em request.getResponseBodyAsStream()vez derequest.getResponseBodyAsString()

Vic Seedoubleyew
fonte