livro j2ee

381
 Pro gr amação Web com Jsp, Servlets e J2EE André Temple CPqD Telecom & IT Solutions. Rodrigo Fe rnandes de Mello  Departamento de Ciências da Computação Instituto de Ciências Matemáticas e de Computação. Universidade de São Paulo Danival Taffarel Calegari  CPqD Telecom & IT Sol utions. Maurício Schiezar o  CPqD Telecom & IT Solutions. ISBN: 85- 905209- 1- 9 Copyright © 2004 André Templ e, Rodrigo Fernandes de Mello, Danival Taffarel Calegari e Maurício Schiezaro. Este trabalho está licenciado sobre uma licença Creative Commons Atribuição-UsoNãoComercial-Compartilhamento pela mesma licença. Para ver uma cópia desta licença visite http://creativecommons.org/licenses/by-nc-sa/2.0/br/ ou envie uma carta para Creative Commons, 559 Nathan Abbott Way, St andford, California 94305, USA. 1

Upload: lucasdoval1

Post on 11-Jul-2015

348 views

Category:

Documents


0 download

TRANSCRIPT

Programao Web com Jsp, Servlets e J2EEAndr TempleCPqD Telecom & IT Solutions.

Rodrigo Fernandes de MelloDepartamento de Cincias da Computao Instituto de Cincias Matemticas e de Computao. Universidade de So Paulo

Danival Taffarel CalegariCPqD Telecom & IT Solutions.

Maurcio SchiezaroCPqD Telecom & IT Solutions.

ISBN: 85- 905209 - 1- 9Copyright 2004 Andr Temple, Rodrigo Fernandes de Mello, Danival Taffarel Calegari e Maurcio Schiezaro. Este trabalho est licenciado sobre uma licena Creative Commons Atribuio- UsoNoComercial- Compartilhamento pela mesma licena. Para ver uma cpia desta licena visite http://creativecommons.org/licenses/by- nc- sa/2.0/br/ ou envie uma carta para Creative Commons, 559 Nathan Abbott Way, Standford, California 94305, USA.

1

Prefcio

Este livro dividido em duas partes. A primeira parte trata do desenvolvimento de aplicaes Web utilizando, principalmente, Servlets. A segunda parte aborda o paradigma de desenvolvimento de aplicaes distribudas utilizando a tecnologia Enterprise Java Beans. A primeira parte do livro aborda de forma consistente e didtica o contedo relacionado a Servlets. Nesta abordagem definido um histrico do desenvolvimento de aplicaes Web, passando por CGIs e linguagens de script. Alm dos tpicos relacionados a Servlets so abordados tpicos relacionados tais como Java Server Pages (JSP), Java Beans, Taglibs, modelo MVC, instalao de configurao de um Web Container para desenvolvimento, alm de tpicos avanados tais como controle de pooling de conexes com banco de dados. A segunda parte do livro aborda o paradigma de desenvolvimento de aplicaes distribudas, destacando a evoluo das tcnicas de desenvolvimento desde a programao estrutura at o atual uso de sistemas distribudos. A tecnologia utilizada para prover distribuio a plataforma J2EE (Java 2 Enterprise Edition). So detalhados os componentes e possibilidades que esta plataforma oferecem ao desenvolvedor. O livro foi dividido em partes para oferecer um contedo mais abrangente e completar. A primeira parte trata da construo de interfaces e controles para interao com os clientes de uma aplicao Web. A segunda parte aprofunda nos aspectos de distribuio de um sistema, permitindo que este execute em diversos computadores, dividindo sua carga e, conseqentemente, aumentando seu desempenho.

2

SumrioParte I................................................................................................7 Desenvolvendo Interfaces e Controles de Interao com o Usurio .............................................................................................7 Captulo 1.........................................................................................8 Introduo ........................................................................................8 1.1 Colocar Nome do tpico?........................................................8 1.1 Comparando Servlets com CGIs..........................................10 1.2 O que so Servlets?...............................................................11 1.3 O que so pginas JSP? .........................................................12 Captulo 2......................................................................................14 Instalao e Configurao ...........................................................14 2.1 Colocar Nome do tpico?.....................................................14 2.1 Instalao e configurao no Apache Tomcat ...................15 2.2 Instalao e Configurao de uma Aplicao Web...........16 Captulo 3......................................................................................28 Servlets caractersticas bsicas...............................................28 3.1 Colocar Nome do tpico?.....................................................28 3.2 O protocolo HTTP..................................................................29 3.3 Hierarquia de um Servlet ......................................................31 3.4 Ciclo de vida de um Servlet ..................................................32 3.5 Inicializao ...........................................................................33 3.6 A classe ServletContext ....................................................39 3.7 Finalizao .............................................................................44 3.8 Atendimento de Requisies ..............................................46 3.9 Concorrncia no atendimento de requisies...................48 3.10 Retornando informaes sobre o Servlet .......................52 Captulo 4......................................................................................54 Servlets Gerao da sada........................................................54 4.1 Gerao de sada HTML simples ........................................54 4.2 Headers da resposta HTTP...................................................57 4.2 Gerao de outros tipos de sadas......................................62 4.3 Gerando contedo XML.........................................................65 4.4 Status HTTP............................................................................66

3

4.5 Cdigo de Status de erro ......................................................73 4.6 Buffering da resposta .........................................................74 Captulo 5......................................................................................77 Servlets Captura de parmetros da requisio .....................77 5.1 Informaes sobre o servidor .............................................77 5.2 Informaes sobre a requisio\: ......................................79 5.3 Formulrios HTML e parmetros da requisio\: ............85 5.4 Captura de parmetros da requisio\: ............................87 5.5 Headers da requisio HTTP................................................90 5.6 Upload de arquivos ................................................................92 5.7 Atributos da requisio .........................................................95 Captulo 6......................................................................................96 Servlets Cookies e Sesses.......................................................96 6.1 Colocar Nome do tpico?......................................................96 6.1 Campos escondidos de formulrios HTML........................97 6.2 Informaes adicionais de caminho ...................................99 6.3 Cookies.................................................................................101 6.4 Gerenciamento de sesses................................................106 Captulo 7....................................................................................122 Pginas JSP ..................................................................................122 7.1 Formatao do contedo da resposta com Servlets......122 7.2 Formatao do contedo da resposta com pginas JSP ....... 125 7.3 Funcionamento interno ......................................................127 7.4 Ciclo de vida.........................................................................129 7.5 Elementos dinmicos ..........................................................130 7.6 Diretivas................................................................................130 7.7 Expresses............................................................................133 7.8 Scriptlets ...............................................................................134 7.9 Objetos implcitos ...............................................................136 7.10 Declaraes........................................................................139 7.11 Comentrios .......................................................................140 7.12 JavaBeans............................................................................141 7.13 Bibliotecas de Tags (Tag Libraries)................................145 Captulo 8....................................................................................152 Modelo MVC................................................................................152 8.1 Colocar Nome do tpico?...................................................152 8.1 Arquitetura bsica...............................................................153 8.2 Forward de requisies......................................................154 8.3 Atributos de requisies....................................................156

4

8.4 Juntando as partes ..............................................................158 Captulo 9....................................................................................162 Tpicos adicionais ....................................................................162 9.1 Arquivos WAR.......................................................................162 9.2 Autenticao HTTP..............................................................163 9.3 Pools de conexes a base de dados.................................166 Parte II..........................................................................................178 Desenvolvimento de Aplicaes Distribudas Utilizando EJB ..... 178 Captulo 10 ..................................................................................179 Novas Tcnicas de Desenvolvimento ......................................179 10.1 Desenvolvimento de Clssico de Aplicaes................179 10.2 Sistemas Distribudos .......................................................182 10.3 Primeiros Ensaios de Arquiteturas para Sistemas Distribudos no Mercado ...........................................................192 10.4 Mercado Atual para Sistemas Distribudos ...................195 Captulo 11 ..................................................................................197 J2EE e Enterprise JavaBeans......................................................197 11.1 O que J2EE? .....................................................................197 11.2 Viso da plataforma ..........................................................198 11.3 Instalando o J2SDKEE........................................................200 11.4 O que so Enterprise JavaBeans?....................................201 11.5 Para que servem e por que utiliz- los?.........................201 11.6 Componentes EJB ..............................................................203 11.7 Classes e interfaces..........................................................204 11.8 Acesso local e/ou remoto ................................................205 11.9 EJBObject e EJBHome.........................................................207 11.10 Como construir, executar e acessar os componentes ..... 209 Captulo 12 ..................................................................................212 Session Beans..............................................................................212 12.1 O que so Session Beans?................................................212 12.2 Quando usar um Session Bean?......................................216 12.3 Session Bean Stateless.....................................................216 12.4 Ciclo de vida - Session Bean Stateless..........................218 Session Bean Stateful .................................................................219 Ciclo de vida - Session Bean Stateful ......................................222 Captulo 13 ..................................................................................223 Entity Beans.................................................................................223 13.1 O que so Entity Beans?...................................................223

5

13.2 Quando usar um Entity Bean?.........................................224 13.3 Entity Bean Bean- Managed- Persistence........................224 13.4 Ciclo de vida Entity Bean BMP......................................228 13.5 Entity Bean Container- Managed- Persistence...............229 13.6 Ciclo de vida Entity Bean CMP......................................233 13.7 Relacionamento EJB Entity Bean CMP.............................234 13.8 EJB-QL.................................................................................240 Captulo 14 ..................................................................................244 Message- Driven Beans..............................................................244 14.1 O que so Message- Driven Beans?................................244 14.2 Quando usar um Message- Driven Bean?.......................246 14.3 Ciclo de vida - Message- Driven Bean............................247 14.4 O que e para que serve o JMS? .....................................248 Captulo 15 ..................................................................................256 Transaes e Segurana............................................................256 15.1 Transaes.........................................................................257 Segurana....................................................................................265 Captulo 16 ..................................................................................281 Descobrindo Enterprise JavaBeans .........................................281 16.1 Qual servidor J2EE utilizar?..............................................281 16.2 Instalando, configurando e executando um Servidor J2EE ......................................................................................................282 16.3 Criando um Session Bean Stateless................................283 16.4 Criando um Session Bean Stateful ..................................287 16. 5 Criando um Entity Bean BMP..........................................292 16.6 Criando um Entity Bean CMP...........................................302 16.7 Criando um Message- Driven Bean.................................306 16.8 Empacotando a aplicao................................................309 16.9 Instalando a aplicao no servidor J2EE ........................314 Apndice A..................................................................................316 Deployment Descriptor .............................................................316 A.1 O que um deployment descriptor?................................316 A.2 Elementos do deployment descriptor ejb- jar.xml .........317 Apndice B...................................................................................329 API Enterprise JavaBeans...........................................................329 B.1 Interfaces..............................................................................329 B.2 Excees................................................................................336 Apndice C..................................................................................339 Aplicao J2EE Exemplo ..........................................................339

