Làm cách nào tôi có thể nhận phần thân phản hồi http dưới dạng chuỗi trong Java?


155

Tôi biết đã từng có một cách để có được nó với apache commons như được ghi lại ở đây: http://hc.apache.org/httpclient-legacy/apidocs/org/apache/commons/httpclient/HttpMethod.html và một ví dụ ở đây:

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

nhưng tôi tin rằng điều này không được chấp nhận Có cách nào khác để thực hiện một yêu cầu http trong java và nhận phần thân phản hồi dưới dạng chuỗi chứ không phải luồng không?


1
Vì câu hỏi và tất cả các câu trả lời dường như là về các thư viện apache, nên điều này nên được gắn thẻ như vậy. Tôi không thấy bất cứ điều gì mà không sử dụng libs của bên thứ ba.
eis

Câu trả lời:


104

Mỗi thư viện tôi có thể nghĩ về việc trả về một luồng. Bạn có thể sử dụng IOUtils.toString()từ Apache Commons IO để đọc một InputStreamthành một Stringtrong một lời gọi phương thức. Ví dụ:

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

Cập nhật: Tôi đã thay đổi ví dụ trên để sử dụng mã hóa nội dung từ phản hồi nếu có. Mặt khác, nó sẽ mặc định là UTF-8 như một dự đoán tốt nhất, thay vì sử dụng mặc định hệ thống cục bộ.


4
điều này sẽ làm hỏng văn bản trong nhiều trường hợp vì phương thức sử dụng mã hóa văn bản mặc định của hệ thống, thay đổi dựa trên cài đặt của hệ điều hành và người dùng.
McDowell

1
@McDowell: Rất tiếc, tôi đã liên kết javadoc cho phương thức với mã hóa nhưng tôi quên sử dụng nó trong ví dụ. Bây giờ tôi đã thêm UTF-8 vào ví dụ, mặc dù về mặt kỹ thuật nên sử dụng Content-Encodingtiêu đề từ phản hồi nếu có.
WhiteFang34

Công dụng tuyệt vời của IOUtils. Cách tiếp cận pratical đẹp.
Spidey

8
Trên thực tế, bộ ký tự được chỉ định trong contentType như "charset = ...", nhưng không có trong contentEncoding, có chứa một cái gì đó như 'gzip'
Timur Yusupov

1
chức năng này làm cho luồng đầu vào bị đóng, có cách nào @ WhiteFang34 tôi có thể in phản hồi của mình và tiếp tục sử dụng thực thể http
amIT 13/03/2015

274

Đây là hai ví dụ từ dự án làm việc của tôi.

  1. Sử dụng EntityUtilsHttpEntity

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

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

10
Vấn đề duy nhất tôi gặp phải với phương pháp 1 là, đối tượng thực thể được tiêu thụ khi bạn thực hiện response.getEntity()và nó hiện có sẵn dưới dạng responseString. nếu bạn cố gắng thực hiện một phản hồi.getEntity () một lần nữa, nó sẽ trở lại IllegalStateException.
Tirtha

Làm việc trong trường hợp của tôi - nhận cơ thể từ phản ứng ClosizableHttpClient.
Jaroslav treit

1
HttpClient là gì?!
Andreas L.

1
@AndreasL. httpClient thuộc loại httpClient (gói org.apache.commons.httpclient)
spideringweb

Rất phổ biến để có được nội dung phản hồi dưới dạng chuỗi hoặc byte hoặc một cái gì đó. Sẽ rất tuyệt với API trực tiếp trên Thực thể để cung cấp cho bạn điều đó. Phải tìm cái này để tìm lớp tiện dụng này.
Claus Ibsen

52

Đây là một ví dụ từ một dự án đơn giản khác mà tôi đang thực hiện bằng cách sử dụng thư viện httpclient từ 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);
}

chỉ cần sử dụng EntityUtils để lấy phần thân phản hồi dưới dạng Chuỗi. rất đơn giản.


28

Điều này tương đối đơn giản trong trường hợp cụ thể, nhưng khá khó khăn trong trường hợp chung.

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

Câu trả lời phụ thuộc vào Content-Type tiêu đề phản hồi HTTP .

Tiêu đề này chứa thông tin về tải trọng và có thể xác định mã hóa dữ liệu văn bản. Ngay cả khi bạn giả sử các loại văn bản , bạn có thể cần phải tự kiểm tra nội dung để xác định mã hóa ký tự chính xác. Ví dụ, xem thông số kỹ thuật HTML 4 để biết chi tiết về cách thực hiện điều đó cho định dạng cụ thể đó.

Sau khi mã hóa được biết đến, InputStreamReader có thể được sử dụng để giải mã dữ liệu.

Câu trả lời này phụ thuộc vào máy chủ thực hiện đúng - nếu bạn muốn xử lý các trường hợp tiêu đề phản hồi không khớp với tài liệu hoặc khai báo tài liệu không khớp với mã hóa được sử dụng, đó là một ấm cá khác.


Làm thế nào để có được nó như HashMap? Tôi nhận được phản hồi như Json, làm thế nào để đọc nó?
dùng1735921

10

Dưới đây là một cách đơn giản để truy cập phản hồi dưới dạng Chuỗi bằng thư viện 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);

9

Làm thế nào về điều này?

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

9

Câu trả lời của McDowell là đúng. Tuy nhiên nếu bạn thử gợi ý khác trong một vài bài viết ở trên.

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

Sau đó, nó sẽ cung cấp cho bạn bất hợp phápStateException nói rằng nội dung đã được tiêu thụ.


3

Chúng tôi cũng có thể sử dụng mã dưới đây để nhận Phản hồi HTML trong 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);

    }
}

Đây là một phản hồi rất tốt, đây là những gì tôi cần hiển thị, phản hồi sau khi đăng dữ liệu lên máy chủ. Làm tốt.
SlimenTN

0

Đây là một cách nhẹ nhàng để làm như vậy:

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

Tất nhiên responseStringvới phản hồi và phản hồi của trang web thuộc loại HttpResponse, được trả về bởiHttpClient.execute(request)


0

Sau đây là đoạn mã cho thấy cách tốt hơn để xử lý phần thân phản hồi dưới dạng Chuỗi cho dù đó là phản hồi hợp lệ hoặc phản hồi lỗi cho yêu cầu POST HTTP:

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

Bạn có thể sử dụng thư viện bên 3 ngày gửi yêu cầu http và xử lý phản hồi. Một trong những sản phẩm nổi tiếng sẽ là Apache commons HTTPClient: httpClient javadoc , httpClient Maven artifact . Có rất ít HTTPClient được biết đến nhưng đơn giản hơn nhiều (một phần của thư viện MgntUtils mã nguồn được viết bởi tôi): MgntUtils HttpClient javadoc , MgntUtils maven artifact , MgntUtils Github . Sử dụng một trong những thư viện đó, bạn có thể gửi yêu cầu REST của mình và nhận phản hồi độc lập từ Spring như một phần của logic kinh doanh của bạn


0

Nếu bạn đang sử dụng Jackson để khử lưu lượng cơ thể phản hồi, một giải pháp rất đơn giản là sử dụng request.getResponseBodyAsStream()thay vìrequest.getResponseBodyAsString()

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.