Artigo Java Magazine 18 - Programando Servlets
Artigo publicado na Java Magazine edição 18.
Clique aqui para ler este artigo em PDF
Programando Servlets
Parte 1: Fundamentos e Técnicas Básicas
No primeiro artigo da série, apresentaremos os conceitos básicos como protocolo HTTP, API, ciclo de vida, cookies e sessões
A API de Servlets, criada em 1996 com o intuito de gerar dinamicamente código HTML, é um componente fundamental da plataforma J2EE. Com o passar do tempo, porém, outras tecnologias, como JSP e linguagens de template, mostraram-se mais apropriadas para a geração de HTML, e os servlets passaram a ser usados para tarefas de processamento de dados, como download e upload de arquivos e filtragem de requisições. Mas isso não significa que os servlets perderam importância. Muito pelo contrário. A API de Servlets é o alicerce de muitas outras tecnologias, como JSP, JSF, Portlets e Struts. A Tabela 1 lista as tecnologias J2EE relacionadas à camada web (web-tier) e suas especificações (JSRs).
Nesse artigo, vamos apresentar os conceitos básicos de servlets e uma introdução ao funcionamento de uma aplicação web. Este artigo complementa e se relaciona com a outra matéria de capa de edição, sobre JSP 2.0 e Tomcat 5, e em alguns pontos mostrará conceitos similares, mas sob a perspectiva unificadora dos servlets.
O protocolo HTTP
Antes de nos aprofundarmos na API de Servlets em si, é importante entender como funciona o protocolo HTTP, responsável pela comunicação, em nível de aplicação, entre o navegador e a aplicação web. Quando você digita uma URL no navegador, digamos, http://localhost:8080/jm18/alo?nomePessoa=Felipe, é feita uma requisição (request) ao servidor HTTP. Aqui localhost representa o seu próprio computador. O servidor então processa a requisição e envia uma resposta (response) ao navegador. A Figura 1 ilustra o processo.
Junto com a requisição, o navegador passa algumas informações para o servidor. No exemplo ilustrado, está sendo explicitamente passado um parâmetro nomePessoa, cujo valor é felipe. Implicitamente, são passadas informações sobre o navegador através de variáveis de header e, opcionalmente, cookies (veremos mais sobre estes adiante).
Como a requisição é enviada no formato texto, podemos verificar o que é enviado usando o nosso "pseudo servidor web" mostrado na Listagem 1. Acessando esse servidor, por exemplo, a partir de um navegador Mozilla rodando no Linux (e passando a URL http://localhost:8080/alo?nomePessoa=Felipe), temos:
> java jm18.pentefino.ServidorHTTP 8080
### Criando servidor na porta 8080
### Conexao estabelecida
### Recebendo dados:
GET /aloServlet?nomePessoa=Felipe HTTP/1.1
Host: localhost:2424
User-Agent: Mozilla/5.0
(X11; U; Linux i686; en-US; rv:1.6) Gecko/20040116
Accept: text/xml,application/xml,application/xhtml+xml,
text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,
image/gif;q=0.2,*/*;q=0.1
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
### Dados ok
### Enviando dados:
### Dados ok
Nesta requisição, a primeira linha indica ao servidor o recurso que está sendo acessado (/aloServlet?nomePessoa=Felipe), além da versão do protocolo e o método usado – HTTP/1.1 e GET. As linhas seguintes são variáveis de cabeçalho (header), seguidas por uma linha em branco, que separa o cabeçalho do corpo da requisição.
Nota: O corpo de uma requisição HTTP só é usado em requisições do tipo POST; é no corpo que os bytes de um arquivo são transmitidos em um upload, por exemplo.
O servidor envia uma resposta, também em formato texto. A estrutura é similar à requisição: a primeira linha indica o código da resposta (veja a Tabela 2), sendo seguida por variáveis de cabeçalho, uma linha em branco e o corpo. O corpo contém os dados da resposta, como código HTML ou bytes de um arquivo, no caso de um download.
Usando o cliente da Listagem 2 em vez do navegador web, o comando a ser executado e a resposta para o exemplo anterior seria:
> java jm18.pentefino.ServidorHTTP 8080
### Criando servidor na porta 8080
### Conexao estabelecida
### Recebendo dados:
GET /aloServlet?nomePessoa=Felipe HTTP/1.1
### Dados ok
### Enviando dados:
### Dados ok
E no cliente:
> java jm18.pentefino.ClienteHTTP http://localhost:8080/aloServlet?nomePessoa=Felipe
### Tentando conexao com servidor localhost na porta 8080
### Conexao estabelecida. Enviando query /aloServlet?nomePessoa=Felipe
### Recebendo resposta
### Dados enviados pelo servidor:
Requisicao tratada com sucesso!
### Dados ok
Note
que o cliente da Listagem 2 não envia nenhuma variável de cabeçalho.
Por isso não seria um cliente válido para servidores reais, como mostra
o seguinte exemplo:
> java jm18.pentefino.ClienteHTTP http://javamagazine.com.br:80
### Tentando conexao com servidor javamagazine.com.br na porta 80
### Conexao estabelecida. Enviando query ?null
### Recebendo resposta
### Dados enviados pelo servidor:
HTTP/1.1 400 Bad Request
Date: Tue, 07 Sep 2004 18:17:08 GMT
Server: Apache
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=iso-8859-1
127
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML><HEAD>
<TITLE>400 Bad Request</TITLE>
</HEAD><BODY>
<H1>Bad Request</H1>
Your browser sent a request that this server could not understand.<P>
client sent HTTP/1.1 request without hostname (see RFC2616 section 14.23): /<P>
</BODY></HTML>
0
### Dados ok
Para finalizar, é importante lembrar que o protocolo HTTP é sem-estado (stateless). Ou seja, não existe uma conexão permanente entre o servidor e o navegador, e portanto o servidor não sabe se uma conexão seguinte está relacionada com a anterior. Para contornar essa restrição, foram criados os cookies. Cookies são informações armazenadas no computador do usuário que são opcionalmente enviadas em cada requisição pelo navegador, processados pelo servidor e recebidos de volta na resposta (veja a Figura 2).
Servlets e aplicações web
Na Figura 1, vimos que o navegador faz uma requisição que será processada de alguma maneira pelo servidor. A forma como esse processamento é feito depende do servidor e da URL. Por exemplo, um servidor web Apache pode ser configurado para servir páginas estáticas em HTML e páginas dinâmicas em PHP, e para repassar as requisições de JSPs a um servidor Tomcat rodando na mesma máquina. Como se vê, a API de Servlets é uma dentre várias tecnologias de processamento de requisições HTTP para geração de páginas dinâmicas.
Os servlets não ficam sozinhos. Eles são gerenciados por um Container Web, responsável pela criação e destruição dos servlets e pela delegação de requisições HTTP para os servlets existentes, além da criação de um pool de threads para o processamento das requisições (cada requisição é atendida em uma thread própria). A Figura 3 ilustra o relacionamento entre o servidor HTTP, o container web e os servlets.
Outro conceito importante é o de Aplicação Web (Web Application, ou abreviadamente webapp). Todo servlet está contido numa aplicação web, que pode conter ainda outros recursos como páginas JSP e arquivos estáticos (páginas HTML, imagens JPG e GIF etc.), além de um diretório especial chamado WEB-INF (cujo conteúdo não é exposto por uma URL e só pode ser acessado pelos servlets) – veja a Figura 4. Para ser instalada, uma aplicação web é tipicamente condensada em um arquivo WAR (Web ARchive). Esse formato condensado é mais comumente usado na aplicação final em produção, e o formato “expandido”, durante o desenvolvimento.
Um container pode gerenciar várias aplicações web, cada uma em seu Contexto. Um contexto é identificado por um "diretório" na URL. Por exemplo, a URL http://localhost:8080/jm18/alo refere-se ao recurso alo da aplicação web cujo contexto mapeia para o "diretório" jm18.
Um servlet também é responsável pelo tratamento de URLs da aplicação web. No exemplo anterior, poderíamos criar um servlet chamado " [...] continue lendo...
Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Artigo