6

Parte I

Desen v ol v e n d o Interfaces e Controles de Interao com o Usurio

7

Captulo 1 Introduo

Introduzimos, nesse captulo, a tecnologia de Servlets e Pginas JSP e mostramos algumas caractersticas que tornam essas tecnologias bastante atraentes para o desenvolvimento de aplicaes na Web.

1.1 Aplicaes na WebSe um dia a Internet era composta, principalmente, de pginas estticas com contedo institucional, hoje ela oferece uma infinidade de aplicaes com contedo dinmico e personalizado. Diversas tecnologias possibilitaram essa revoluo: seja para construir um simples site com contedo dinmico ou para construir um complexo sistema de Business- ToBusiness, necessria a utilizao de ferramentas que possibilitem consultas a bancos de dados, integrao com sistemas corporativos, entre outras inmeras funcionalidades. Dentre as diversas tecnologias disponveis atualmente para o desenvolvimento dessa classe de aplicaes, destaca- se a de Servlets e a de pginas JSP (Java Server Pages). A utilizao de Servlets e de pginas JSP oferece diversas vantagens em relao ao uso de outras tecnologias (como PHP, ASP e CGI). As principais vantagens so herdadas da prpria linguagem Java:

8

Portabilidade: a aplicao desenvolvida pode ser implantada em diversas plataformas, como por exemplo Windows, Unix e Macintosh, sem que seja necessrio modificar ou mesmo reconstruir a aplicao. Facilidade de programao: a programao orientada a objetos, simplificando o desenvolvimento de sistemas complexos. Alm disso, a linguagem oferece algumas facilidades, como por exemplo o gerenciamento automtico de memria (estruturas alocadas so automaticamente liberadas, sem que o desenvolvedor precise se preocupar em gerenciar esse processo). Flexibilidade: o Java j se encontra bastante difundido, contando com uma enorme comunidade de desenvolvedores, ampla documentao e diversas bibliotecas e cdigos prontos, dos quais o desenvolvedor pode usufruir. Alm dessas vantagens, a arquitetura de Servlets e pginas JSP possibilita alguns benefcios adicionais: Escalabilidade: na maior parte dos servidores de aplicaes modernos, possvel distribuir a carga de processamento de aplicaes desenvolvidas em diversos servidores, sendo que servidores podem ser adicionados ou removidos de maneira a acompanhar o aumento ou decrscimo dessa carga de processamento.

Figura 1.1 Exemplo de arquitetura distribuda com Servlets e Pginas JSP.

9

Eficincia: os Servlets carregados por um servidor persistem em sua memria at que ele seja finalizado. Assim, ao contrrio de outras tecnologias, no so iniciados novos processos para atender cada requisio recebida; por outro lado, uma mesma estrutura alocada em memria pode ser utilizada no atendimento das diversas requisies que chegam a esse mesmo Servlet. Recompilao automtica: pginas JSP modificadas podem ser automaticamente recompiladas, de maneira que passem a incorporar imediatamente as alteraes sem que seja necessrio interromper o funcionamento da aplicao como um todo.

1.1 Comparando Servlets com CGIsO CGI, ou Common Gateway Interface, surgiu como uma das primeiras tecnologias disponveis para a gerao de contedo dinmico em servidores Web: o desenvolvedor implementa uma aplicao que deve ser executada a cada requisio recebida, sendo que o servidor Web passa para essa aplicao, atravs de variveis de ambiente e entrada padro, os parmetros recebidos, e retorna a sada da aplicao como resposta da requisio.

Figura 1.2 Funcionamento de um CGI. Podemos usar o CGI para analisar algumas das vantagens em se utilizar Servlets. Em primeiro lugar, h um grande ganho em performance na utilizao de Servlets: ao invs de iniciar um novo processo a cada requisio recebida, um Servlet fica

10

carregado em memria e atende as requisies recebidas atravs de novos threads. Alm disso, um Servlet pode tirar proveito dessa persistncia para manter tambm em memria recursos que demandem grande processamento para serem inicializados. Um exemplo tpico, para esse caso, a manuteno de conexes com banco de dados: ao invs de inicializar uma nova conexo com o banco de dados a cada requisio recebida, um Servlet pode inicializar diversas conexes ao ser carregado, e simplesmente alocar uma conexo desse pool a cada requisio recebida (e retornar a conexo ao pool aps o atendimento da requisio). Alm destes ganhos de performance, a utilizao de um Servlet possibilita uma maneira mais padronizada e portvel de se distribuir / implantar sua aplicao. Conforme explicado mais adiante no Captulo 2 Instalao e Configurao , o ambiente onde sua aplicao ser implantada no precisa ser igual ao ambiente onde foi feito o desenvolvimento: seus Servlets podem ser instalados em qualquer ambiente onde haja um Servidor de Aplicaes que implemente a especificao de Servlets. Por fim, diversas Servlets simples, estaremos apresentando ao longo deste livro as caractersticas e funcionalidades da tecnologia de que tornam o seu desenvolvimento muito mais e o resultado, muito mais eficiente e robusto.

1.2 O que so Servlets?Servlets so classes Java, desenvolvidas de acordo com uma estrutura bem definida, e que, quando instaladas junto a um Servidor que implemente um Servlet Container (um servidor que permita a execuo de Servlets, muitas vezes chamado de Servidor de Aplicaes Java), podem tratar requisies recebidas de clientes. Um cenrio tpico de funcionamento de uma aplicao desenvolvida com Servlets o seguinte:

11

Figura 1.3 Exemplo de funcionamento de uma aplicao com Servlets. Ao receber uma requisio, um Servlet pode capturar parmetros desta requisio, efetuar qualquer processamento inerente a uma classe Java, e devolver uma pgina HTML por exemplo.

Exemplo de Servletimpo rt java.io.*; impo rt javax.servlet.htt p.*; / / Servlet simples que retor na pgina HTML com o endereo IP / / do cliente que est fazendo o acesso public class RemoteIPServlet extends HttpServlet { public void doGet( HttpServletReque st p_reque st, HttpServletResp o n s e p_respo ns e) throws IOException { PrintWriter l_pw = p_respon se.getWriter (); l_pw.println( ); l_pw.println(O seu endereo IP \ + p_req ue st.getRe mo teAd d r () + \); l_pw.println(< /BODY> < / H TML >); l_pw.flush (); } }

1.3 O que so pginas JSP?

12

As pginas JSP, ou Java Server Pages, foram criadas para contornar algumas das limitaes no desenvolvimento com Servlets: se em um Servlet a formatao da pgina HTML resultante do processamento de uma requisio se mistura com a lgica da aplicao em si, dificultando a alterao dessa formatao, em uma pgina JSP essa formatao se encontra separada da programao, podendo ser modificada sem afetar o restante da aplicao. Assim, um JSP consiste de uma pgina HTML com alguns elementos especiais, que conferem o carter dinmico da pgina. Esses elementos podem tanto realizar um processamento por si, como podem recuperar o resultado do processamento realizado em um Servlet, por exemplo, e apresentar esse contedo dinmico junto a pgina JSP. Existe tambm um recurso adicional bastante interessante na utilizao de pginas JSP: a recompilao automtica, que permite que alteraes feitas no cdigo da pgina sejam automaticamente visveis em sua apresentao. Assim, no necessrio interromper o funcionamento da aplicao para incorporar uma modificao de layout, por exemplo.

Exemplo de Pgina JSP O seu endereo IP < /BODY> < /H TML>

13

Captulo 2 Instalao e Configurao

Nesse captulo so apresentados os tpicos referentes a instalao e configurao de um ambiente bsico para a implantao e execuo de aplicaes Web com Servlets e pginas JSP.

2.1 Pr- requisitos:O primeiro passo para desenvolver aplicaes Web com Servlets e pginas JSP a configurao de um ambiente bsico para a implantao e execuo dessas aplicaes. Esse ambiente bsico pressupe a instalao de dois componentes principais: o Java 2 Standard Development Kit (J2SDK), utilizado para compilar aplicaes Java, e um Servlet Container, que ir executar os Servlets desenvolvidos. Alguns sistemas operacionais j possuem um J2SDK instalado por default. Caso esse ainda no se encontre instalado, pode- se obt- lo no site oficial do Java (http: / / java.sun.com ). Neste site possvel selecionar entre as verses de J2SDK para as diversas plataformas de mercado tais como Windows, Linux, Solaris e outros. O outro componente necessrio para o desenvolvimento de Servlets e JSP um servidor que implemente um Servlet Container. Esse servidor ser responsvel por prover um framework bsico para as diversas aplicaes desenvolvidas, inicializando- as, distribuindo as

14

requisies entre elas e tratando processamento de cada aplicao.

os

resultados

do

Apesar de existirem diversos servidores disponveis no mercado, para efeito dos exemplos apresentados neste livro, utilizaremos o Apache Tomcat, disponvel no site http: / / jakarta.apache.org . Esse servidor de aplicaes atende s especificaes mencionadas anteriormente e pode ser utilizado sem nenhum custo para o desenvolvedor. Um ltimo componente normalmente utilizado para o desenvolvimento de Servlets e pginas JSP um ambiente grfico de desenvolvimento (IDE). Porm, a escolha e configurao de um ambiente desse tipo foge do escopo deste livro, sendo deixado para o leitor a tarefa de escolher a ferramenta que melhor atenda s suas necessidades.

2.1 Instalao e configurao no Apache TomcatNo site do Apache Tomcat so disponibilizadas verses do software com instaladores para os diversos sistemas operacionais. Normalmente esse processo de instalao simples, e, uma vez finalizado, tem - se um servidor de aplicaes pronto para produo. De qualquer forma, o site disponibiliza toda a documentao necessria para resolver problemas encontrados e esclarecer dvidas com relao ao processo de instalao e configurao do servidor. Para entender um pouco mais a fundo o funcionamento do Tomcat, deve- se examinar os diretrios criados durante o processo de instalao. Os principais diretrios criados so:Diretrio Descriobin Executveis, incluindo os aplicativos para iniciar e para encerrar a execuo do servidor

15

conf

