J2EEBrasil - O site da comunidade J2EE no Brasil - www.j2eebrasil.com.br Servlets Otávio Henrique Vieira Sanchez [email protected] Quando você digita um endereço no seu navegador para entrar em alguma página de internet, basicamente solicita um determinado arquivo localizado em um computador em especial no local que você digita a URL. O computador onde o arquivo está armazenado, é chamado de web server (servidor web). Essa principal função do computador é para servir a qualquer um na Internet que solicite arquivos que ele se hospeda. Já que você nunca sabe quando um usuário visitará e usará o seu aplicativo web, o seu servidor web precisa estar ativo e em execução o tempo todo. No momento em que você digita um endereço na internet acontecem as seguintes ações: O O O O browser(cliente) estabelece uma conexão TCP/IP com o servidor. browser envia uma solicitação ao servidor (request). servidor envia uma resposta ao cliente (response). servidor fecha a conexão HTTP é o protocolo que permite que os servidores web e browsers trocar dados pela web. É um protocolo de solicitação e resposta. No início as páginas eram praticamente todas estáticas, ou seja somente arquivos HTML que não eram gerados dinamicamente e nem tinham conexões com banco de dados. Logo após começaram a criar as CGIs que eram geradas dinâmicamentes, podiam trabalhar com arquivos, interagir com banco de dados e etc. Mais tarde vieram linguagens em script tais como php e asp. O que são Servlets ? Servlet é um programa que estende a funcionalidade de um web server, gerando conteúdo dinâmico e interagindo com os clientes, utilizando o modelo request/response. Os servlets não são restritos ao modelo HTTP de request/response, onde na realidade são pequenas aplicações de servidores, mas o modelo HTTP é o modelo mais comumente utilizado. Arquitetura de um Servlet HTTP SERVLET Esta classe estende a classe javax.servlet.GenericServlet. Possui basicamente seis métodos que são chamados automaticamente de acordo com os métodos HTTP que são requisitados. Por exemplo se a solicitação do seu browser for feita pelo método GET, no seu servlet irá ser chamado o método doGet(). Basicamente você irá trabalhar com dois métodos: o GET e o POST. Os seis métodos são: doPost(); doPut(); doGet(); doDelete(); doOption(); doTrave(); 1 of 6 J2EEBrasil - O site da comunidade J2EE no Brasil - www.j2eebrasil.com.br HTTP SERVLET REQUEST As solicitações HTTP que o browser envia pelo cliente ao servidor com informações importantes, tais como cookies e referenciador são tratadas a partir do objeto HttpServletRequest passado a um método doGet ou doPost. Aqui você consegue recuperar cabeçalhos, recuperar parâmetros passados ao servidor etc. getHeaderNames(); - pega todos os nomes dos cabeçalhos . getHeader (); - pega todos os valores do cabeçalho . getQueryString(); - pega a Query String completa. getParameterNames(); - pega todos os names dos parâmetros passados. getParameterValues(); - recuperação de parâmetros de múltiplos valores. getParameter(); - recuperação de parâmetros de acordo com o nome passado. HTTP SERVLET RESPONSE A interface HttpServletResponse oferece diversos métodos específicos de protocolo. Sempre você precisará especificar a saída para seu browser, através dos métodos setContentType e getWriter. Exemplo: response.setContentType("text/html"); PrintWriter out = response.getWriter(); Além disso você pode enviar cookies ao browser, também tem métodos para manipular os URLs enviados ao browser, gerenciamento de sessões, etc. Container de Servlets Tomcat Atualmente estão disponíveis vários containers servlets. A versão mais atual dele atualmente é a 5.0 que implementa as especificações Servlet 2.3 e JSP 1.2. O Tomcat também é um servidor de web. Isso significa que você pode usar Tomcat para solicitar serviços HTTP em servlets, e também arquivos HTML, arquivos de imagens e assim por diante. Normalmente as pessoas usam o Tomcat para requisições de Servlets e JSP, e outro servidor mais robusto em paralelo, como o Apache para as outras requisições HTTP. Ciclo de vida Em qualquer Servlet que você for escrever você precisa implementar direta ou indiretamente a interface javax.servlet.Servlet. O ciclo de vida de um servlet é determinado por três de seus métodos: init, service e destroy. Os servidores carregam e executam o servlet, que por sua vez aceita nenhuma ou mais requisições de clientes e retorna dados para o mesmo. Os servidores podem também remover os servlets. Carregar: Quando um servidor carrega um servlet, ele roda o método init() do mesmo. Como a maioria dos servlets roda em servidores multi-thread, não há concorrência durante a inicialização dos mesmos. Isto ocorre pois o servidor chamará somente uma vez o método init() quando carregar o servlet e não o chamará de novo a não ser que o servlet seja recarregado. O servidor não pode recarregar um servlet até que o mesmo seja removido pelo método destroy(). Executar: Após o servidor carregar e incializar o servlet, o mesmo está apto a receber requisições do cliente. Cada requisição 2 of 6 J2EEBrasil - O site da comunidade J2EE no Brasil - www.j2eebrasil.com.br do cliente possui uma chamada ao método run() em sua própria thread do servlet. O método recebe a requisição do cliente e envia a resposta. Os servlets podem executar vários métodos de serviços de uma vez. Remover: Os servlets permanecem em execução até que sejam removidos. Quando um servidor remove um servlet, ele executa o método destroy() do mesmo. O método é executado somente uma vez. O servidor não executará o método destroy() novamente até que o servlet seja recarregado e reinicializado. Contexto do Servlet Em programação de servlet, o contexto de servlet é o ambiente onde o servlet executa. O container de servlet cria um objeto ServletContext que você pode usar para acessar informações a respeito do ambiente do servlet. Um servlet também pode ligar um atributo de objeto ao contexto pelo nome. Qualquer objeto ligado a um contexto está disponível a qualquer servlet que faça parte do mesmo a plicativo web. Criar o primeiro Servlet Depois de ter instalado e configurado o Tomcat, você pode colocá-lo no serviço. Basicamente é preciso seguir seis etapas para ir de escrever o seu servlet e executá-lo. 1. 2. 3. 4. 5. 6. Crie uma estrutura de diretório para seu aplicativo em Tomcat. Escreva o código fonte de servlet. É preciso importar o pacote javax.servlet e javax.servlet.http em seu arquivo-fonte. Compile seu código-fonte. Crie uma distribuição descritiva. Execute o Tomcat. Chame seu servlet a partir de um web browser. Analisando cada passo: Primeiro passo: Crie um diretório chamado teste sob o diretório webapps que fica dentro de Tomcat (onde foi instalado). É importante o nome do diretório, pois ele irá aparecer na URL do browser. Crie também um diretório chamado WEB-INF dentro do teste, e dentro de WEB-INF crie o diretório classes. Segundo passo: Nessa etapa você prepara seu código-fonte, depois salva dentro do diretório classes do contexto. import java.io.*; import javax.servlet.*; import javax.servlet.http.*; 3 of 6 J2EEBrasil - O site da comunidade J2EE no Brasil - www.j2eebrasil.com.br public class Teste extends HttpServlet { private PrintWriter out; public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ response.setContentType("text/html"); out = response.getWriter(); out.println("<HTML>"); out.println( "<HEAD>"); out.println( "<TITLE> Teste</TITLE>"); out.println( "</HEAD>"); out.println( "<BODY>"); out.println( "Primeiro Servlet."); out.println( "</BODY>"); out.println("</HTML>"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ doGet(request, response); } } Terceiro passo: Compile o código-fonte. Quarto passo: Crie a distribuição descritiva, que nada mais é um documento XML. Esse documento será gravado com o nome de web.xml dentro do diretório WEB-INF do seu contexto. <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <servlet> <servlet-name>Teste</servlet-name> <servlet-class>Teste</servlet-class> </servlet> <servlet-mapping> <servlet-name>Teste</servlet-name> <url-pattern>/Teste</url-pattern> </servlet-mapping> </web-app> Quinto passo: Se o Tomcat ainda não estiver sendo executado, será preciso iniciá-lo, caso contrário pule para o sexto passo. Sexto passo: Agora você deve chamar seu Servlet a partir de um browser da web. Por padrão o Tomcat executa na porta 8080 no diretório virtual teste. Então digite o seguinte endereço no browser: http://localhost:8080/teste/Teste Gerenciamento de sessão Como dito anteriormente o protocolo de rede que os servidores web e browsers cliente usam para se comunicar é o HTTP, sendo a linguagem web. As conexões HTTP são iniciadas por um browser cliente que envia uma solicitação HTTP. Então, o servidor web responde com uma resposta HTTP, num comportamento simplificado. Portanto se um cliente solicitar um outro recurso do servidor, ele precisará abrir uma outra conexão HTTP para o servidor. Vamos imaginar que um usuário está comprando em uma loja on-line. Como sempre, o processo se inicia com o usuário buscando por um produto. Se o produto for encontrado, então o usuário entrará com a quantidade daquele produto no formulário do carrinho de compras e submeterá ao servidor. Mas, o usuário ainda não está saindo, ele ainda quer comprar algo mais. Portanto, ele busca novamente no catálogo pelo segundo produto. Mas, agora, o primeiro pedido de produto está perdido, porque a conexão anterior foi fechada e o servidor web não se lembra de nada sobre a conexão anterior. Outro exemplo seria para autenticar usuários em um sistema intranet. Podemos imaginar que teríamos várias cadastros, relatórios e consultas onde a pessoa que tem acesso a isso irá precisar "logar" no sistema para poder visualizar. Se fosse uma única página tudo bem, mas agora se temos muitas páginas seria necessário validar todas elas, pedindo usuário e senha. Isso é quase impossível e não convém. Para esses dois exemplos citados acima é que entra o gerenciamento de sessão, que possuem basicamente quatro técnicas, e são elas: 1. Reescrita de URL 2. Campos ocultos 3. Cookies 4 of 6 J2EEBrasil - O site da comunidade J2EE no Brasil - www.j2eebrasil.com.br 4. Objetos de sessão Dessas 4 técnicas de gerenciamento de sessão, o objeto Session, representado pela interface javax.servlet.http.HttpSession, é o mais fácil de usar e o mais poderoso. Por padrão quando um objeto session é criado ele envia ao browser do cliente e ao servidor um identificador de sessão, que fica ativo até que se destrua a sessão ou expire o tempo. Principais commandos do objeto Session: Criar sessão: HttpSession session = request.getSession( true ); Recuperar sessão: request.getSession(); Setar atributos: session.setAttribute("usuario","valor"); Recuperar atributos: session.getAttribute("usuario"); Destruir Sessão: session.invalidate(); Filtragem de Servlet O filtro de um servlet é um recurso novo na especificação Servlet 2.3, onde na realidade ele nada mais é do que uma classe Java normal que tem acesso aos objetos HttpServletResponse e HttpServletRequest antes de eles serem passados ao Servlet. Eles podem estar em cadeia, pode trabalhar com múltiplos servlets, e podem ser filtros de entrada ou de saída. Exemplo de um filtro que registra endereços IP de usuário ao arquivo de registro. import import import import import import import import java.io.*; javax.servlet.Filter; javax.servlet.FilterChain; javax.servlet.FilterConfig; javax.servlet.ServletContext; javax.servlet.ServletException; javax.servlet.ServletRequest; javax.servlet.ServletResponse; public class FiltroLog implements Filter { private FilterConfig filterConfig = null ; public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { ServletContext servletContext = filterConfig.getServletContext(); ServletContext.log( req.getRemoteHost() ) chain.doFilter(request, response); } public void init(FilterConfig filterConfig) throws ServletException{ this.filterConfig = filterConfig; } 5 of 6 J2EEBrasil - O site da comunidade J2EE no Brasil - www.j2eebrasil.com.br public void destroy(){ this.filterConfig = null; } } A distribuição descritiva do exemplo é dada abaixo: <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <filter> <filter-name>FiltroLog </filter-name> <filter-class>FiltroLog </filter-class> </filter> <filter-mapping> <filter-name>FiltroLog</filter-name> <servlet-name>Teste</servlet-name> </filter-mapping> <servlet> <servlet-name>Teste</servlet-name> <servlet-class>Teste</servlet-class> </servlet> <servlet-mapping> <servlet-name>Teste</servlet-name> <url-pattern>/Teste</url-pattern> </servlet-mapping> </web-app> 6 of 6