Como explicamos na seção 3.2 deste livro, além dos headers e do conteúdo propriamente dito, a resposta a uma requisição HTTP deve conter também a informação do status da resposta, sendo que essa informação é composta por um código numérico mais um string com uma mensagem.
Esse status é utilizado não só para indicar se o processamento da requisição recebida foi bem - sucedida ou não, mas também para indicar algumas outras situações possíveis, como por exemplo que o documento solicitado encontra - se disponível em uma outra URL. Um Servlet pode definir esse status através do método setStatus () da classe HttpServletResponse, sendo que, conforme explicado anteriormente, para preservar a ordem dos elementos da resposta HTTP, a chamada a esse método deve ser feita antes de qualquer definição de headers ou início da geração do conteúdo da resposta.
Assinatura do métod o “setStatus()”
public void setStat u s(int p_stat u sCo d e);
Nos exemplos apresentados anteriormente, como esse status não foi atribuído explicitamente em código, automaticamente o ServletContainer o definiu como sendo 200, ou status OK. Vemos a seguir, por exemplo, a resposta do Servlet HelloWorld :
Exemplo de respo sta HTTP do Servlet “HelloWorld”
HTTP/1.1 200 OK
Server: Apache / 1. 3.26 (Unix)
Last- Modified: Sun, 22 Dec 2002 17:47:59 GMT Content - Type: text / h t m l
Content - Length: 40
<HTML> <BODY>Hello World!< /BODY> < / H TML >
Temos, a seguir, uma tabela com alguns dos códigos de status HTTP existentes e seus respectivos significados:
200 OK Requisição foi processada com sucesso.
302 Moved Temporarily O documento solicitado encontra- se disponível em outra URL. 404 Page Not Found O documento solicitado não foi
encontrado.
500 Internal Server Error Erro no processamento / obtenção do documento requisitado. 503 Service Unavailable O serviço não se encontra
disponível.
Assim, no caso de nosso Servlet de geração de imagem JPEG “ImageServlet”, podemos modificá - lo de forma que ele retorne um código 404 caso o arquivo com a imagem a ser gerada não exista.
Servlet “ImageServlet” com possível uso do código de status HTTP 404
impo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*;
/ / Servlet para geração de saída com image m JPEG; gera código de stat u s 404
/ / caso o arq uivo com a imagem não exista. public class ImageServlet extend s HttpServlet {
public void doGet(HttpServletReq ue s t p_req ue s t, HttpServletRes p o n s e p_res po n s e) {
FileInpu tStrea m l_imageFile = null; try {
/ / Verifican d o se o arquivo com a imagem existe String l_filena me = getServletConfig ().getInitPara m e t e r (“JpegFilena me”);
if(l_filena me != null) {
File l_file = new File(l_filena m e); if(!l_file.exists ()) l_filena me = null; }
if(l_filena me = = null) {
/ / Como o arquivo não existe, retorn a m o s o código 404 p_res p o n s e. se tStat u s(p_res p o n s e.SC_NOT_FOUND);
retur n; }
/ / Definind o o tipo do conteú d o
p_res po n s e.se tCo n te n t Ty p e(“image / j p e g”);
/ / Obten d o o arquivo com a image m JPEG a partir dos parâ m e t r o s
/ / de inicializaçã o do Servlet
l_imageFile = new FileInpu tStrea m(l_filena m e);
/ / Lendo o conte ú d o de um arquivo conten d o uma imagem e
/ / retor na n d o este conte ú d o como respo s t a
ServletOut p u tStrea m l_os = p_res po n s e.getOu t p u tStre a m (); byte [] l_buffer = new byte[1024];
int l_bytes = 0;
while((l_bytes = l_imageFile.read(l_buffer)) != - 1) l_os.write(l_buffer, 0, l_bytes);
/ / Finalizan d o proces s o de geração de saída e fechan d o o arquivo
l_os.flush (); l_imageFile.close ();
} catch( IOExceptio n p_e ) { try {
if(l_imageFile != null) l_imageFile.close (); } catch(Exception p_e2) {}
ServletContext l_context = getServletContext (); l_context.log(“Erro: não foi possível ler imagem de arquivo”);
} } }
Podemos ver, nessa implementação, que o código de status é definido pela constante numérica SC_NOT_FOUND da classe HttpServletResponse.
Utilização de constante SC_NOT_FOUND da class e
“javax.ser vl et.HttpServletResp o n s e”
...
p_res p o n s e. se tStat u s(p_res p o n s e.SC_NOT_FOUND); ...
Para cada código de status HTTP existente, a classe HttpServletResponse define uma constante correspondente, sendo que você deve dar preferência ao uso dessas constantes (em vez do número em si) para aumentar a legibilidade de seu código.
Código de Status Mensagem Constante
200 OK SC_OK
302 Moved Temporarily SC_MOVED_TEMPORARILY
404 Page Not Found SC_NOT_FOUND 500 Internal Server Error
SC_INTERNAL_SERVER_ERROR 503 Service Unavailable
SC_SERVICE_UNAVAILABLE
Vale observar também que, para alguns códigos de status, existem headers auxiliares que contém indicações sobre o que o cliente deve fazer ao receber aquele código de status.
Assim, no caso do código 503 (SC_SERVICE_UNAVAILABLE), você pode definir o valor do header Retry- After para indicar o tempo estimado em segundos até que o serviço volte a ficar ativo.
Outro exemplo é o código de status 302 (SC_MOVED_TEMPORARILY): ao definir esse código de status, você deve definir também o valor do header Location para indicar a URL onde o novo documento pode ser encontrado.
Temos a seguir o exemplo de um Servlet que, dependendo do endereço IP do cliente que envia a requisição, redireciona o acesso para uma nova página contendo uma mensagem de acesso negado.
Servlet “CheckIPAcce s s”
impo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*;
/ / Servlet para verificação do IP do cliente que faz a requisição; / / se o prefixo do IP não for reconhecid o, direciona para uma página / / com uma mens age m de acess o negado.
public class CheckIPAccess extend s HttpServlet {
/ / Prefixo dos IPs per mitid o s (rede local)
private static final String _AllowedIPPrefix = “192.168.0.”;
public void doGet(HttpServletReq ue s t p_req ue s t, HttpServletRes p o n s e p_res po n s e) {
try {
/ / Verifican d o o prefixo do cliente que fez a requisição String l_ip = p_req ue s t.getRe m o t eA d d r ();
if((l_ip != null) && (l_ip.startsWith(_AllowedIPPrefix))) l_ip = null;
if(l_ip = = null) { p_res p o n s e. se tStat u s (p_res po n s e.SC_MOVED_TEMPORARILY);
p_res p o n s e. se tHea d e r(“Location”, “/acces s d e nie d. ht ml”); retur n;
}
/ / Acesso per mitido; imprimin d o página de sucess o PrintWriter l_pw = p_res po n s e.getWriter ();
l_pw.println(“<HTML> <BODY>”);
l_pw.println(“Parabé n s, seu acesso foi permitid o!”); l_pw.println(“< /BODY> < / H TML>”);
l_pw.flus h ();
} catch(IOException p_e) {
ServletContext l_context = getServletContext (); l_context.log(“Erro: “ + p_e.getMessage ()); }
}
Essa situação de redirecionamento do acesso mostra - se tão frequente que um outro método, chamado sendRedirect (), é disponibilizado pela API de Servlets para a obtenção desse mesmo efeito.
Assinaturas do método “sendRedirect()”
public void sendRedirect(String p_location);
Desta forma, poderíamos trocar, no Servlet anterior, o trecho de código:
...
if(l_ip = = null) {
p_resp o n s e. setStat u s(p_res p o n s e.SC_MOVED_TEMPORARILY); p_resp o n s e. setHea d e r(“Location”, “/acces s d e nie d. ht m l”); retur n; } ... Pelo código: ... if(l_ip = = null) {
p_resp o n s e. se n dRe direct(“ / a cces s d e nie d. ht m l”); retur n;
} ...
Veremos a seguir uma variação do ServletContador, apresentado anteriormente neste livro, que utiliza o método sendRedirect() para redirecionar o milésimo acesso para uma página especial:
Variação do ServletContador: redireciona milési m o
acess o
impo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*;
/ / Servlet simples que retor na página HTML com o númer o de requisições
public class ServletCont a d o r exten d s HttpServlet {
/ / Conta d o r das requisições recebida s private int _Contad o r = 0;
public void doGet(Htt pServletReq u e s t p_requ e s t, HttpServletRes p o n s e p_res po n s e)
throws IOException {
/ / Armaz en a n d o valor do contad o r em uma variável local usan d o sincroni za çã o
int l_contad o r = 0; synchr o ni z e d(t his) {
l_contad o r = + + _Conta d o r; }
/ / Se este for o milésim o acesso, redireciona para uma página especial
if(l_conta d o r = = 1000) {
p_res po n s e.se n dRe direct(“ / p r e m i o e s p e cial.ht ml”); retur n;
}
/ / ... caso contrá rio, imprime númer o de requisições recebidas PrintWriter l_pw = p_resp o n s e.getWriter ();
l_pw.println(“< HTML> <BODY>”);
l_pw.println(“Requisiçõe s recebidas: “ + Integer.toString (l_contad o r));
l_pw.flush (); }
}