Arquivos de configurao do Tomcat. O arquivo server.xml, em particular, define uma srie de parmetros para a execuo do servidor, como por exemplo, a porta onde o servidor ir receber requisies (essa porta , por default, 8080), devendo ser examinado com cuidado e modificado conforme as necessidades. Arquivos de log do servidor. Alm de gerar arquivos de log contendo entradas para cada requisio recebida, como qualquer servidor Web, o Tomcat tambm pode gerar arquivos de log com tudo o que as aplicaes desenvolvidas enviam para as sadas padro do sistema: tipicamente, o que impresso atravs do System.out acrescido no arquivo stdout.log, e tudo o que impresso atravs do System.err acrescido no arquivo stderr.log. Diretrio temporrio do Tomcat. Esse diretrio utilizado, por exemplo, para realizar a recompilao automtica de pginas JSP (esse processo explicado mais adiante no captulo Pginas JSP). Nesse diretrio so instaladas as diversas desenvolvidas por voc ou por terceiros. aplicaes web

logs

work

webapps

Figura 2.1 Subdiretrios na instalao do Apache Tomcat.

2.2 Instalao e Configurao de uma Aplicao WebConforme vimos anteriormente, existe um diretrio no Apache Tomcat chamado webapps onde devem ser instaladas as diversas aplicaes desenvolvidas por voc ou por terceiros. Para que possamos mostrar como so feitas essas instalaes, precisamos antes definir o que uma

16

aplicao Web: a partir de agora, estaremos chamando de uma aplicao Web um conjunto de Servlets, pginas JSP, classes Java, bibliotecas, cones, pginas HTML e outros elementos, que podem ser empacotados juntos e que provem as funcionalidades previstas pela aplicao. Essa definio est contida, na verdade, na prpria especificao de Servlets Java, no sendo especfica, portanto, utilizao do Servidor de Aplicaes Apache Tomcat. Isso significa que as aplicaes desenvolvidas por voc podem ser instaladas em qualquer servidor que implemente a especificao de Servlets (como o IBM Websphere e o Bea Weblogic): com isso, segue- se o princpio da linguagem Java de desenvolver o cdigo uma s vez e implant- lo em mltiplas plataformas.Aplicao Web: Aplicao composta de Servlets + Pginas JSP + Bibliotecas e classes Java + imagens + pginas HTML e outros componentes estticos que podem ser empacotados juntos e instalados em qualquer Servlet Container.

De acordo com a especificao de Servlets, existem duas maneiras pelas quais uma aplicao web pode ser instalada junto a um Servlet Container: por meio de um arquivo WAR (Web Application Archive), explicado mais adiante no Captulo 9, ou por meio de uma estrutura de diretrios criada junto ao servidor. No caso especfico do Tomcat, essa estrutura deve ser criada abaixo do diretrio webapps. Para uma determinada aplicao Web, a estrutura de diretrios mnima que deve ser criada abaixo do diretrio webapps a seguinte:

Figura 2.2 Estrutura mnima de diretrios de uma Aplicao Web.

17

Conforme pode ser visto na figura anterior, deve ser criado, abaixo do diretrio webapps , um diretrio com o nome da aplicao. Esse diretrio deve conter pelo menos um subdiretrio WEB-INF; podem haver alm do subdiretrio WEB-INF, por outro lado, outros subdiretrios e arquivos, como pginas html, pginas JSP etc. O diretrio WEB-INF, por sua vez, deve conter um arquivo chamado web.xml e dois subdiretrios: classes, com todas as classes, e lib, com as bibliotecas utilizadas. Obviamente, abaixo do diretrio classes podem haver subdiretrios para refletir o path relacionado aos packages Java (mais informaes sobre packages podem ser obtidas em qualquer livro introdutrio sobre a linguagem Java). Utilizando como exemplo uma aplicao chamada RemoteIP, contendo o Servlet RemoteIPServlet do exemplo do captulo 1 desse livro, uma estrutura possvel abaixo do diretrio webapps seria a seguinte:

18

Figura 2.3 Exemplo de estrutura para aplicao RemoteIP . Obviamente, podem haver diversas aplicaes instaladas, gerando diversas rvores de diretrios abaixo do diretrio webapps:

Figura 2.4 Exemplo de algumas aplicaes instaladas abaixo do diretrio webapps. Cada uma dessas aplicaes carregada pelo Servidor em um Servlet Context (Contexto do Servlet). Cada contexto d sua aplicao uma URL base, chamada de Context Path (Path do Contexto), e prov um ambiente comum para todos os Servlets da aplicao. O path do contexto serve para que o Servidor possa mapear e distribuir as requisies recebidas para as diversas aplicaes instaladas. No Apache Tomcat, o path do contexto coincide com o nome do subdiretrio criado abaixo do webapps. Assim, no nosso exemplo, supondo que o endereo IP do servidor onde instalamos o Apache Tomcat 192.168.0.1 , teremos os acessos s URLs iniciadas por

19

http: / / 1 9 2 .1 6 8.0.1:8080 / Re m o teIP

direcionadas para a aplicao RemoteIP, os acessos s URLs iniciadas porhttp: / / 1 9 2 .1 6 8.0.1:8080 / C a d a s t r oClientes

direcionadas para a aplicao CadastroClientes , e assim por diante.

Figura 2.5 Exemplo de mapeamento de requisies para aplicaes instaladas no Tomcat. Por fim, conforme o leitor pode ter reparado nos exemplos citados anteriormente, para cada aplicao h um Deployment Descriptor: trata- se de um arquivo, chamado web.xml e localizado abaixo do diretrio WEBINF, e que contm informaes de configurao da aplicao, tais como, parmetros de inicializao, mapeamentos de Servlets, entre outros.Deployment Descriptor: Arquivo XML com as informaes de configurao de uma Aplicao Web. Esse arquivo fica abaixo do diretrio WEB-INF e se chama web.xml.

Um possvel Deployment Descriptor para a aplicao RemoteIP, por exemplo, seria o seguinte:

Exemplo de Deploym e nt Descriptor

20

Re m o t eIP< / d i s play - name > Re mo teIP< / s e r vlet - name > Re m o teIPServlet < / s e r vlet - class > < / s e rvlet > Re mo teIP< / s e r vlet - name > / R e m o teIP< / u r l - patter n > < / s e rvlet - map ping > < /w e b - app >

Como o Deployment Descriptor composto de muitas sees, procuraremos apresentar as principais e suas respectivas funes, usando como exemplo a aplicao CadastroClientes mencionada anteriormente. Uma apresentao mais detalhada e aprofundada desse arquivo pode ser encontrada na prpria especificao de Servlets. Pressupomos, para essa apresentao um conhecimento mnimo de XML; caso voc no tenha familiaridade com esse tipo de documento, sugerimos que voc tente acompanhar os exemplos, e os utilize como templates para criar seus prprios Deployment Descritors.

Estrutura geral do Deploym e nt Descriptor . . . < /w e b - app >

Assim, como em qualquer documento XML, inicialmente so colocados os elementos de declarao do XML e do tipo de documento (XML declaration e Document type

21

declaration). Na figura anterior, esses correspondem s 6 primeiras linhas listadas.

elementos

Em seguida, vem o elemento web- app : esse o elemento root (raiz) desse XML, ou seja, deve haver somente um elemento web- app , e abaixo dele devem ficar todos os outros elementos do XML. Os principais elementos abaixo do elemento root so os seguintes: display- name, context - param , session- config , welcome- file- list , error- page, servlet e servlet - mapping . O elemento display- name deve conter um nome da aplicao a ser apresentado por ferramentas GUI de gerenciamento / desenvolvimento de Aplicaes Web. Esse elemento opcional, porm caso voc decida utiliz- lo, importante que haja somente um desses elementos por Deployment Descriptor.

Exemplo de utilizao do elemento display - nameCa d a s t r o de Clientes < / d i s pl ay - name >

O elemento context - param serve para que se possam definir parmetros de inicializao do contexto da aplicao; esses parmetros estaro disponveis para todos os Servlets e pginas JSP da aplicao. Cada elemento presente deve conter o nome de um parmetro e o seu valor correspondente. O desenvolvedor pode tambm optar por no utilizar nenhum desses elementos em seu XML.

Exemplo de utilizao do elemento context - param N o m eBaseDa do s < / p a r a m - name > d b a plic < / p a r a m - value > < /c o n t ex t - para m > IPBancoDado s < / p a r a m - name > 1 9 2.168.0.2 < / p a r a m - value > < /c o n t ex t - para m >

O elemento seguinte, session- config , serve para que se possa especificar o perodo mximo, em minutos, de uma

22

sesso (esse recurso explicado mais adiante no captulo 6 Sesses). Assim como o elemento name , esse elemento opcional, mas desenvolvedor opte por utiliz - lo, deve existir uma instncia desse elemento no arquivo.

livro, no displaycaso o somente

Exemplo de utilizao do elemento session - config 1 5 < / s e s si o n - timeout > < / se s sio n - config >

Os elementos welcome- file- list e error - page contm, respectivamente, a lista ordenada de pginas a serem utilizadas como index e as pginas a serem apresentadas em casos de erros HTTP ou excees no tratadas pela aplicao. Esses dois elementos so opcionais, sendo que somente o primeiro admite uma instncia por Deployment Descriptor.

Exemplo de utilizao dos elemento s welcom e file- list e error- page index.html < / w e lc o m e - file> index.jsp < / w e lc o m e - file> < /w elco me - file- list> 4 0 4 < / e r r o r - code > / 4 0 4Err or.ht ml < / l o c a tion > < /e r r o r - page > c o m. min h ae m p r e s a.exceptions.DBConnException < / e x c e p tio n type > / DBError.ht ml < / l o c a tion > < /e r r o r - page >

De acordo com o que apresentado na listagem anterior, se tomarmos como exemplo nossa aplicao CadastroClientes , quando feito um acesso a URL http: / / 1 92.168.0.1:8080 /CadastroClientes/ , o Servidor tentar retornar a pgina index.html, conforme

23

especificado na lista do welcome- file- list . Caso essa pgina no exista, o Servidor tentar utilizar a pgina index.jsp. A figura anterior tambm demonstra a utilizao do elemento error - page duas vezes: a primeira vez para mapear erros HTTP 404 (pgina no encontrada) a uma pgina de erro- padro, e a segunda, para mapear exceptions com.minhaempresa.exceptions. DBConnException a uma outra pgina de erro. Os ltimos dois elementos, servlet e servlet - mapping , servem para definir, respectivamente, os Servlets da aplicao, com seus respectivos parmetros, e os mapeamentos de URLs a cada Servlet da aplicao. Cada elemento servlet , por sua vez, composto dos seguintes elementos: servlet - name: deve conter o nome do Servlet. servlet - class: deve conter o nome da classe (incluindo a informao sobre o package, se existir). init - param: deve conter um parmetro de inicializao do Servlet; pode haver nenhum, somente um, ou mais de um elemento deste tipo para cada Servlet. load- on- startup: deve conter um inteiro positivo indicando a ordem de carga deste Servlet em relao aos outros Servlets da aplicao, sendo que inteiros menores so carregados primeiro; se este elemento no existir, ou seu valor no for um inteiro positivo, fica a cargo do Servlet Container decidir quando o Servlet ser carregado (possivelmente, no instante em que chegar chegar a primeira requisio a esse Servlet).

