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
精彩评论