Java 句柄HttpURLConnection重定向(NASA开放API)

Java 句柄HttpURLConnection重定向(NASA开放API),java,json,http,Java,Json,Http,我正在编写一个Java应用程序,它与NASA的开放API进行通信。我有一个名为NASAClient的类,它公开了实现此任务所需的接口,但在处理地球图像API时,我面临以下问题 public EarthImageryResponseObject earthImagery(double lon, double lat, String year, String mon, String day, boolean cloud_score) { String cs; if(cloud

我正在编写一个Java应用程序,它与NASA的开放API进行通信。我有一个名为NASAClient的类,它公开了实现此任务所需的接口,但在处理地球图像API时,我面临以下问题

    public EarthImageryResponseObject earthImagery(double lon, double lat, String year, String mon, String day, boolean cloud_score) {
    String cs;
    if(cloud_score) cs = "True";
    else cs = "False";
    String url = "https://api.nasa.gov/planetary/earth/imagery?lon="
            + lon
            + "&lat=" 
            + lat
            + "&date="
            + year+"-"+mon+"-"+day
            + "&cloud_score="
            + cs 
            + "&api_key=" + api_key;
    try {
        String json = (read(getConnection(url)));
        return gson.fromJson(json, EarthImageryResponseObject.class);
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }

}

private String read(HttpURLConnection conn) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
    return readFromBufferedReader(br);
}

private String readFromBufferedReader(BufferedReader br) throws IOException {
    StringBuilder sb = new StringBuilder();
    String line = br.readLine();
    while (line != null) {
        sb.append(line);
        line = br.readLine();
    }
    return sb.toString();
}

private HttpURLConnection getConnection(String url) throws IOException {
    HttpURLConnection connection;
    connection = createConnection(url);
    this.availability = connection.getHeaderField("X-RateLimit-Remaining");
    connection.setConnectTimeout(2000);
    this.last_resp = connection.getResponseCode();
    return connection;
}

private HttpURLConnection createConnection(String url) throws IOException {
    URL UniformResourceLocation = new URL(url);
    return (HttpURLConnection) UniformResourceLocation.openConnection();
}
当我使用一些标准参数调用EarthImages时,我会得到以下url:

https://api.nasa.gov/planetary/earth/imagery?lon=100.75&lat=1.5&date=2017-01-01&cloud_score=False&api_key=[MY_KEY]
如果我使用curl或浏览器导航到此url,我会得到预期的Json序列化对象,但在我的应用程序中调用时,我会得到指向heroku应用程序的重定向链接(带有301响应代码):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><title>Redirecting...</title><h1>Redirecting...</h1><p>You should be redirected automatically to target URL: <a href="http://earth-imagery-api.herokuapp.com/earth/imagery/?lon=100.75&amp;lat=1.5&amp;date=2017-01-01&amp;cloud_score=False">http://earth-imagery-api.herokuapp.com/earth/imagery/?lon=100.75&amp;lat=1.5&amp;date=2017-01-01&amp;cloud_score=False</a>.  If not click the link.

这是因为我需要一个Json对象,但我得到一个字符串(html重定向页面)。

如果您希望代码自动遵循重定向,请设置此标志

connection.setFollowRedirects (true);

我使用HttpURLConnection和SSLSocket解决了这个问题。第一个连接获取重定向链接,该链接不是由另一个httpurlconnection访问的,而是使用SSLSocket访问该链接

public EarthImageryResponseObject earthImagery(double lon, double lat, String year, String mon, String day, boolean cloud_score) {
    String cs;
    if(cloud_score) cs = "True";
    else cs = "False";
    String url = "https://api.nasa.gov/planetary/earth/imagery?lon="
            + lon
            + "&lat=" 
            + lat
            + "&date="
            + year+"-"+mon+"-"+day
            + "&cloud_score="
            + cs 
            + "&api_key=" + api_key;
    try {
        HttpURLConnection conn = getConnection(url);
        String new_url = conn.getHeaderField("Location");
        SSLSocketFactory factory =
                    (SSLSocketFactory)SSLSocketFactory.getDefault();
        SSLSocket socket =
                    (SSLSocket)factory.createSocket("api.nasa.gov", 443);
        socket.startHandshake();
        socket.getOutputStream().write(("GET "+new_url+"\n").getBytes());
        BufferedReader in = new BufferedReader(
                                        new InputStreamReader(
                                        socket.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String inputLine;
        while ((inputLine = in.readLine()) != null)
                    sb.append(inputLine);
        in.close();
        socket.close();
        String json = sb.toString();
        System.out.println(json);
        return gson.fromJson(json, EarthImageryResponseObject.class);
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

这正是我所做的,但它返回一条错误消息,告诉参数是错误的。我认为这是因为一次访问提供的url earth-images-api.herokuapp.com就会丢失关于我的api密钥的信息,这是必须的。我以为它在cookies或其他连接参数中,但不是,即使我从第一个连接获取cookies并将它们添加到第二个连接中,它也不会工作。不过,谢谢你
catch(IOException e){…}
-打印statcktrace,不要默默地吞下异常你是对的,我已经多次更改了代码。我在问题中添加了异常堆栈跟踪。这个问题与重定向无关,问题在于JSON解析
返回gson.fromJson(JSON,EarthImageryResponseObject.class)首先尝试打印json,以检查json字符串正是字符串“仍在尝试,结果相同”(实际上,此标志默认为true)
public EarthImageryResponseObject earthImagery(double lon, double lat, String year, String mon, String day, boolean cloud_score) {
    String cs;
    if(cloud_score) cs = "True";
    else cs = "False";
    String url = "https://api.nasa.gov/planetary/earth/imagery?lon="
            + lon
            + "&lat=" 
            + lat
            + "&date="
            + year+"-"+mon+"-"+day
            + "&cloud_score="
            + cs 
            + "&api_key=" + api_key;
    try {
        HttpURLConnection conn = getConnection(url);
        String new_url = conn.getHeaderField("Location");
        SSLSocketFactory factory =
                    (SSLSocketFactory)SSLSocketFactory.getDefault();
        SSLSocket socket =
                    (SSLSocket)factory.createSocket("api.nasa.gov", 443);
        socket.startHandshake();
        socket.getOutputStream().write(("GET "+new_url+"\n").getBytes());
        BufferedReader in = new BufferedReader(
                                        new InputStreamReader(
                                        socket.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String inputLine;
        while ((inputLine = in.readLine()) != null)
                    sb.append(inputLine);
        in.close();
        socket.close();
        String json = sb.toString();
        System.out.println(json);
        return gson.fromJson(json, EarthImageryResponseObject.class);
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}