Exemplo de utilizao do elemento servlet Pr oc e ss aCa da st r o < / s e r vlet - name > c o m. mi n h a e m p r e s a.Cada str oCliente s.ProcCadas tr o < / s e r vle t class > < p a r a m - name >E mail.ServidorSMTP< / p a r a m name > < p a r a m -

24

value > s m t p. mi nha e m p r e s a.co m.br < / p a r a m - value > < / i ni t para m > < p a r a m - name >E mail.Remete nte < / p a r a m name > < p a r a m value > site@minhae m p r e s a.co m.br < / p a r a m - value > < / i ni t para m > < p a r a m - name >E mail.Destina ta rio < / p a r a m name > < p a r a m value >ve n d a s@minhae m p r e s a.co m.br < / p a r a m - value > < / i n i t para m > < p a r a m - name >E mail.Assunt o < / p a r a m name > < p a r a m - value > Novo cadastr o de cliente < / p a r a m - value > < / i n it - para m > 0 < / l o a d - on - startup > < / se r vlet >

Por fim, um elemento servlet- mapping contm um nome de Servlet, conforme definido em servlet - name, e um padro da URL do Servlet no servidor (URL pattern).

Exemplo de utilizao do elemento servlet mapping Pr oc e ss aCa da st r o < / s e r vlet - name > / P r oc e s s a m e n t o < / u r l - patter n > < / se r vlet - map ping >

No exemplo anterior, todos as requisies com URLs iniciadas por /CadastroClientes/Processamento/ sero mapeadas para o Servlet cujo nome ProcessaCadastro . Outros mapeamentos interessantes podem ser obtidos atravs de padres de URL do tipo *. , como por exemplo, *.wm ou *.pdf , de maneira que o acessos a todas as URLs com o sufixo indicado sejam tratados por um mesmo Servlet. Um ltimo exemplo de mapeamento interessante diz respeito ao padro / , que define o Servlet default para todos os acessos que no se encaixarem em nenhum outro padro. Juntando ento todos os elementos apresentados anteriormente, temos o Deployment Descriptor de exemplo apresentado a seguir:

25

Exemplo de Deploym e nt Descriptor completo para a aplicao CadastroClientes Ca d a s t r o de Clientes < / d i s play - name > N o meBaseDa dos < / p a r a m - name > d b a plic < / p a r a m - value > < /c o n te x t - para m > IPBancoDado s < / p a r a m - name > 1 9 2.168.0.2 < / p a r a m - value > < /c o n te x t - para m > 1 5 < / s e s si o n - timeout > < / s e s sio n - config> index.html < / w e lc o me - file> index.jsp < / w e lc o m e - file> < /w elco m e - file- list> 4 04 < / e r r o r - code > / 4 0 4Err or.ht ml < / l o c a tion > < /e r r o r - page > c o m. min h ae m p r e s a.exceptions.DBConnException < / e x c e p tio n type > / DBError.ht ml < / l o c a tion > < /e r r o r - page > Pr oce ss aCa da st r o < / s e r vle t - name >

26

c o m. mi n h a e m p r e s a.Cada str oCliente s.ProcCadas tr o < / s e r vle t class > < p a r a m - name >E mail.ServidorSMTP< / p a r a m name > < p a r a m - value > smtp.min h a e m p r e s a.co m.br < / p a r a m - value > < / i n it para m > < p a r a m - name >E mail.Remete nte < / p a r a m name > < p a r a m - value > site@minh ae m p r e s a.co m.br < / p a r a m - value > < / i n it - para m > < p a r a m - name >E mail.Destinata rio < / p a r a m name > < p a r a m - value > venda s@minha e m p r e s a.co m.br < / p a r a m - value > < / i n it para m > < p a r a m - name >E mail.Assunt o < / p a r a m name > < p a r a m - value > Novo cadastr o de cliente < / p a r a m - value > < / i n it - para m > 0 < / l o a d - on - startup > < / s e rvlet > For m ula rioCada s t r o < / s e r vle t - name > c o m. mi n h a e m p r e s a.Cada str oCliente s.For mCa da s tr o < / s e r vle t class > < / s e rvlet > Pr oce ss aCa da st r o < / s e r vle t - name > / P r oc e s s a m e n t o < / u r l - patter n > < / s e rvlet - map ping > For m ula rioCada s t r o < / s e r vle t - name > / F o r m ul a rio < / u r l - patter n > < / s e rvlet - map ping > < /w e b - app >

27

Captulo 3 Servlets caractersticas bsicas

Nesse captulo, exploramos as caractersticas bsicas de Servlets, mostrando o funcionamento e sua interao com o Servlet Container. Implementamos tambm nossos primeiros Servlets de exemplo.

3.1 Biblioteca e documentaoAntes que voc possa iniciar o desenvolvimento de seus Servlets, imprescindvel que voc tenha disponvel a biblioteca de Servlets Java (normalmente, um arquivo chamado servlet.jar ; se voc estiver utilizando o Apache Tomcat, voc pode encontrar esse arquivo abaixo do diretrio de instalao do Tomcat, no subdiretrio common \lib ). Essa biblioteca contm todas as classes e interfaces necessrias para o desenvolvimento de Servlets, e deve estar contida em seu classpath. Outro item importante, embora no imprescindvel, a documentao da API de Servlets. Por meio dessa documentao, voc poder verificar todos as classes, com seus respectivos mtodos e variveis, com os quais voc poder contar durante o processo de desenvolvimento. Essa documentao pode ser obtida diretamente do site oficial do Java (http: / / java.sun.com ).

28

3.2 O protocolo HTTPEmbora Servlets possam ser utilizados no s para o desenvolvimento de aplicaes HTTP, a maior parte das aplicaes desenvolvidas so destinadas a esse fim. Sendo assim, vale a pena estudar um pouco mais a fundo o funcionamento e caractersticas desse protocolo. O protocolo HTTP utilizado na navegao nas pginas da Internet: quando voc abre uma janela de um browser, acessa uma pgina Web e navega em seus links, voc est, na verdade, utilizando esse protocolo para visualizar, em sua mquina, o contedo que est armazenado em servidores remotos. O HTTP um protocolo stateless de comunicao clienteservidor: o cliente envia uma requisio para o servidor, este processa a requisio e devolve uma resposta para o cliente, sendo que, a princpio, nenhuma informao mantida no servidor em relao s requisies previamente recebidas. Assim, quando digitamos o endereo de uma pgina em um browser Web, estamos gerando uma requisio a um servidor, que ir, por sua vez, devolver para o browser o contedo da pgina HTML requisitada. A requisio enviada por um cliente deve conter, basicamente, um comando (tambm chamado de mtodo), o endereo de um recurso no servidor (tambm chamado de path) e uma informao sobre a verso do protocolo HTTP sendo utilizado. Supondo, por exemplo, que utilize - se o mtodo GET, o path /index.html e a verso 1.0 do protocolo HTTP (o que equivale a digitar um endereo http: / / < e n dereo de algum servidor> / i n dex.html em um browser), temos a seguinte requisio enviada:

Exemplo de requisio HTTPGET /in dex.html HTTP/1.0

29

Existem diversos mtodos HTTP que podem ser especificados em requisies, sendo os mais comuns o mtodo GET, normalmente utilizado para obter o contedo de um arquivo no servidor, e o mtodo POST, utilizado para enviar dados de formulrios HTML ao servidor. Alm desses mtodos, o protocolo HTTP 1.0 admite tambm o mtodo HEAD, que permite que o cliente obtenha somente os headers da resposta; j o protocolo HTTP verso 1.1 admite os seguintes mtodos: PUT: transfere um arquivo do cliente para o servidor DELETE: remove um arquivo do servidor OPTIONS: obtm a lista dos mtodos suportados pelo servidor TRACE: retorna o contedo da requisio enviada de volta para o cliente Alm do mtodo, path e verso, uma requisio pode conter parmetros adicionais, chamados headers. Dois headers comuns so, por exemplo, o header User- Agent , que contm informaes sobre o cliente que est gerando a requisio (tipo, verso do browser etc.) e o header Accept , que serve para especificar os tipos de recursos aceitos pelo cliente para a requisio enviada.

Exemplo de requisio HTTP com headersGET /in dex.html HTTP/1.0 User - Agent: Mozilla /4.0 (compa tible; MSIE 5.0; Windows 98; DigExt) Accept: text / h t ml

Uma vez processada a requisio, o servidor, por sua vez, manda uma resposta para o cliente, sendo que essa resposta tambm tem um formato predeterminado: a primeira linha contm informaes sobre a verso do protocolo, um cdigo de status da resposta e uma mensagem associada a esse status; em seguida so enviados tambm headers (com informaes do servidor que gerou a resposta, por exemplo); e finalmente, enviado o contedo, propriamente dito, da resposta.

Exemplo de resposta HTTP com headers 30

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 ml Content - Length: 30 < /BODY> < /H TML>

Assim, no exemplo anterior, o cdigo de status 200 indica que houve sucesso no atendimento da requisio enviada pelo cliente, os headers indicam o tipo, tamanho e data e hora de ltima modificao do contedo requisitado, e por fim, temos uma pgina HTML em branco, com o contedo propriamente dito. Outros cdigos de status bastante comuns so o 404 , que indica que o recurso no foi localizado no servidor, e o cdigo 500 , que indica que houve erro no processamento da requisio enviada.

3.3 Hierarquia de um ServletConforme descrito anteriormente, um Servlet nada mais que uma classe Java que obedece a uma estrutura bem definida. Em especial, essa classe deve implementar a interface javax.servlet.Servlet . Existem duas classes, na biblioteca de Servlets, que implementam essa interface: javax.servlet.GenericServlet e sua sub- classe, javax.servlet.http.HttpServlet . A classe GenericServlet , como o prprio nome indica, serve para atender requisies genricas (utilizando qualquer protocolo), e a classe HttpServlet , para atender requisies HTTP.

31

Figura 3.1 Hierarquia de classes associadas a um Servlet. No desenvolvimento do Servlet de nossa aplicao exemplo CadastroClientes , temos assim a seguinte declarao de classe:

Declarao do Servlet ProcCadastroimpo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*; / / Servlet para process a me nt o do cadastr o de novos clientes public class ProcCada str o extends HttpServlet { ... }

