Single URLConnection to fetch only the first line

2019-06-10 21:03发布

I am trying to write a Java program that should automatically download text from a website if and only if it gets updated. The problem I am running into is using only one HTTPURLConnection to do that because if i don't there will be billions of HTTPURLConnections to the web server since I am using a while(true) loop. Here is my work-in-progress, the getMsg() method receives a url and opens an HTTPURLConnection. Currently I am starting a new connection every time I have to read a line, which is not the most efficient way I am sure. How do I keep reading the same line with the same HTTPURLConnection?

// Starts a new URLConnection to "localhost/currentmsg.dat"
// Receives JSON string from the URLConnection
// Sets up a different variable for each object received from the URL for eg. if delete=1 means that the admin is requesting to delete a message from the screen.

import java.io.*;
import java.net.*;

import org.json.*;
import java.io.*;
import java.util.Scanner;

public class jListenerURL {

// Current arguments retrieved from the URL
private static int msgID = 0;
private static int aptID = 1; // Apartment ID of current device
private static int unitID = 3; // Unit ID of current device
static String message; // Message received from admin
static int delete; // Delete a message?
static int dmsgID; // What message to delete?

public static void jListener() {

    URL url;
    boolean keepGoing = true;
    String msg = "";

    try {
        url = new URL("http://www.lotussmoke.com/msgtest/currentmsg.dat");
        while (keepGoing) {
            msg = getMsg(url);

            JSONObject jObj = null;

            try {
                jObj = new JSONObject(msg);
            }

            catch (JSONException je) {
                System.out.println("JSON Exception for message, try restarting terminal.");
            }

            int current = jObj.getInt("msgID");
            int targetaptID = jObj.getInt("aptID");
            int targetunitID = jObj.getInt("unitID");

            // Keep listening, if the message changes meaning a different msgID then print that message
            if (current!=msgID && targetaptID == aptID && targetunitID == unitID) {

                msgID = jObj.getInt("msgID");
                message = jObj.getString("message");
                delete = jObj.getInt("delete");
                dmsgID = jObj.getInt("dmsgID");

                if (delete==1) {
                    // Delete a message
                    System.out.println("Delete msg ID? " + dmsgID);
                    continue;
                }

                System.out.println("Message ID: " + msgID);
                System.out.println("Apartment ID: " + aptID);
                System.out.println("Unit ID: " + unitID);
                System.out.println("Message: " + message);
            }
        }
    }

    catch (MalformedURLException e) {
        System.err.println();
    }
}

  public static void main(String args[]) throws Exception {
      jListener();
      }

  private static String getMsg(URL url) {
        HttpURLConnection con = null;
        try {
            con = (HttpURLConnection) url.openConnection();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        BufferedReader in = null;
        String msg = "";
        try {
            in = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String received;
            while((received = in.readLine()) != null) {
                //System.out.println(received);
                msg = received;
                }
            in.close();
            }
        catch (IOException e) {
            e.printStackTrace();
            }
        return msg;
  }

}

2条回答
Emotional °昔
2楼-- · 2019-06-10 21:10

Why don't you simply declare your HttpURLConnection object outside of your while loop ? It will then not open a connection at each call inside the loop.

查看更多
Explosion°爆炸
3楼-- · 2019-06-10 21:25

HttpURLConnection cannot be reused, but it can reuse an open connection to the same server internally by setting the header Connection: keep-alive. It doesn't make sense if you connect to different servers, obviously.

One way to efficiently test whether there are changes, is to use If-Modified-Since header or the like If-Unmodified-Since, If-None-Match or If-Match (see HTTP Headers). In this case the web-server decides to deliver a new document if there are changes or just sends the response code 304 Not Modified without a body.

One last thing regarding the use of members (and especially static members): I'd refactor this code and the only item which would be left as static is static void main(). You can see the static members as some kind of global variables. Observing something like 'the connection is returning the same message' might be a effect of inappropriate exception handling and usage of static members.

查看更多
登录 后发表回答