Utilizando Apache HttpClient
Em muita situações precisamos realizar um requisição Http através de nossos programas, seja para baixar um arquivo ou realizar uma requisição a um serviço REST, onde precisamos de um controle melhor de qual método Http utilizar, headers enviar e receber, códigos de resposta, etc. Para isso o HttpClient facilita bastante.
Para começar vamos importar as bibliotecas, se você utiliza o maven adicione a seguinte dependência:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
Para realizar uma requisição necessitamos criar um objeto HttpClient
para transmitir a requisição para o servidor e obter a resposta.
HttpClient httpclient = HttpClients.createDefault();
Tendo um objeto HttpClient, criamos um objeto de requisição, neste ponto temos um objeto para cada método Http que podemos utilizar, HttpGet
, HttpHead
, HttpPost
, HttpPut
, HttpDelete
, HttpTrace
, HttpOptions
.
Vamos criar então uma requisição GET.
HttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("http://www.botecodigital.info/exemplos/teste_requisicao.php");
try {
HttpResponse response = httpclient.execute(httpget);
...
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
httpget.releaseConnection();;
}
Podemos também construir a url da requisição através de um URIBuilder
, já passando os parâmetros de URL que forem necessários:
URI uri = new URIBuilder()
.setScheme("http")
.setHost("www.botecodigital.info")
.setPath("/exemplos/teste_requisicao.php")
.addParameter("nome", "Rodrigo")
.addParameter("sobrenome", "Aramburu")
.build();
HttpGet httpget = new HttpGet( uri );
Em muitos casos, nossa aplicação precisará passar por um proxy para chegar na internet, para isso devemos criar um objeto HttpHost
com as configurações de protocolo, endereço porta, então configuramos ele como proxy no RequestConfig
, então adicionamos esta configuração no nosso objeto de requisição, neste caso HttpGet
.
HttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet( "http://www.botecodigital.info/exemplos/teste_requisicao.php" );
HttpHost proxy = new HttpHost("97.77.104.22", 3128, "http");
RequestConfig config = RequestConfig.custom().setProxy( proxy ).build();
httpget.setConfig(config);
try {
HttpResponse response = httpclient.execute(httpget);
...
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
httpget.releaseConnection();;
}
Uma vez feita a conexão e devolvido um objeto HttpResponse
podemos pegar as informações de retorno, podemos começar com com os códigos de status, para saber se a requisição foi bem sucedida:
HttpResponse httpResponse = client.execute(method);
StatusLine status = httpResponse.getStatusLine();
if (status.getStatusCode() == HttpStatus.SC_OK) {
// se o código é o esperado
}
O método getStatusLine()
retorna um objeto onde podemos pegar o valor inteiro do código de retorno(getStatusCode()
) que podemos comparar com as constantes da interface HttpStatus
como também o getReasonPhrase
, segue abaixo uma pequena tabela com os código mais utilizados
Código | Reason Phrase | HttpStatus | Descrição |
---|---|---|---|
200 | OK | HttpStatus.SC_OK | Indica que foi tudo bem com a requisição |
201 | Created | HttpStatus.SC_CREATED | Indica que a requisição foi completada e um novo recurso criado |
204 | No Content | HttpStatus.SC_NO_CONTENT | Indica que o servidor completou a requisição e não tem um corpo da entidade para enviar para o cliente |
301 | Moved Permanently | HttpStatus.SC_MOVED_PERMANENTLY | Indica que o recurso requisitado foi movido para uma nova localização e a nova URI necessita ser usada para acessar o recurso |
400 | Bad Request | HttpStatus.SC_BAD_REQUEST | Indica que a requisição esta mal formada e o servidor não está apto para entender a requisição |
401 | Unautthorized | HttpStatus.SC_UNAUTHORIZED | Indica que o cliente precisa de autenticação antes de acessar o recurso. Se a requisição já contem as credenciais do cliente, então um 401 indica credenciais inválidas (p.e. bad password) |
403 | Forbidden | HttpStatus.SC_FORBIDDEN | Indica que o servidor entendeu a requisição mas está recusando cumpri-la. Isto pode ser por causa de o recurso está sendo acessado de um lista negra de endereços IPs ou fora de uma janela de tempo aprovada. |
404 | Not Found | HttpStatus.SC_NOT_FOUND | Indica que o recurso da URI requisitada não existe. |
406 | Not Accepteble | HttpStatus.SC_NOT_ACCEPTABLE | Indica que o servidor é capaz de processar a requisição. No entanto, a resposta gerada pode não ser aceitável pelo cliente. Isto acontece quando o cliente se torna muito exigente. |
500 | Internal Server Error | HttpStatus.SC_INTERNAL_SERVER_ERROR | Indica que teve um erro no servidor enquanto processava a requisição, e que a requisição não pode ser completada. |
503 | Service Unavaliable | HttpStatus.SC_SERVICE_UNAVAILABLE | Indica que a requisição não pode ser completada, o servidor está sobrecarregado ou passando manutenção programada. |
Sendo a requisição bem sucedida ou tendo retornado algum erro, normalmente iremos querer obter o conteúdo retornado e para isso utilizaremos o objeto HttpEntity
que pode ser recuperado pelo método getEntity()
do nosso objeto HttpResponse
. Deste objeto podemos obter um InputStream
com o conteúdo retornado, o tamanho, o ContentType
entre outras informações.
if( response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
HttpEntity entity = response.getEntity();
System.out.println("Tamanho: "+entity.getContentLength() );
System.out.println("Content-type: "+entity.getContentType().getValue() );
InputStream in = entity.getContent();
Scanner scan = new Scanner( in );
while( scan.hasNext() ){
System.out.println( scan.nextLine() );
}
}
Outra maneira para ler o conteúdo se este for apenas texto é utilizando o método toString
da classe EntityUtils
que possui alguns métodos para manipular um HttpEntity
.
HttpEntity entity = response.getEntity();
String content = EntityUtils.toString(entity);
System.out.println( content );
Agora para realizar uma requisição POST, utilizamos a classe HttpPost
e como é normal em uma requisição deste tio devemos enviar os valores como se fosse um formulário submetendo seus campos, para isso é criado uma ArrayList
do tipo NameValuePair
representando cada um dos campos a serem enviados. Após ser criado o ArrayList
criamos um UrlEncodedFormEntity
passando para o construtor o próprio ArrayList
. Após isso atribuímos o objeto UrlEncodedFormEntity
para o objeto HttpPost, agora basta enviar a requisição através do HttpClient
.
HttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost("http://www.botecodigital.info/exemplos/teste_requisicao.php");
try {
ArrayList<NameValuePair> valores = new ArrayList<NameValuePair>();
valores.add(new BasicNameValuePair("nome", "rodrigo"));
valores.add(new BasicNameValuePair("sobrenome", "aramburu"));
httppost.setEntity( new UrlEncodedFormEntity( valores ) );
HttpResponse response = httpclient.execute( httppost );
HttpEntity entity = response.getEntity();
String content = EntityUtils.toString(entity);
System.out.println( content );
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
httppost.releaseConnection();;
}
Uma informação bastante relevante em uma requisição Http são os seus headers, sendo necessários muitas vezes enviá-los e recebê-los. Para enviar headers na requisição feita ao servidor podemos utilizar o método setHeader
do objeto HttpGet
, passando como primeiro parâmetro a chave( nome do header) e como segundo o seu valor. Para pegar o header enviado pelo servidor utilizamos o método getAllHeaders()
que retorna um array de objetos Header
que possuem ons métodos getName
para pegar o nome do header e getValue
para pegar
HttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("http://www.botecodigital.info/exemplos/teste_requisicao.php");
try {
httpget.setHeader("accept", "text/json;text/xml");
httpget.setHeader("Authorization", "Basic QWxhZGRpbjpPcGVuU2VzYW1l");
HttpResponse response = httpclient.execute( httpget );
HttpEntity entity = response.getEntity();
String content = EntityUtils.toString(entity);
System.out.println( content );
System.out.println("Headers Recebidos");
Header[] headers = response.getAllHeaders();
for(Header h : headers){
System.out.println(h.getName()+" = "+h.getValue() );
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
httpget.releaseConnection();;
}
Outro componente importante de uma requisição são os cookies, eles são utilizadas para transportar estado entre as requisições e são utilizadas para trabalhar com sessões. Para enviar um cookie devemos criar um objeto BasicCookieStore
para os contê-los, logo após iremos criar um BasicClientCookie
que representa o cookie que será enviado. No construtor do BasicClientCookie
passamos a chave(nome do cookie) e o seu valor. Depois configuramos ao qual domínio ele pertence, e também qual seu path. Agora adicionamos o cookie no cookieStore
.
O próximo passo é adicionar o cookieStore em nosso HttpCliente
, o método mais fácil é na sua criação através de seu builder, então ao invés de utilizarmos um HttpClients.createDefault()
para criá-lo iremos utilizar um HttpClients.custom()
e chamar o setDefaultCookieStore
para adicionar o cookieStore
, em seguida chamando o método build
para efetivamente criar o o objeto HttpClient
.
CookieStore cookieStore = new BasicCookieStore();
BasicClientCookie cookie = new BasicClientCookie("JSESSIONID", "5A693144F9323FDAB06861B906B49084");
cookie.setDomain("www.botecodigital.info");
cookie.setPath("/");
cookieStore.addCookie(cookie);
HttpClient httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
HttpGet httpget = new HttpGet("http://www.botecodigital.info/exemplos/teste_requisicao.php");
try {
HttpResponse response = httpclient.execute( httpget );
HttpEntity entity = response.getEntity();
String content = EntityUtils.toString(entity);
System.out.println( content );
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
httpget.releaseConnection();;
}
Bom, este é o básico e acho que já serve para a maioria das nossas necessidades.