3.4 Ciclo de vida de um ServletTodo Servlet segue, por outro lado, um ciclo de vida composto de 3 fases: inicializao, atendimento de requisies e finalizao. A inicializao ocorre quando o Servlet Container carrega o Servlet: se o parmetro load- on- startup , do Deployment Descriptor (vide seo 2.2), estiver presente e contiver um inteiro positivo, essa carga ocorre quando o prprio servidor iniciado; caso contrrio, essa carga ocorre quando recebida a primeira requisio a ser mapeada para a aplicao que contm o Servlet. Aps a inicializao, o Servlet pode atender requisies. Assim, enquanto o servidor estiver ativo, e a aplicao que

32

contem o Servlet estiver carregada, este permanecer na fase 2 de seu ciclo. Um ponto importante com relao a essa fase, e que na verdade constitui uma vantagem da tecnologia de Servlets e pginas JSP com relao a outras tecnologias, que o fato do Servlet permanecer carregado permite que dados armazenados em variveis de classe persistam ao longo das diversas requisies recebidas. Assim, possvel manter um pool de conexes ao banco de dados, por exemplo, de maneira que no seja necessrio iniciar e estabelecer uma nova conexo ao banco de dados a cada requisio recebida. Finalmente, quando o servidor finalizado, ou quando a aplicao tornada inativa pelo Servlet Container, o Servlet finalizado.

Figura 3.2 Ciclo de vida de um Servlet. Cada uma das fases se traduz, na verdade, em mtodos do Servlet que so chamados pelo Servlet Container nos diversos instantes do ciclo. Apresentamos, nas sees subsequentes, os mtodos relacionados s fases de inicializao, finalizao e de atendimento de requisies.

3.5 InicializaoConforme apresentado nos pargrafos anteriores, a inicializao do Servlet ocorre no instante em que feita a carga da aplicao pelo Servlet Container. Nesse instante, o Servlet Container executa o mtodo init do Servlet, dando chance ao Servlet de executar quaisquer passos necessrios para sua inicializao, tais como: 1) leitura de parmetros de configurao

33

2) inicializao de variveis de classe (variveis estticas) 3) inicializao de conexes ao banco de dados, etc. Assim, podemos ter implementado ProcCadastro, por exemplo: em nosso Servlet

Inicializao do Servlet ProcCadastroimpo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*; / / Servlet para process a me nt o do cadastr o de novos clientes: a cada novo cadastr o bem sucedido, / / envia email com os dados do cadastr o public class ProcCada str o extends HttpServlet { ... public void init () { ... } ... }

As assinaturas do mtodo init() so:

Assinaturas do mtodo init ()public void init(); public void init( javax.servlet.ServletConfig p_config );

Conforme pode ser visto, o mtodo init() admite duas assinaturas, sendo que em uma delas, recebido como parmetro um objeto da classe javax.servlet.ServletConfig : atravs desse objeto, o Servlet pode obter os parmetros de inicializao do Servlet, contidos no Deployment Descriptor (veja seo 2.2). Por outro lado, caso voc opte por implementar o mtodo init() sem nenhum parmetro, possvel tambm obter uma referncia para o objeto ServletConfig por meio da chamada getServletConfig() da prpria classe javax.servlet.GenericServlet (a qual nossa classe estende).

Assinatura do mtodo getServletConfig ()

34

public javax.servlet.ServletConfig getServletConfig ();

Para obter um parmetro de inicializao do Servlet usando o objeto ServletConfig , deve- se utilizar o mtodo getInitParameter(), passando como parmetro o nome do parmetro que se deseja obter.

Assinatura do mtodo getInitParameter ()public java.lang.String getInitPara me te r( java.lang.String p_par a me te rN a m e );

Temos, a seguir, um exemplo de uso desse mtodo:

Exemplo de uso do mtodo getInitParameter() de um objeto ServletConfigpublic void init(ServletConfig p_servletConfig) throw s ServletException { super.init(p_servletConfig); String l_servidorSMTP = p_servletConfig.getInitPara me te r (Email.Servido rSMTP); if(l_servidorSMTP != null) { ... } }

Obviamente o mtodo getInitParameter() pode retornar um valor nulo caso o parmetro inicial a ser obtido no tenha sido definido, e por isso importante que voc faa a verificao do String retornado pela chamada do mtodo antes de utiliz - lo. possvel tambm, a partir de um objeto da classe ServletConfig , percorrer a lista dos parmetros de inicializao do Servlet, bastando utilizar o mtodo getInitParameterNames().

Assinatura do mtodo getInitParameterNam es ()public java.util.Enumer a tion getInitPara me te rNa me s();

Temos, a seguir, um exemplo de uso deste outro mtodo:

Exemplo de uso do mtodo getInitParameterName s () de um objeto ServletConfig 35

public void init(ServletConfig p_servletConfig) throw s ServletException { super.init(p_servletConfig); Enumeratio n l_para me te rNa me s = p_servletConfig.getInitPara m e te rNa me s (); if(l_para me te rNa m e s != null) while(l_para me t erNa me s.ha sMoreEleme nts ()) { String l_para me t erNa m e = (String) l_para me t erNa m e s.nextElement (); String l_para me t erValue = p_servletConfig.getInitParameter (l_parameterName) ; ... } } }

Assim, em nossa aplicao de exemplo CadastroClientes , podemos implementar o mtodo de inicializao do Servlet ProcCadastro como:

Inicializao do Servlet ProcCadastroimpo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*; / / Servlet para process a me nt o do cadastr o de novos clientes: / / a cada novo cadastr o bem sucedido, envia email com os dados do cadastr o public class ProcCada str o extends HttpServlet { / / Servidor SMTP a ser usado para o envio de email private static String _ServidorSMTP = null; / / Remetente, destinat rio e assunto do email a ser enviado a cada cadastr o private static String _Remetente = null, _Destinatario = null, _Assunto = null; public void init(ServletConfig p_servletConfig) throws ServletException {

36

super.init(p_servletConfig); / / Recupera n d o os par me tr o s de inicializa o do Servlet _ServidorSMTP = p_servletConfig.getInitPara me te r (Email.Servido rSMTP); _Remetente = p_servletConfig.getInitPara me te r (Email.Remeten t e); _Destinatario = p_servletConfig.getInitPara m e te r (Email.Destinata rio); _Assu nto = p_servletConfig.getInitPara me te r(Email.Assunt o); ... } }

Outro uso comum para o mtodo de inicializao do Servlet para o despacho de um ou mais Threads, que devero ser executados durante o perodo em que o Servlet permanecer carregado. Assim, um serlvet pode, por exemplo, iniciar um Thread que ir verificar continuamente a disponibilidade de uma conexo com o banco de dados, independente de qualquer requisio que receba. Este Servlet de exemplo apresentado a seguir:

Inicializao do Servlet VerificaConBDimpo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*; / / Servlet para verificar conexo com banco de dados: lana threa d que verifica statu s da conexo periodica me n te public class VerificaConDB extends HttpServlet impleme nts Runnable { / / Referncia ao thread que ir fazer a verificao da conexo Threa d _ThreadVerif = null; / / Inicializa o do Servlet public void init(ServletConfig p_servletConfig) throws ServletException { super.init(p_servletConfig);

37

/ / Lanand o Threa d ... _Threa dVerif = new Threa d(this); _Threa dVerif.star t (); ... } / / Execuo do thread public void run() { while(_ThreadVerif != null) { if(!ConBD.OK ()) { ... } } } ... }

Uma observao importante com relao a esse processo de inicializao que o Servlet somente poder receber requisies aps a concluso de seu processo de inicializao. O desenvolvedor pode, por outro lado, indicar que esse processo de inicializao no foi bem sucedido, atravs do lanamento da exceptions ServletException ou UnavailableException ; nestes casos, o Servlet Container ir deixar o Servlet em um estado inativo, ou seja, sem poder receber requisies. A exception UnavailableException , em particular, pode receber como parmetro em seu construtor, um nmero de segundos com uma estimativa de quanto tempo o Servlet dever ficar inativo.

