String message = URLEncoder.encode("my message", "UTF-8");
try {
// instantiate the URL object with the target URL of the resource to
// request
URL url = new URL("http://www.example.com/comment");
// instantiate the HttpURLConnection with the URL object - A new
// connection is opened every time by calling the openConnection
// method of the protocol handler for this URL.
// 1. This is the point where the connection is opened.
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
// set connection output to true
connection.setDoOutput(true);
// instead of a GET, we're going to send using method="POST"
connection.setRequestMethod("POST");
// instantiate OutputStreamWriter using the output stream, returned
// from getOutputStream, that writes to this connection.
// 2. This is the point where you'll know if the connection was
// successfully established. If an I/O error occurs while creating
// the output stream, you'll see an IOException.
OutputStreamWriter writer = new OutputStreamWriter(
connection.getOutputStream());
// write data to the connection. This is data that you are sending
// to the server
// 3. No. Sending the data is conducted here. We established the
// connection with getOutputStream
writer.write("message=" + message);
// Closes this output stream and releases any system resources
// associated with this stream. At this point, we've sent all the
// data. Only the outputStream is closed at this point, not the
// actual connection
writer.close();
// if there is a response code AND that response code is 200 OK, do
// stuff in the first if block
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
// OK
// otherwise, if any other status code is returned, or no status
// code is returned, do stuff in the else block
} else {
// Server returned HTTP error code.
}
} catch (MalformedURLException e) {
// ...
} catch (IOException e) {
// ...
}
As 3 primeiras respostas às suas perguntas são listadas como comentários embutidos, ao lado de cada método, no exemplo HTTP POST acima.
De getOutputStream :
Retorna um fluxo de saída que grava nesta conexão.
Basicamente, acho que você tem uma boa compreensão de como isso funciona, então deixe-me reiterar nos termos dos leigos. getOutputStream
basicamente abre um fluxo de conexão , com a intenção de gravar dados no servidor. No exemplo de código acima, "message" pode ser um comentário que estamos enviando para o servidor que representa um comentário deixado em uma postagem. Quando você vê getOutputStream
, está abrindo o fluxo de conexão para gravação, mas na verdade não grava dados até ligar writer.write("message=" + message);
.
De getInputStream () :
Retorna um fluxo de entrada que lê desta conexão aberta. Uma SocketTimeoutException pode ser lançada ao ler a partir do fluxo de entrada retornado se o tempo limite da leitura expirar antes que os dados estejam disponíveis para leitura.
getInputStream
faz o oposto. Assim getOutputStream
, ele também abre um fluxo de conexão , mas a intenção é ler dados do servidor, não gravar nele. Se a conexão ou a abertura do fluxo falhar, você verá a SocketTimeoutException
.
E o getInputStream? Como só consigo obter a resposta em getInputStream, isso significa que ainda não enviei nenhuma solicitação no getOutputStream, mas simplesmente estabeleci uma conexão?
Lembre-se de que enviar uma solicitação e enviar dados são duas operações diferentes. Quando você chama getOutputStream ou getInputStream url.openConnection()
, envia uma solicitação ao servidor para estabelecer uma conexão. Há um handshake que ocorre onde o servidor retorna uma confirmação de que a conexão foi estabelecida. É nesse momento que você está preparado para enviar ou receber dados. Portanto, você não precisa chamar getOutputStream para estabelecer uma conexão para abrir um fluxo, a menos que seu objetivo para fazer a solicitação seja enviar dados.
Nos termos dos leigos, fazer um getInputStream
pedido é o equivalente a fazer uma ligação para a casa de seu amigo e dizer: "Ei, tudo bem se eu vier e pedir emprestado esse par de vagens?" e seu amigo estabelece o aperto de mão dizendo: "Claro! Venha e pegue". Então, nesse ponto, a conexão é estabelecida, você caminha para a casa de seu amigo, bate na porta, solicita as garras e volta para sua casa.
Usar um exemplo semelhante getOutputStream
envolveria ligar para seu amigo e dizer "Ei, eu tenho o dinheiro que lhe devo, posso enviar para você"? Seu amigo, precisando de dinheiro e doente por dentro, que você o guardou por tanto tempo, diz "Claro, vamos lá, seu bastardo barato". Então você vai até a casa do seu amigo e "paga" o dinheiro para ele. Ele então te expulsa e você volta para sua casa.
Agora, continuando com o exemplo do leigo, vejamos algumas exceções. Se você ligou para o seu amigo e ele não estava em casa, pode ser um erro de 500. Se você ligou e recebeu uma mensagem de número desconectado porque seu amigo está cansado de você pedir dinheiro emprestado o tempo todo, é uma página 404 não encontrada. Se seu telefone estiver morto porque você não pagou a conta, isso pode ser uma IOException. (OBSERVAÇÃO: Esta seção pode não estar 100% correta. Pretende fornecer uma idéia geral do que está acontecendo nos termos dos leigos.)
Pergunta 5:
Sim, você está certo de que o openConnection simplesmente cria um novo objeto de conexão, mas não o estabelece. A conexão é estabelecida quando você chama getInputStream ou getOutputStream.
openConnection
cria um novo objeto de conexão. Desde os javadocs URL.openConnection :
Uma nova conexão é aberta sempre, chamando o método openConnection do manipulador de protocolo para este URL.
A conexão é estabelecida quando você chama openConnection, e o InputStream, OutputStream, ou ambos, são chamados quando você os instancia.
Pergunta 6 :
Para medir a sobrecarga, geralmente envolvo um código de temporização muito simples em todo o bloco de conexão, como:
long start = System.currentTimeMillis();
log.info("Time so far = " + new Long(System.currentTimeMillis() - start) );
// run the above example code here
log.info("Total time to send/receive data = " + new Long(System.currentTimeMillis() - start) );
Tenho certeza de que existem métodos mais avançados para medir o tempo e a sobrecarga de solicitação, mas isso geralmente é suficiente para minhas necessidades.
Para obter informações sobre o fechamento de conexões, sobre as quais você não perguntou, consulte Em Java, quando uma conexão de URL é fechada? .