Java'da hata yanıt gövdesini okuyun


93

Java'da, HTTP sonucu 404 aralığı olduğunda bu kod bir istisna atar:

URL url = new URL("http://stackoverflow.com/asdf404notfound");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.getInputStream(); // throws!

Benim durumumda, içeriğin 404 olduğunu biliyorum, ancak yine de yanıtın gövdesini okumak istiyorum.

(Benim durumumda yanıt kodu 403'tür, ancak yanıtın gövdesi reddedilme nedenini açıklar ve bunu kullanıcıya göstermek istiyorum.)

Yanıt gövdesine nasıl erişebilirim?


Sunucunun bir gövde gönderdiğinden emin misiniz?
Hank Gay

2
@jdigital: HttpURLConnection.getInputStream () tarafından oluşturulan istisna java.io.FileNotFoundException'dur. (Daha iyi googlability için bundan bahsediyor.)
Jonik

Yanıtlar:


172

İşte hata raporu (kapat, düzeltmeyecek, hata değil).

Onların tavsiyeleri şu şekilde kodlamaktır:

HttpURLConnection httpConn = (HttpURLConnection)_urlConnection;
InputStream _is;
if (httpConn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
    _is = httpConn.getInputStream();
} else {
     /* error from server */
    _is = httpConn.getErrorStream();
}

5
Yanıt kodu> = 400 olduğunda hata akışını tam tersi şekilde almak istemez misiniz?
Stephen Swensen

3
Hata durumunda getInputStream () bir GÇ İstisnası atar. İstisnayı yakalamanız ve getErrorStream () kullanarak hata akışından okumalısınız. Bu, httpresponse kodunu kontrol etmekten daha iyi bir yaklaşım gibi görünüyor.
Sudarshan Bhat

3
Sorun şu ki, HttpUrlConnection.getErrorStream () kodunu okursanız, HER ZAMAN boş döndürdüğünü göreceksiniz. (Java 6) :-(
Gangnus

6
"201 CREATED" gibi diğer başarı kodları burada başarısız olmaz mı?
Zengin

4
Hata raporu, kontrol httpConn.getResponseCode() >= 400etmeyi öneriyor (ve bunların çözümünde bir hata var, giriş akışlarını kullanmak için çeviriyorlar)
Dag

14

Benim yaşadığım sorunla aynı: bağlantıdan okumaya çalışırsanız HttpUrlConnectiongeri döner . Durum kodu 400'den yüksek olduğunda bunun yerine kullanmalısınız .FileNotFoundExceptiongetInputStream()
getErrorStream()

Bundan daha fazlası, lütfen dikkatli olun çünkü başarı durum kodu sadece 200 değil, hatta 201, 204 vb. Çoğu zaman başarı durumları olarak kullanılıyor.

İşte onu nasıl yönettiğime dair bir örnek

... connection code code code ...

// Get the response code 
int statusCode = connection.getResponseCode();

InputStream is = null;

if (statusCode >= 200 && statusCode < 400) {
   // Create an InputStream in order to extract the response object
   is = connection.getInputStream();
}
else {
   is = connection.getErrorStream();
}

... callback/response to your handler....

Bu şekilde, hem başarı hem de hata durumlarında gerekli yanıtı alabileceksiniz.

Bu yardımcı olur umarım!


13

.Net'te, bir istisna ON akışa erişim sağlayan WebException Response özelliğine sahipsiniz. Sanırım bu Java için iyi bir yol, ...

private InputStream dispatch(HttpURLConnection http) throws Exception {
    try {
        return http.getInputStream();
    } catch(Exception ex) {
        return http.getErrorStream();
    }
}

Veya kullandığım bir uygulama. (Kodlama veya diğer şeyler için değişiklik gerekebilir. Mevcut ortamda çalışır.)

private String dispatch(HttpURLConnection http) throws Exception {
    try {
        return readStream(http.getInputStream());
    } catch(Exception ex) {
        readAndThrowError(http);
        return null; // <- never gets here, previous statement throws an error
    }
}

private void readAndThrowError(HttpURLConnection http) throws Exception {
    if (http.getContentLengthLong() > 0 && http.getContentType().contains("application/json")) {
        String json = this.readStream(http.getErrorStream());
        Object oson = this.mapper.readValue(json, Object.class);
        json = this.mapper.writer().withDefaultPrettyPrinter().writeValueAsString(oson);
        throw new IllegalStateException(http.getResponseCode() + " " + http.getResponseMessage() + "\n" + json);
    } else {
        throw new IllegalStateException(http.getResponseCode() + " " + http.getResponseMessage());
    }
}

private String readStream(InputStream stream) throws Exception {
    StringBuilder builder = new StringBuilder();
    try (BufferedReader in = new BufferedReader(new InputStreamReader(stream))) {
        String line;
        while ((line = in.readLine()) != null) {
            builder.append(line); // + "\r\n"(no need, json has no line breaks!)
        }
        in.close();
    }
    System.out.println("JSON: " + builder.toString());
    return builder.toString();
}

Kabul edilen cevap bu olmalı ... İnsanların istisnaları ele almak yerine neden hala sihirli sayıları doğruladığını merak ediyorum ...
SparK

Merak ediyorum, bu neden kabul edilen cevap değil. Bana çok yardım etti. Teşekkürler!
Nikhil Jain

2

Bunun soruyu doğrudan yanıtlamadığını biliyorum, ancak Sun tarafından sağlanan HTTP bağlantı kitaplığını kullanmak yerine (bence) çalışmak için çok daha kolay bir API'ye sahip olan Commons HttpClient'e bir göz atmak isteyebilirsiniz .


4
Naçizane size katılmıyorum. Sun'ın API'sı, gerçekten basit şeyleri yaptığınız sürece çok daha kolaydır. Basit şeyler derken, çok fazla hata işlemesi olmayan bir GET'i kastediyorum, ki bu çok sayıda durum için yeterlidir. Elbette HttpClient işlevsellikte çok daha üstündür.
Michael Piefel

2014 itibariyle, en iyisi OkHttp olabilir (aslında bir URL'yi açarken HttpURLConnection örneklerini döndürür). Özellikle Android'de, hem düz HttpURLConnection hem de Apache HttpClient'in bazı kötü sorunlarından kaçınmanıza yardımcı olabilir.
Jonik

2

Önce yanıt kodunu kontrol edin ve ardından HttpURLConnection.getErrorStream()


1
InputStream is = null;
if (httpConn.getResponseCode() !=200) {
    is = httpConn.getErrorStream();
} else {
     /* error from server */
    is = httpConn.getInputStream();
}

4
"201 CREATED" gibi diğer başarı kodları burada başarısız olmaz mı?
Zengin

Evet @Rich, bu yüzden yapmak daha iyi:if (httpConn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
AO_

1

Koşu kodum.

  HttpURLConnection httpConn = (HttpURLConnection) urlConn;    
 if (httpConn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
                        in = new InputStreamReader(urlConn.getInputStream());
                        BufferedReader bufferedReader = new BufferedReader(in);
                        if (bufferedReader != null) {
                            int cp;
                            while ((cp = bufferedReader.read()) != -1) {
                                sb.append((char) cp);
                            }
                            bufferedReader.close();
                        }
                            in.close();

                    } else {
                        /* error from server */
                        in = new InputStreamReader(httpConn.getErrorStream());
                    BufferedReader bufferedReader = new BufferedReader(in);
                    if (bufferedReader != null) {
                        int cp;
                        while ((cp = bufferedReader.read()) != -1) {
                            sb.append((char) cp);
                        }
                        bufferedReader.close();
                    }    
                    in.close();
                    }
                    System.out.println("sb="+sb);

0

Java'da 404 yanıt gövdesi nasıl okunur:

Apache kitaplığını kullanın - https://hc.apache.org/httpcomponents-client-4.5.x/httpclient/apidocs/

veya Java 11 - https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpClient.html

Aşağıda verilen kod parçası Apache'yi kullanır:

import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;

CloseableHttpClient client = HttpClients.createDefault();
CloseableHttpResponse resp = client.execute(new HttpGet(domainName + "/blablablabla.html"));
String response = EntityUtils.toString(resp.getEntity());
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.