Exemplo de uso da exceo UnavailableException para indicar fracass o na inicializaopublic void init(ServletConfig p_servletConfig) throws ServletException, UnavailableException { super.init(p_servletConfig); ... / / Recupera n d o e validando par me tr o s de inicializao do Servlet

38

_ServidorSMTP = p_servletConfig.getInitPara me te r (Email.Servido rSMTP); _Remeten te = p_servletConfig.getInitPara me te r (Email.Remeten t e); _Destinata rio = p_servletConfig.getInitPara me te r (Email.Destinata rio); _Assun to = p_servletConfig.getInitPara me te r(Email.Assunt o); if((_ServidorSMTP = = null) || (_Remetente = = null) || (_Assunto = = null)) throw new UnavailableException(Erro: parme t r os de inicializao no encontr a d o s!);

No caso de voc no ter percebido, todos os mtodos init() apresentados at agora nos exemplos foram declarados de maneira a possibilitar o lanamento do exception ServletException : isso necessrio devido chamada do mtodo super.init (), que pode, por si, lanar essa exceo para indicar problemas em sua execuo.

3.6 A classe ServletContextAlm da referncia ao objeto da classe ServletConfig recebido como parmetro na inicializao, o Servlet pode obter tambm uma referncia a um objeto da classe javax.servlet.ServletContext atravs do mtodo getServletContext (), herdado da classe GenericServlet .

Assinatura do mtodo getServletContext ()public javax.servlet.ServletContext getServletContext();

Esse objeto ServletContext contm os atributos e informaes sobre o contexto em que o Servlet est sendo executado e, sendo assim, compartilhado por todos os Servlets que fazem parte da Aplicao Web. Analogamente ao que acontece com o objeto ServletConfig , existem mtodos para recuperar os parmetros iniciais do contexto definidos no DeploymentDescriptor (vide seo 2.2).

Assinatura dos mtodos getInitParameterName s () e getInitParameter () 39

public java.util.Enumer a tion getInitPara me te rNa me s(); public java.util.Enumer a tion getInitPara me te r(java.lang.String p_par a me te rN a m e);

Por outro lado, importante fazer a distino entre os parmetros iniciais do Servlet e os parmetros iniciais do contexto, lembrando sempre que esses parmetros so definidos em sees distintas do DeploymentDescriptor.

Exemplo de uso do mtodo getInitParameter do objeto ServletConfig e do objeto ServletContextpublic void init(ServletConfig p_servletConfig) throw s ServletException { super.init(p_servletConfig); / / Recupera n d o par me tr o s de execuo do Servlet String l_para mExec = p_servletConfig.getInitPara me te r (Parametr oExecucao); / / Se no existir tal par me tr o do Servlet, tenta mo s como par me tr o do contexto if(l_para mExec = = null) { ServletContext l_servletContext = getServletContext (); l_para mExec = l_servletContext.getInitPara m e te r (Parametr oExecucao); } ... }

Alm dos parmetros de inicializao do contexto do Servlet, podemos usar esse objeto para atribuir e recuperar atributos que sero compartilhados por todos os Servlets do contexto. Assim, temos os mtodos:

Assinatura dos mtodos getAttribute (), getAttributeName s (), removeAttribute() e setAttribute()public java.lang.Object getAttribute(java.lang.String p_attributeNa me); public java.util.Enumer a tion getAttributeNa me s(); public void removeAttribute(java.lang.String p_attributeN a m e);

40

public void setAttrib u te(java.lang.String p_attributeNa me, java.lang.Object p_attributeValue);

No exemplo a seguir, temos dois Servlets que fazem parte de uma mesma Aplicao Web e que utilizam os atributos do contexto para indicar falhas em suas respectivas inicializaes.

Exemplo de uso dos mtodos getAttribute e setAttribute do objeto ServletContextimpo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*; / / Primeiro Servlet do exemplo public class PrimeiroServlet extends HttpServlet { public void init(ServletConfig p_servletConfig) throws ServletException { super.init(p_servletConfig); / / Carregan d o o par me tr o inicial boolean l_sucesso = true; String l_para mInicial = p_servletConfig.getInitPara m e te r (ParamPrimeiroServlet); if(l_para mInicial = = null) l_sucesso = false; ... / / Usando o atribut o de contexto para indicar status da inicializao ServletContext l_servletContext = getServletContext (); l_servletCo ntext.setAttribute(PrimeiroServlet, new Boolean (l_sucesso)); / / Verificand o status do segund o Servlet Boolean l_statusSegun d oServlet = (Boolean) l_servletContext.getAttribut e(Segund oServlet); while(l_statu sSegun d oServlet = = null) { Thread.slee p(5000); / / Espera 5 segund os e verifica o statu s novame n te l_statu sSegun d oServlet = (Boolean) l_servletContext.getAttribut e(Segund oServlet);

41

} / / Se houve fracasso na inicializa o deste Servlet ou do segun d o, / / lanamo s uma exceo if((l_sucesso = = false) || (l_statusSegund oServlet.booleanValue () = = false)) throw new UnavailableException(Erro: os dois Servlets no pud era m ser carregad o s com sucesso!); } ... } / / Segundo Servlet do exemplo public class Segund oServlet extends HttpServlet { public void init(ServletConfig p_servletConfig) throws ServletException { super.init(p_servletConfig); / / Carregan d o o par me tr o inicial boolean l_sucesso = true; String l_para mInicial = p_servletConfig.getInitPara m e te r (ParamSegu n d oServlet); if(l_para mInicial = = null) l_sucesso = false; ... / / Usando o atribut o de contexto para indicar status da inicializao ServletContext l_servletContext = getServletContext (); l_servletCo ntext.setAttribute(Segund oServlet, new Boolean (l_sucesso)); / / Verificand o status do segund o Servlet Boolean l_statusPrimeiroServlet = (Boolean) l_servletContext.getAttribut e(PrimeiroServlet); while(l_statu sPrimeiroServlet = = null) { Thread.slee p(5000); / / Espera 5 segund os e verifica o statu s novame n te

42

l_statu sPrimeir oServlet = (Boolean) l_servletContext.getAttribut e(PrimeiroServlet); } / / Se houve fracasso na inicializa o deste Servlet ou do primeiro, / / lanamo s uma exceo if((l_sucesso = = false) || (l_statusPrimeiroServlet.boolea nValue () = = false)) throw new UnavailableException(Erro: os dois Servlets no pud era m ser carregado s!); } ... }

Por fim, h um outro mtodo da classe ServletContext que vale a pena conhecer: o mtodo log() permite que voc adicione mensagens em um arquivo de log do Servidor de Aplicaes. Voc poder utilizar esse mtodo para depurar seus Servlets, gerar alertas de problemas na sua execuo etc.

Assinatura dos mtodo log ()public void log(java.lang.String p_msg);

Em alguns Servidores de Aplicao voc pode tambm tentar usar as sadas- padro (System.out, System.err) para gerar suas mensagens de log, porm, muito mais interessante que voc use o mtodo anterior, de maneira que o ServletContainer possa separar as suas mensagens em um log diferenciado. No caso especfico do Tomcat, as mensagens geradas por meio do mtodo log() so adicionadas a um arquivo de log normalmente chamado localhost_log.ext.txt , onde ext uma extenso contendo a data corrente.

Exemplo de uso do mtodo log () (da classe ServletContext)impo rt java.io.*; impo rt javax.servlet.*;

43

impo rt javax.servlet.htt p.*; / / Servlet para teste de gerao de mensage ns de log public class TesteLog extends HttpServlet { / / Valor default para para me tr o inicial do Servlet private static final String _ValorDefaultPara mI nicial = ; public void init(ServletConfig p_servletConfig) throws ServletException { super.init(p_servletConfig); / / Recupera n d o os par me tr o s de inicializa o do Servlet String l_para mInicial = p_servletConfig.getInitPara me te r (Parametr oInicial); if(l_para mInicial = = null) { ServletContext l_context = p_servletConfig.getServletContext (); l_context.log(Aviso: no foi possvel se carregar o par me tr o inicial; atribuin d o valor default ...); l_para mInicial = _ValorDefaultPara mI nicial; } ... } ... }

3.7 FinalizaoA finalizao de um Servlet deve ser tratada atravs da implementao do mtodo destroy : no instante em que o Servlet descarregado, seu mtodo destroy , se tiver sido implementado, chamando, permitindo a execuo de rotinas de finalizao (como por exemplo, o encerramento de conexes com bancos de dados, finalizao de threads que tenham sido lanados etc.). A assinatura do mtodo destroy() a seguinte:

44

Assinatura do mtodo destroy ()public void destroy();

Utilizando nosso exemplo de cadastro de clientes, temos a seguir um exemplo de nosso Servlet VerificaConBD com os mtodos init() e destroy() implementados:

Inicializao do Servlet VerificaConBDimpo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*; / / Servlet para verificar conexo com banco de dados: lana threa d que verifica statu s da conexo periodica me n te public class VerificaConDB extends HttpServlet impleme nts Runnable { / / Referncia ao thread que ir fazer a verificao da conexo Threa d _ThreadVerif = null; / / Inicializa o do Servlet public void init(ServletConfig p_servletConfig) throws ServletException { super.init(p_servletConfig); / / Lanand o Threa d ... _Threa dVerif = new Threa d(this); _Threa dVerif.star t (); ... } / / Execuo do thread public void run() { while(_ThreadVerif != null) { if(!ConBD.OK ()) { ... } } }

45

/ / Finalizao do Servlet public void destroy() { _Threa dVerif = null; } ... }

No exemplo, o mtodo destroy() serve para indicar que o thread deve ser finalizado: a atribuio do valor null varivel _ThreadVerif faz com que o looping principal do mtodo run() seja finalizado.

3.8 Atendimento de RequisiesConforme descrito anteriormente na seo sobre o ciclo de vida de um Servlet, entre as fases de inicializao e finalizao, existe uma fase onde o Servlet ir, efetivamente, atender as requisies recebidas. No caso da classe GenericServlet , que a classe utilizada para Servlets genricos (classe- pai para a classe HttpServlet , que atende requisies HTTP), o mtodo relacionado a essa fase o mtodo service ().

Assinatura do mtodo service ()public void service(javax.servlet.ServletReque st p_reque st, javax.servlet.ServletRespo ns e p_respon se);

Assim, para cada requisio recebida de um cliente, o ServletContainer efetua uma chamada a esse mtodo service(...) do Servlet; os parmetros desse mtodo so referncias para um objeto que encapsula a requisio recebida e para um objeto que encapsula a resposta que dever ser encaminhada para o cliente. Por outro lado, como voc normalmente estar desenvolvendo Servlets HTTP, dificilmente voc ter que implementar esse mtodo; em vez disso, para classes que extendam a classe HttpServlet , voc dever implementar um ou mais dos seguintes mtodos: doDelete , doGet , doOptions , doPost , doPut ou doTrace.

46

Assinatura dos mtodos de atendimento de requests da classe HttpServletpublic void doGet(javax.servlet.htt p.HttpServletReques t p_reques t, javax.servlet.htt p.HttpServletRespon se p_respo ns e); public void doPost(javax.servlet.htt p.Htt pServletReque s t p_reque st, javax.servlet.htt p.HttpServletRespon se p_respo ns e); public void doDelete( javax.servlet.http.HttpServletReque st p_reque st, javax.servlet.htt p.HttpServletRespon se p_respo ns e); public void doPut(javax.servlet.http.HttpServletReque s t p_reque st, javax.servlet.htt p.HttpServletRespon se p_respo ns e); public void doOp tio ns(javax.servlet.http.HttpServletReque s t p_req ue st, javax.servlet.htt p.HttpServletRespon se p_respo ns e); public void doTrace(javax.servlet.htt p.HttpServletReques t p_reques t, javax.servlet.htt p.HttpServletRespon se p_respo ns e);

Quando uma requisio HTTP recebida por uma classe que estende HttpServlet, seu mtodo service() chamado, sendo que a implementao default desse mtodo ir chamar a funo doXXX () correspondente ao mtodo da requisio recebida. Ou seja, caso uma requisio com mtodo GET, por exemplo, seja recebida (vide seo 3.2, sobre o protocolo HTTP), o mtodo doGet() implementado por voc ser chamado. Geralmente, desenvolvedores de Servlets implementam somente os mtodos doGet() e doPost (); os mtodos restantes s so implementados em casos especiais, e requerem um conhecimento mais avanado por parte do desenvolvedor. Por ora, estaremos utilizando o mtodo doGet(); nos captulos seguintes demonstraremos com mais detalhes alguns dos outros mtodos (principalmente, o mtodo doPost()). Um exemplo simples de implementao do mtodo doGet() pode ser observado a seguir:

Servlet HelloWorldimpo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*;

47

/ / Servlet para pgina HelloWorld public class HelloWorld extends HttpServlet { / / Atendime n t o de requisies HTTP com mtodo GET public void doGet(HttpServletReque st p_reque st, HttpServletRespo n s e p_respon se) throws IOException { PrintWriter l_pw = p_respon se.getWriter (); l_pw.println( ); l_pw.println(Hello World!); l_pw.println(< /BODY> < / H TML >); l_pw.flush (); } }

3.9 Concorrncia no atendimento de requisiesDurante o ciclo de vida de um Servlet, o ServletContainer ir fazer a carga de um Servlet instanciando um nico objeto e chamando seu mtodo init(); a finalizao tambm efetuada chamando o mtodo destroy desse objeto. Na fase de atendimento de requisies, por outro lado, o mtodo service() (e, consequentemente, os mtodos doXXX (), no caso de Servlets HTTP), so chamados na medida em que so recebidas as requisies, ou seja, pode haver, em um determinado instante, um ou mais threads do ServletContainer executando mtodos service() simultaneamente.

48

Figura 3.3 Concorrncia no atendimento de requisies. Por isso muito importante que voc se preocupe com acesso a variveis de instncia ou classe e concorrncia no seu desenvolvimento (maiores detalhes sobre esses tpicos podem ser obtidos, por exemplo, no livro Aprendendo Java 2, da Editora Novatec). Nesse sentido, uma opo para garantir a execuo livre de problemas de concorrncia a implementao da interface SingleThreadModel em seu Servlet. Essa interface no define, na verdade, novos mtodos ou variveis de classe, ela serve somente para indicar ao ServletContainer que o atendimento de requisies do Servlet em questo deve ser feito de forma a serializar as chamadas ao mtodo service(). Ou seja, somente uma requisio ser atendida por vez pelo seu Servlet.

Exemplo de Servlet que implementa a interface SingleThreadModelimpo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*; / / Servlet simples que retor na pgina HTML com o nme r o de / / requisies recebida s at o mome nto public class ServletConta d or extends HttpServlet imple men t s SingleThrea dMo del {

49

/ / Conta d o r das requisies recebida s private int _Contador = 0; public void doGet(HttpServletReque st p_reque st, HttpServletResp o n s e p_respo n s e) throws IOException { PrintWriter l_pw = p_respon se.getWriter (); l_pw.println( ); l_pw.println(Requisie s recebidas: + Integer.toString(+ + _Conta d o r)); l_pw.println(< /BODY> < / H TML >); l_pw.flush (); } }

No exemplo anterior, o Servlet utiliza uma varivel de instncia _Contador e, por isso, h a necessidade de se preocupar com a concorrncia no acesso a esta varivel. Imagine, por exemplo, que esse Servlet no implemente a interface SingleThreadModel , e receba duas requisies simultaneamente: o primeiro doGet() poderia incrementar o contador, seguido do segundo doGet() incrementando o contador, seguido dos dois threads, cada um por sua vez, imprimindo o valor do contador. Nessa situao, o mesmo valor de contador seria impresso nas duas pginas HTML resultantes.

Resultado da primeira requisio Requisies recebida s: 2 < /BODY> < / H TML>

Resultado da segunda requisio Requisies recebida s: 2 < /BODY> < / H TML>

Obviamente a implementao dessa interface tem um custo na performance de execuo do Servlet, pois, no

50

Servlet anterior, por exemplo, no s o acesso a varivel _Contador serializado, mas a execuo do mtodo doGet () como um todo. Em particular, a execuo dos cdigos de gerao do header e do footer HTML no precisariam ser serializados, mas so. Por isso, em vez de implementar esta interface, na maioria das vezes mais conveniente implementar diretamente um cdigo de sincronizao nos trechos que precisam ser serializados. O Servlet ServletContador , por exemplo, poderia ser implementado da seguinte forma (com exatamente o mesmo resultado):

Exemplo de Servlet que substitui a impleme ntao da interface SingleThreadModel por cdigo de sincronizaoimpo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*; / / Servlet simples que retor na pgina HTML com o nme r o de / / requisies recebida s at o mome nto public class ServletConta d or extends HttpServlet { / / Conta d o r das requisies recebida s private int _Contador = 0; public void doGet(HttpServletReque st p_reque st, HttpServletResp o n s e p_respo n s e) throws IOException { / / Imprimin d o cabealho PrintWriter l_pw = p_respon se.getWriter (); l_pw.println( ); / / Armaz en a n d o valor do contado r em uma varivel local usan d o sincroni za o int l_contad o r; synchr o niz e d(this) { l_contad o r = + + _Conta dor; }

51

/ / Imprimin d o nmer o de requisies recebidas e rodap l_pw.println(Requisie s recebidas: + Integer.toString (l_contad o r)); l_pw.println(< /BODY> < / H TML >); l_pw.flush (); } }

3.10 Retornando informaes sobre o ServletAlm dos mtodos doXXX(), init() e destroy(), voc tambm pode implementar o mtodo getServletInfo() de um Servlet.

Assinatura do mtodo getServletInfo () da classe HttpServletpublic String getServletInfo ();

A implementao desse mtodo dever retornar um texto contendo informaes gerais sobre o Servlet desenvolvido, como por exemplo, o autor, verso e informaes de copyright de seu Servlet. Implementando esse HelloWorld , temos: mtodo para o nosso Servlet

Servlet HelloWorld com implementao do mtodo getServletInfo()impo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*; / / Servlet para pgina HelloWorld public class HelloWorld extends HttpServlet { / / Atendime n t o de requisies HTTP com mtodo GET public void doGet(HttpServletReque st p_reque st, HttpServletResp o n s e p_respo n s e) throws IOException {

52

PrintWriter l_pw = p_respon se.getWriter (); l_pw.println( ); l_pw.println(Hello World!); l_pw.println(< /BODY> < / H TML >); l_pw.flush (); } / / Retorna n d o infor ma e s sobre esse Servlet public String getServletInfo () { retur n Autor: Autores do livro; Verso: 1.0; } }

Caso voc no implemente esse mtodo, um texto vazio ser retornado pela implementao default desse mtodo.

53

Captulo 4 Servlets Gerao da sada

Embora j tenhamos visto um pouco sobre o funcionamento da gerao de uma resposta simples de um Servlet, estaremos neste captulo analisando esse processo mais a fundo e apresentando algumas funcionalidades mais avanadas.

4.1 Gerao de sada HTML simplesQuando o Servlet recebe uma requisio, sem mtodo doXXX() chamado com dois parmetros: uma referncia a um objeto da classe javax.servlet.http.HttpServletRequest , que encapsula a requisio recebida, e uma referncia a um objeto da classe javax.servlet.http.HttpServletResponse, que encapsula a resposta do Servlet.

Figura 4.1 Atendimento de uma requisio por um Servlet.

54

Sendo assim, a manipulao da resposta do Servlet passa, na verdade, pela manipulao do objeto dessa classe javax.servlet.http.HttpServletResponse. Para gerar uma sada simples, por exemplo, voc deve utilizar o mtodo getWriter() desse objeto. A chamada desse mtodo ir retornar uma referncia a um objeto da classe java.io.PrintWriter , que encapsula um stream de sada para um contedo do tipo texto. Esse stream deve ser utilizado para enviar a resposta de seu Servlet para o cliente que enviou a requisio.

Assinatura do mtodo getWriter ()public java.io.PrintWriter getWriter () throw s java.io.IOException;

Embora a anlise dos mtodos dessa classe fuja um pouco ao escopo deste livro (trata- se de uma classe do prprio core Java), interessante apresentar alguns de seus mtodos aqui. Os mtodos print () e println () dessa classe, por exemplo, podem ser utilizados para adicionar Strings ao stream de sada do Servlet; como a sada mantida em um buffer por questes de performance, voc pode tambm utilizar o mtodo flush () para forar a liberao desse buffer de sada, fazendo que o contedo da resposta definido por voc seja imediatamente enviado para o cliente.

Exemplo de gerao de sada simples de Servletimpo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*; / / Servlet para pgina HelloWorld public class HelloWorld extends HttpServlet { / / Atendime n t o de requisies HTTP com mtodo GET public void doGet(HttpServletReque st p_reque st, HttpServletResp o n s e p_respo ns e) throws IOException { PrintWriter l_pw = p_respon se.getWriter (); l_pw.print( );

55

l_pw.print( Hello World! ); l_pw.println( < /BODY> < / H TML > ); l_pw.flush (); } }

Assim, nesse exemplo, utilizamos o objeto da classe java.io.PrintWriter para adicionar um contedo texto (no caso uma pgina HTML) ao stream de sada do Servlet. A resposta recebida pelo cliente ser justamente essa pgina HTML. Se voc observou o exemplo anterior com cuidado (e, na verdade, todos os exemplos anteriores que incluiam algum mtodo doXXX ()), voc percebeu que o mtodo doGet () foi declarado de maneira a possibilitar o lanamento de uma exceo java.io.IOException : essa exceo pode ser lanada pelo mtodo getWriter () caso haja algum problema gerao de sada do Servlet. Outra opo de implementao para o Servlet HelloWorld seria, portanto:Exemplo de gerao de sada simples de Servlet com captur a de exceo: impo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*; / / Segunda impleme nt a o do Servlet para pgina HelloWorld public class HelloWorld extends HttpServlet { / / Atendime n t o de requisies HTTP com mtodo GET public void doGet(HttpServletReque s t p_reque st, HttpServletResp o n s e p_respo ns e) { try { PrintWriter l_pw = p_respo ns e.getWriter (); l_pw.print( ); l_pw.print(Hello World!); l_pw.println(< /BODY> < / H TML>); l_pw.flush ();

56

} catch( IOException p_e ) { ServletContext l_context = getServletContext (); l_context.log(Erro: no foi possvel utilizar a referncia ao objeto PrintWriter); } } }

Dessa forma, podemos capturar e tratar a exceo java.io.IOException caso ela ocorra, gerando, por exemplo, uma mensagem de log. Mais detalhes sobre essas excees lanadas durante o processo de gerao da sada do Servlet, incluindo suas possveis causas, so apresentadas ao longo das prximas sees desse captulo.

4.2 Headers da resposta HTTPConforme apresentado na seo 3.2 deste livro, a resposta a uma requisio HTTP composta de diversos elementos, sendo que alguns desses elementos so headers (cabealhos) HTTP.

Exemplo de resposta HTTP do Servlet HelloWorldHTTP/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 ml Content - Length: 40 Hello World!< /BODY> < / H TML >

Embora alguns headers sejam adicionados por default pelo ServletContainer, como no caso da resposta do Servlet HelloWorld acima, podem haver situaes em que voc queira definir ou modificar seus prprios headers HTTP, e para fazer isso, voc deve utilizar o mtodo setHeader ().

Assinatura do mtodo setHeader ()

57

public void setHead er( java.lang.String p_heade rNa me, java.lang.String p_hea derValue );

Para indicar, por exemplo, que a resposta de um Servlet no deve ficar armazenada em nenhum cache (armazenamento temporrio) do browser do usurio, nem em nenhum proxy, podemos definir alguns headers adicionais especiais por meio do seguinte trecho de cdigo:

Headers para evitar cacheam ento da resposta de um Servletpublic void doGet( HttpServletReque st p_reque st, HttpServletResp o n s e p_respo ns e ) { ... p_resp o n se.setHea de r( Cache - Control, no- cache, must revalidate ); p_resp o n se.setHea de r( Pragma, no- cache ); p_resp o n se.setHea de r( Expires, Mon, 26 Jul 1997 05:00:00 GMT ); p_resp o n se.setDateHea de r( Last- Modified, System.cu rr en tTim eMillis ()); ... }

Nesse cdigo, o header Expires indica a data de expirao, o header Last- Modified indica a data de ltima modificao, e os headers Cache- Control e Pragma indicam o tratamento que o documento (ou seja, a resposta do Servlet) deve receber se houver cacheamento. Com a incluso do cdigo anterior, a resposta do Servlet passa a ser:

Exemplo de resposta HTTP do Servlet HelloWorld com headers adicionaisHTTP/1.1 200 OK Server: Apache / 1.3.26 (Unix) Cache - Control: no - cache, must - revalidate Pragma: no - cache Expires: Mon, 26 Jul 1997 05:00:00 GMT

58

Last- Modified: Sun, 22 Dec 2002 17:47:59 GMT Content - Type: text /h t ml Content - Length: 40 Hello World!< /BODY> < / H TML >

Uma observao muito importante que essas adies / modificaes de headers HTTP devem acontecer antes da gerao do contedo da sada, para garantir a ordem dos elementos da resposta HTTP (ou seja, primeiro status, depois headers e, por fim, contedo). A alterao de um header aps a escrita de parte ou de todo o contedo pode gerar uma exceo java.lang.IllegalStateException e interromper o processo de gerao da sada do Servlet. Assim, o cdigo completo para o Servlet HelloWorld sem cacheamento pode ser escrito como:

Servlet HelloWorld com headers para evitar cacheame nto da pginaimpo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*; / / Terceira imple me nta o do Servlet para pgina HelloWorld public class HelloWorld extends HttpServlet { / / Atendime n t o de requisies HTTP com mtodo GET public void doGet(HttpServletReque s t p_reque st, HttpServletResp o n s e p_respo ns e) { try { / / Passo 1 Definindo header s p_respo n s e.se tHea de r(Cache - Control, no- cache, must revalidate); p_respo n s e.se tHea de r(Pragma, no- cache); p_respo n s e.se tHea de r(Expires, Mon, 26 Jul 1997 05:00:00 GMT); p_respo n s e.se tDa teHea de r(Last - Modified, System.cu rr en tTim eMillis ()); / / Passo 2 Gerando a pgina de resposta

59

PrintWriter l_pw = p_respo ns e.getWriter (); l_pw.print( ); l_pw.print(Hello World!); l_pw.println(< /BODY> < / H TML>); l_pw.flush (); } catch( IOException p_e ) { ServletCon text l_context = getServletContext (); l_context.log(Erro: no foi possvel obter referncia ao objeto PrintWriter); } } }

Se voc observou atentamente o cdigo para a modificao dos headers, voc deve ter reparado no uso de um mtodo setDateHeader(): esse mtodo , na verdade, uma variante do mtodo setHeader() que simplifica a definio de um header com uma data. Assim como esse mtodo, existe um outro mtodo setIntHeader() para a definio de headers que contenham valores inteiros.

Assinaturas dos mtodos setDateHeader() e setIntHeader()public void setDateHea der(java.lang.String p_heade rNa m e, long p_date); public void setIntHeade r(java.lang.String p_headerN a me, long p_int);

O segundo parmetro do mtodo setDateHeader() deve conter o nmero de milisegundos desde epoch (meianoite, do dia 1 de Janeiro de 1970); o mtodo currentTimeMillis() do objeto java.lang.System retorna esse valor para o instante corrente. Alm dos mtodos anteriores, existe o mtodo containsHeader(), para verificar se um header j foi definido, e os mtodos addHeader(), addDateHeader() e addIntHeader() que permitem a adio de mais de um valor para um mesmo header.

60

Assinaturas dos mtodos containsHeader(), addHeader(),addDateHeader() e addIntHeader ()public boolean containsHea de r(java.lang.String p_headerNa m e); public void addHea de r(java.lang.String p_heade rNa me, java.lang.String p_hea derValue); public void addDateHea der(java.lang.String p_heade rNa me, long p_date); public void addIntHea de r(java.lang.String p_headerN a me, long p_int);

Podemos usar o mtodo containsHeader() para verificar, por exemplo, se o header Content - Type j foi definido, e defini - lo em caso negativo:

Servlet HelloWorld com definio do header Content - Typeimpo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*; / / Quarta imple me n ta o do Servlet para pgina HelloWorld public class HelloWorld extends HttpServlet { / / Atendime n t o de requisies HTTP com mtodo GET public void doGet(HttpServletReque s t p_reque st, HttpServletResp o n s e p_respo ns e) { try { / / Passo 1 - Definindo header s if(!p_respo n de.containsHe a de r(Conte nt - Type)) p_resp ons e.se tHea de r(Conte nt - Type, text / h t ml); / / Passo 2 Gerando a pgina de resposta PrintWriter l_pw = p_respo ns e.getWriter (); l_pw.print( ); l_pw.print(Hello World!); l_pw.println(< /BODY> < / H TML>); l_pw.flush (); } catch( IOException p_e ) { ServletContext l_context = getServletContext ();

61

l_context.log(Erro: no foi possvel obter referncia ao objeto PrintWriter); } } }

A funo desse header Content - Type informar o tipo do contedo que est contido na resposta, para que o browser (ou dispositivo cliente que est fazendo o acesso) saiba como esse contedo deve ser interpretado e apresentado. Nos exemplos anteriores esse header no foi definido explicitamente em cdigo: nesses casos, o ServletContainer automaticamente define seu valor como text / html . Esse valor indica que o contedo deve ser interpretado pelo browser como uma pgina HTML. Outro header que definido automaticamente pelo ServletContainer, caso o desenvolvedor no o defina explicitamente, o header Content - Length . Esse header indica o tamanho em bytes do contedo contido na resposta. Podem haver casos em que seja necessrio se alterar esse comportamento default: nesses casos, o desenvolvedor pode utilizar os mtodos setXXXHeader () apresentados anteriormente, ou o mtodo setContentLength () diretamente.

Assinatura do mtodo setContentLength()public void setConte ntLength( int p_conte ntLength );

4.2 Gerao de outros tipos de sadasConforme mencionado no na seo anterior, o header Content - Type serve para indicar o tipo do contedo contido na resposta do Servlet. Dessa maneira, o valor text / html indica uma pgina HTML, o valor image/jpeg indica uma imagem JPEG, e assim por diante.

62

Devido a sua importncia, existe uma funo especial utilizada para a definio do valor desse header.

Assinatura do mtodo setContentTyp e()public void setConte ntType(java.lang.String p_conte ntType);

Embora a gerao de uma sada HTML seja a situao mais comum, podem haver situaes em que voc deseje gerar outros tipos de sada. Nesses casos, voc deve utilizar o mtodo setContentType para especificar o tipo do contedo desejado. Assim, podemos usar o seguinte trecho de cdigo para retornar uma imagem JPEG contida em um arquivo:

Servlet ImageServletimpo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*; / / Servlet para gerao de sada com image m JPEG public class ImageServlet extends HttpServlet { public void doGet(HttpServletReque s t p_reque st, HttpServletResp o n s e p_respo ns e) { FileInpu tStrea m l_imageFile = null; try { / / Definindo o tipo do conted o p_respo n s e.se tConte ntType(image / j p e g); / / Obten d o o arquivo com a image m JPEG a partir dos par me tr o s / / de inicializa o do Servlet l_imageFile = new FileInputStrea m(getServletConfig ().getInitPara me te r(JpegFilena me)); / / Lendo o conte d o de um arquivo contend o uma imagem e / / retor na n d o este conte d o como resposta ServletOutp u tStrea m l_os = p_respo ns e.getOut p u tStre a m (); byte [] l_buffer = new byte[1024]; int l_bytes = 0;

63

while((l_bytes = l_imageFile.read(l_buffer)) != - 1) l_os.write(l_buffer, 0, l_bytes); / / Finalizando processo de gerao de sada e fechand o o arquivo l_os.flush (); l_imageFile.close (); } catch(IOException p_e) { try { if(l_imageFile != null) l_imageFile.close (); } catch(Exception p_e2) {} ServletContext l_context = getServletContext (); l_context.log(Erro: no foi possvel ler imagem de arquivo); } } }

No exemplo anterior, voc poder observar tambm a utilizao do mtodo getOutputStream (). Esse mtodo deve ser utilizado, em substituio ao mtodo getWriter () que foi usado nos exemplos anteriores, para obter uma referncia a um stream de sada binria do Servlet. Assim, quando voc desejar que seu Servlet retorne um contedo binrio (no- texto), como uma imagem JPEG no cdigo anterior, voc dever utilizar esse mtodo getOutputStream (), e obter uma referncia a um objeto da classe javax.servlet.ServletOutputStream . Esse stream ServletOutputStream extende, na verdade, a classe java.io.OutputStream e, sendo assim, herda os diversos mtodos write() e o mtodo flush() da classe- me.

Assinaturas dos mtodos write() e flush ()public public public public void void void void write(byte [] p_byteArray); write( byte [] p_byteArray, int p_offset, int p_length ); write( int p_byte ); flush();

64

Obviamente, a utilizao dos mtodos anteriores e at mesmo a obteno desse stream de sada binria do Servlet podem gerar excees do tipo java.io.IOException , em situaes em que o usurio que est operando o browser aperta o boto Stop, antes de todo o contedo gerado pelo seu Servlet seja enviado, por exemplo. Por isso importante que voc se preocupe em capturar essas excees, e fazer os tratamentos necessrios caso isso ocorra.

4.3 Gerando contedo XMLDentre os diversos tipos de contedos que podem ser gerados como resposta de um Servlet, apresentamos aqui, como mais um exemplo, a gerao de documentos XML. Documentos XML so normalmente usados para estruturar um conjunto de dados de maneira simples, bem - definida e eficiente. Um exemplo de documento XML j foi apresentado no Captulo 2 Instalao e Configurao : o Deployment Descriptor um arquivo XML que descreve a maneira como o ServletContainer deve carregar e gerenciar uma Aplicao Web. Um outro tipo de documento XML bastante utilizado atualmente o WML (definido dentro do padro WAP, ou Wireless Application Protocol): atravs desse formato, um servidor pode formatar um contedo que ser visualizado na tela de telefones celulares. Embora a explicao detalhada do formato de um documento WML fuja ao escopo deste livro (mais detalhes podem ser obtidos no site do WapForum, http: / / w ww.wapforum.org ), apresentamos abaixo o cdigo de um Servlet que gera uma pgina WML apenas para exemplificar a gerao de um documento XML.

Servlet HelloWorldWMLimpo rt java.io.*; impo rt javax.servlet.*; impo rt javax.servlet.htt p.*;

65

/ / Quarta imple me n ta o do Servlet para pgina HelloWorld, desta vez com a gerao da resposta em formato WML public class HelloWorldWML extends HttpServlet { / / Atendi