开发者

Returning the input stream of the object that the caller already has an instance of

I have a design question.

I'm using the HttpURLConnection class to navigate a website. In order to obtain an HttpURLConnection instance, I have a local getter method. This is responsible for setting all the request properties, including possible cookies. Anyway, throughout the life cycle of this application, I use multiple HttpURLConnection instances. And never is there more than one open connection.

Anyway, I have another local method for sending requests in the form of an HTTP POST. Here is the code:

private final InputStream sendRequest(final HttpURLConnection conn, final String content){
    InputStream in = null;
    DataOutputStream out = null;
    try{
        // Write data out to the stream
        out = new DataOutputStream开发者_如何学Go(conn.getOutputStream()); 
        out.writeBytes(content);
        out.flush();

        // Get the input stream
        in = conn.getInputStream();
    }
    catch(IOException e){
        e.printStackTrace();
    }
    finally{
        try
        {
            if(out != null){
                out.close();
            }
        }
        catch(IOException e){
            e.printStackTrace();
        }
    }

    return in;
}

As you can see, as soon as I'm done writing out the content, I open an input stream on the connection and return it. The reason I do this is if I do not open the input stream on the connection, the application will hang. Therefore, I'm leaving it up to the caller as to whether or not they want to parse the incoming content. Also, the caller needs the connection instance because I leave it up to them to disconnect (that is, close the connection).

So, I guess my question is, is this a poor design? That is, opening the input stream of the connection object that the caller already has an instance of and then returning it?


It's a shame you're not allowed to use Apache HttpClient, but a little OOP may help you untangle your code.

Introduce a ResponseHandler interface for the caller to implement. You might also want to provide some out-of-the-box implementations in public static fields (if thread-safe) or via factory methods for the common cases like "give me a String" (make sure to consult the "charset" part of the response's Content-Encoding header when creating your InputStreamReader) and "give me a byte[]".

Don't supply just the InputStream to the ResponseHandler as you might need access to the response headers for character encoding, etc.

Again, this would really be much much nicer with HttpClient :/

(the following code lacks basic sanity checks for the parameters, please add them)

public interface ResponseHandler<T> {
    T handleResponse(HttpURLConnection conn);
}

public <T> T sendRequest(final HttpURLConnection conn, final String content,
        final ResponseHandler<T> handler)
        throws IOException {
    OutputStream out = null;
    try {
        out = conn.getOutputStream();
        // uses platform encoding, might want to explicitly
        // specify "UTF-8"
        out.write(content.getBytes());
        out.flush();

        return handler.handleResponse(conn);
    } finally {
        // closing out omitted for brevity
    }
}

Edit: If you can somehow managed to get rid of HttpUrlConnection in the calling code, that would be even better. Check out if you can get along with a String for the URL and a Map<String, Object> for the parameters, maybe wrap this in a HttpRequest object.


Well IMHO if your class actually handled all the I/O with the HTTP server and returned to the caller the HTTP response body (if there was any) it would make sense.
Now the sendRequest method is not of much use since the caller has to deal with the HTTP and I/O details anyway

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