introdução à programação com java server pages e … 0… · introdução à programação com...

24
IV Congresso Brasileiro de Computação CBComp 2004 Brasil Introdução à Programação com Java Server Pages e Servlets Rafael Santos Instituto Brasileiro de Tecnologia Avançada – IBTA Unidade São José dos Campos 12242-431 Brasil [email protected] RESUMO R. Santos. 2004. Introdução à Programação com Java Server Pages e Servlets. Congresso Brasileiro de Ciência da Computação, Itajaí, 2004, 849 – 872. Itajaí, SC – Brasil, ISSN 1677-2822 Uma das áreas de desenvolvimento de sistemas que apresentou maior crescimento nos últimos anos é a de desenvolvimento de sistemas cliente-servidor onde o cliente é um navegador e todo o processamento é feito no servidor. Estes sistemas usam a Internet ou intranets para transmissão das informações entre cliente e servidor. O processamento das informações neste tipo de sistema é feito na maioria dos casos exclusivamente do lado do servidor, que recebe informações do usuário através do navegador, as processa e retorna ao usuário através de páginas em HTML geradas pelo próprio sistema. O objetivo deste mini-curso é apresentar os conceitos básicos de Java Server Pages e servlets para o desenvolvimento de aplicações cliente-servidor. O curso supõe que o estudante conhece alguma linguagem de programação (conceitos de lógica, subrotinas e funções, parâmetros, etc.) e tenha experiência básica no desenvolvimento para a Internet (conhecimentos básicos de como a Internet e navegadores funcionam). PALAVRAS DE INDEXAÇÃO ADICIONAIS: Programação cliente-servidor, Java 2 Enterprise Edition INTRODUÇÃO Sistemas computacionais onde o cliente é um navegador e o servidor executa aplicações enviando e recebendo dados para este cliente são muito comuns, em especial na Internet. As vantagens de um sistema cliente-servidor deste tipo são várias: clientes podem acessar o sistema de qualquer computador com acesso à Internet (e com permissões adicionais, se for necessário); não existe dificuldade em fazer modificações no sistema, uma vez que não é necessário redistribuir aplicações clientes; clientes são em grande maioria independentes de alguns requisitos como sistemas operacionais específicos ou softwares adicionais ou mesmo de performance de processador. A desvantagem óbvia deste tipo de sistemas é a dependência do funcionamento com performance adequada da comunicação entre o cliente e o servidor para o funcionamento do sistema. A execução do processamento de dados destes sistemas é feita quase exclusivamente do lado do servidor, uma vez que o cliente (navegador) só é responsável pela apresentação dos formulários de entrada de dados e saída formatada dos mesmos. Existem várias alternativas para programação do lado do servidor onde o cliente é um navegador, sendo que as mais usadas e conhecidas são ASP, PHP e Java Server Pages / Servlets. As vantagens de Java Server Pages (JSP) e servlets sobre as alternativas são o uso da linguagem Java como base, evitando que o programador tenha que aprender um padrão de linguagem para cliente e outro para servidor; e possivelmente ainda outro para desenvolvimento de aplicações no desktop. Este tutorial apresenta os conceitos básicos de programação de Java Server Pages e servlets, mostrando os conceitos básicos de programação cliente-servidor com navegadores como clientes, e usando vários exemplos simples de ambas as tecnologias. O tutorial foi escrito com a intenção de ser uma introdução às tecnologias JSP e servlets, não cobrindo muitos aspectos intermediários e avançados da plataforma J2EE (Java 2 Enterprise Edition). Neste tutorial também não veremos alguns conceitos que são interessantes para o desenvolvimento de sistemas comerciais complexos e atrativos, como, por exemplo, HTML (Hypertext Markup Language) intermediário e avançado, programação em Java e orientação a objetos em detalhes intermediários e avançados e SQL (Structured Query Language), exceto o mostrado em alguns exemplos. Instruções sobre instalação e execução de scripts em Java Server Pages e Servlets também não serão mostrados no tutorial, estando disponíveis em documentos separados (Santos, 2004). O tutorial foi escrito para ser o mais prático possível, significando que em vários pontos simplificações foram feitas. Assume-se que o leitor tenha conhecimentos básicos de uma linguagem de programação estruturada ou orientada a objetos moderna, como Pascal, C, C++ ou Java. Este tutorial está dividido nas seguintes seções: HTML básico e interação entre páginas, onde veremos os elementos de marcação mais simples de HTML e como funciona a interação cliente-servidor entre um navegador e um servidor HTTP; Introdução à linguagem Java, onde veremos conceitos básicos de programação em Java que serão úteis para compreensão dos outros tópicos; Escrevendo scripts em Java Server Pages, onde veremos exemplos simples de expressões em JSP e scriptlets, incluindo alguns exemplos simples e completos; Escrevendo Servlets, onde veremos como escrever classes completas em Java capazes de responder a pedidos feitos por clientes na WWW. HTML BÁSICO E INTERAÇÃO ENTRE PÁGINAS

Upload: phungthien

Post on 31-Aug-2018

214 views

Category:

Documents


0 download

TRANSCRIPT

IV Congresso Brasileiro de Computação CBComp 2004 Brasil

Introdução à Programação com Java Server Pages e Servlets

Rafael Santos Instituto Brasileiro de Tecnologia Avançada – IBTA Unidade São José dos Campos 12242-431 Brasil [email protected]

RESUMO R. Santos. 2004. Introdução à Programação com Java Server Pages e Servlets. Congresso Brasileiro de Ciência da Computação, Itajaí, 2004, 849 – 872. Itajaí, SC – Brasil, ISSN 1677-2822

Uma das áreas de desenvolvimento de sistemas que apresentou maior crescimento nos últimos anos é a de desenvolvimento de sistemas cliente-servidor onde o cliente é um navegador e todo o processamento é feito no servidor. Estes sistemas usam a Internet ou intranets para transmissão das informações entre cliente e servidor. O processamento das informações neste tipo de sistema é feito na maioria dos casos exclusivamente do lado do servidor, que recebe informações do usuário através do navegador, as processa e retorna ao usuário através de páginas em HTML geradas pelo próprio sistema.

O objetivo deste mini-curso é apresentar os conceitos básicos de Java Server Pages e servlets para o desenvolvimento de aplicações cliente-servidor. O curso supõe que o estudante conhece alguma linguagem de programação (conceitos de lógica, subrotinas e funções, parâmetros, etc.) e tenha experiência básica no desenvolvimento para a Internet (conhecimentos básicos de como a Internet e navegadores funcionam).

PALAVRAS DE INDEXAÇÃO ADICIONAIS: Programação cliente-servidor, Java 2 Enterprise Edition

INTRODUÇÃO Sistemas computacionais onde o cliente é um navegador e o

servidor executa aplicações enviando e recebendo dados para este cliente são muito comuns, em especial na Internet. As vantagens de um sistema cliente-servidor deste tipo são várias: clientes podem acessar o sistema de qualquer computador com acesso à Internet (e com permissões adicionais, se for necessário); não existe dificuldade em fazer modificações no sistema, uma vez que não é necessário redistribuir aplicações clientes; clientes são em grande maioria independentes de alguns requisitos como sistemas operacionais específicos ou softwares adicionais ou mesmo de performance de processador. A desvantagem óbvia deste tipo de sistemas é a dependência do funcionamento com performance adequada da comunicação entre o cliente e o servidor para o funcionamento do sistema.

A execução do processamento de dados destes sistemas é feita quase exclusivamente do lado do servidor, uma vez que o cliente (navegador) só é responsável pela apresentação dos formulários de entrada de dados e saída formatada dos mesmos. Existem várias alternativas para programação do lado do servidor onde o cliente é um navegador, sendo que as mais usadas e conhecidas são ASP, PHP e Java Server Pages / Servlets.

As vantagens de Java Server Pages (JSP) e servlets sobre as alternativas são o uso da linguagem Java como base, evitando que o programador tenha que aprender um padrão de linguagem para cliente e outro para servidor; e possivelmente ainda outro para desenvolvimento de aplicações no desktop.

Este tutorial apresenta os conceitos básicos de programação de Java Server Pages e servlets, mostrando os conceitos básicos de programação cliente-servidor com navegadores como clientes, e usando vários exemplos simples de ambas as tecnologias.

O tutorial foi escrito com a intenção de ser uma introdução às tecnologias JSP e servlets, não cobrindo muitos aspectos

intermediários e avançados da plataforma J2EE (Java 2 Enterprise Edition). Neste tutorial também não veremos alguns conceitos que são interessantes para o desenvolvimento de sistemas comerciais complexos e atrativos, como, por exemplo, HTML (Hypertext Markup Language) intermediário e avançado, programação em Java e orientação a objetos em detalhes intermediários e avançados e SQL (Structured Query Language), exceto o mostrado em alguns exemplos. Instruções sobre instalação e execução de scripts em Java Server Pages e Servlets também não serão mostrados no tutorial, estando disponíveis em documentos separados (Santos, 2004).

O tutorial foi escrito para ser o mais prático possível, significando que em vários pontos simplificações foram feitas. Assume-se que o leitor tenha conhecimentos básicos de uma linguagem de programação estruturada ou orientada a objetos moderna, como Pascal, C, C++ ou Java.

Este tutorial está dividido nas seguintes seções: • HTML básico e interação entre páginas, onde veremos

os elementos de marcação mais simples de HTML e como funciona a interação cliente-servidor entre um navegador e um servidor HTTP;

• Introdução à linguagem Java, onde veremos conceitos básicos de programação em Java que serão úteis para compreensão dos outros tópicos;

• Escrevendo scripts em Java Server Pages, onde veremos exemplos simples de expressões em JSP e scriptlets, incluindo alguns exemplos simples e completos;

• Escrevendo Servlets, onde veremos como escrever classes completas em Java capazes de responder a pedidos feitos por clientes na WWW.

HTML BÁSICO E INTERAÇÃO ENTRE PÁGINAS

850 Santos

Introdução HTML (Hypertext Markup Language) é uma linguagem de

marcação de textos para que estes sejam mostrados em um navegador de forma específica – este processo também é conhecido como renderização. Documentos em HTML são de texto puro, isto é, podem ser editados em qualquer editor que permita a gravação em formato ASCII ou texto.

HTML não é uma linguagem de programação – seus “comandos” servem somente para formatar texto, e são conhecidos como tags. Existem muitas ferramentas de autoria de documentos HTML, inclusive algumas embutidas nos próprios navegadores, que permitem a criação de documentos de forma puramente visual, mas é importante que o programador de sistemas em JSP ou servlets conheça as tags, pois sua aplicação é que irá escrever os documentos que serão enviados ao navegador.

Nesta seção veremos algumas das tags mais básicas ou representativas de HTML e o resultado do processamento e formatação de documentos usando estas tags por navegadores.

Tags e formatação Tags em HTML definem a estrutura e aparência do documento.

O formato básico de uma tag é <TAG>, ou seja, o nome da tag entre os sinais de menor e maior. Muitas tags modificam o comportamento ou aparência de um trecho do documento, então são compostas de pares, onde uma tag deve ser colocada no início do trecho a ser alterado e a outra no fim, usando o formato <TAG>Trecho</TAG>. Note que a tag final tem uma barra entre o sinal de menor e o nome da tag.

Algumas tags também podem ter argumentos ou parâmetros, usando o formato <TAG PARAM1=VALOR1 PARAM2=VALOR2 ...>, onde parâmetros e seus valores são incluídos entre os sinais de menor e maior.

Nomes e parâmetros de tags, em sua maioria, podem ser escritos indistintamente em maiúsculas ou minúsculas. Tags podem ser combinadas para mostrar efeitos acumulados. Se isso for feito, os pares de tags tem que ser escritos de forma concêntrica, isto é, fechando primeiro as tags abertas por último, como <tag1><tag2>texto</tag2></tag1>.

Organização básica do documento Um documento em HTML pode ser declarado com um conjunto

mínimo de tags, apresentado a seguir. Este documento, embora não esteja completo e não tenha conteúdo, pode ser usado como template ou base para a criação de outros documentos. Esta template é mostrada na Figura 1.

<HTML> <HEAD> <TITLE> Título da Página </TITLE> </HEAD> <BODY> Conteúdo da Página </BODY> </HTML>

Figura 1 – Template para um documento HTML simples.

Podemos ver no documento da Figura 1 as tags que definem o documento HTML (<HTML>), as que identificam o cabeçalho (<HEAD>) e corpo (<BODY>) do documento, e dentro do cabeçalho, as que identificam o título da página (<TITLE>).

As tags na Figura 1 são mostradas formatadas (indentadas) para esclarecer as relações de hierarquia entre elas, mas para o

navegador esta formatação é irrelevante – todo o texto mostrado na Figura 1 poderia estar em uma única linha que o navegador o processaria e exibiria da mesma forma.

Entre as tags <TITLE> e <BODY> alguns trechos de texto que não são tags estão escritos, estes trechos serão usados como conteúdo da página. A página da Figura 1 foi processada pelo navegador Mozilla, e o resultado é mostrado na Figura 2.

Figura 2 – Template processada pelo navegador Mozilla.

Em outros exemplos desta seção, para manter as listagens breves, somente o conteúdo entre as tags <BODY> e </BODY> serão mostrados.

Formatação de texto Vejamos algumas das tags mais básicas usadas para formatar

texto. Trechos de texto podem ser exibidos em negrito se estiverem entre os pares de tags <b> e </b>. Texto entre <i> e </i> será mostrado em itálico, texto entre as tags <u> e </u> sublinhado e texto entre as tags <tt> e </tt> será mostrado em fonte proporcional. A Figura 3 mostra um exemplo de uso destas tags.

<BODY> Texto em <b>negrito</b>, texto em <i>itálico</i>, Texto <u>sublinhado</u>, <tt>proporcional</tt> e <b><i>combinações</i></b>. </BODY>

Figura 3 – Código HTML com tags de formatação de texto.

A Figura 4 mostra o resultado da formatação do código da Figura 3.

Figura 4 – Resultado da formatação do código da Figura 3.

Podemos ver que o documento mostrado na Figura 4 não contém quebras de linhas – estas devem ser inseridas no documento HTML com as tags <br> para quebra de linhas e <p> para inserção de parágrafos.

A cor do texto e seu tamanho relativo para exibição podem ser controlados usando o par de tags <FONT> e </FONT>. A tag <FONT> pode conter os argumentos COLOR e SIZE, onde para COLOR devemos adicionar o nome de uma cor ou sua representação em hexadecimal (com #FF0000 sendo vermelho e #008080 sendo ciano escuro, por exemplo).

Para o argumento SIZE devemos adicionar o tamanho relativo da fonte (precedido do sinal de mais para aumentar a fonte ou de menos para diminuí-la). A Figura 5 mostra trecho de código em

850

851Introdução à Programação com Java Server Pages e Servlets

HTML para modificar cores e tamanhos relativos de fontes, e a Figura 6 mostra o resultado da exibição pelo navegador.

<BODY> <FONT COLOR="red" SIZE=+1> Importante !</FONT><br> <FONT COLOR="#0000FF"> Este texto está em azul.</FONT> </BODY>

Figura 5 – Código HTML com tags para modificação das fontes.

Figura 6 – Resultado da formatação do código da Figura 5.

Outras tags para formatação de texto permitem a criação de cabeçalhos de seção. Os textos destes cabeçalhos aparecem com uma fonte diferenciada e com quebra de parágrafos antes e depois. Alguns exemplos são mostrados na Figura 7 e seu resultado na Figura 8.

<BODY> <H1>Cabeçalho 1</H1> <H2>Cabeçalho 2</H2> <H3>Cabeçalho 3</H3> </BODY>

Figura 7 – Código HTML com tags para cabeçalhos.

Figura 8 – Resultado da formatação do código da Figura 7.

Imagens e outros elementos gráficos Imagens podem ser inseridas no documento usando a tag

<IMG>. Esta tag deve conter o parâmetro obrigatório SRC que indica a URL (Uniform Resource Locator) de uma imagem que será incluída no documento. Esta URL pode ser uma localização na Internet ou o nome de um arquivo local. Um dos parâmetros que esta tag pode usar é o ALIGN, que indica o alinhamento da figura com o texto que a contém, podendo receber os valores TOP, MIDDLE e BOTTOM (entre outros). Outro parâmetro opcional é o ALT, que recebe como argumento um texto descritivo da imagem, para exibição em navegadores sem suporte a imagens.

Alguns exemplos de uso da tag <IMG> com diferentes alinhamentos são mostrados na Figura 9, e sua exibição por um navegador é mostrado na Figura 10.

<BODY>

<IMG ALIGN=TOP SRC="imagem.png"> Superior<P> <IMG ALIGN=MIDDLE SRC="imagem.png"> Meio<P> <IMG ALIGN=BOTTOM SRC="imagem.png"> Inferior<P> </BODY>

Figura 9 – Código HTML com tags para inclusão de imagens.

Figura 10 – Resultado da formatação do código da Figura 9.

Outro elemento gráfico interessante é criado usando-se a tag <HR>, que cria uma linha horizontal no documento.

Listas Listas podem ser construídas com o par de elementos <ul> e

</ul> (listas não-ordenadas ou bullet lists) ou <ol> e </ol> (listas ordenadas ou numeradas). Elementos da lista são indicados com a tag <li>. Listas podem ser colocadas dentro de listas se as convenções corretas forem seguidas. Um exemplo de código HTML para formatação de listas é mostrado na Figura 11 e o resultado visto em um navegador na Figura 12.

<BODY> Livros que estou lendo: <OL> <LI>A Gamut of Games <LI>Fuzzy Algorithms <LI>HTML 4 Unleashed </OL> Objetos sobre a minha mesa: <UL> <LI>Jogo <I>Torres de Hanói</I> <LI>Pilha de CDs do Depeche Mode </UL> Coisas que tenho que fazer: <OL> <LI>Arrumar os CDs <LI>Organizar os livros <UL> <LI>Separar os que vou ler em breve <LI>Guardar os que li há pouco tempo </UL> <LI>Jogar fora velhos documentos </OL> </BODY>

Figura 11 – Código HTML com tags para formatação de listas.

851

852 Santos

Figura 12 – Resultado da formatação do código da Figura 11.

Links Além de servir para formatar textos para apresentação em

navegadores, HTML permite a ligação entre documentos usando o conceito de hipertexto: um pequeno trecho de um documento em HTML (chamado link) pode ser associado a outro documento de forma que se o usuário clicar no trecho marcado, será levado ao outro documento. Este outro documento pode estar localizado no mesmo servidor ou em qualquer outro servidor na Internet.

A ligação entre documentos é feita usando-se a tag <A>, que recebe como argumento HREF seguido do endereço do documento para ligação. O trecho do documento entre as tags <A> e </A> será mostrado de forma diferenciada, e se o usuário clicar neste trecho com o botão do mouse ele será levado ao documento de ligação. Também é possível usar uma imagem como link, bastando usar a tag <IMG> entre as tags <A> e </A>.

A listagem na Figura 13 mostra dois links, um para um documento externo e outro para um documento no mesmo servidor, o primeiro usando texto para mostrar o link e o segundo usando uma imagem. A Figura 14 mostra o resultado como visto em um navegador.

<BODY> Clique <A HREF="http://java.sun.com">aqui</A> para mais informações sobre Java.<p> <A HREF="index.html"> <IMG SRC="index.png"></A> </BODY>

Figura 13 – Código HTML com tags para ligação entre documentos (hyperlinks).

Figura 14 – Resultado da formatação do código da Figura 13.

Tabelas Uma forma atraente de se organizar informações em um

documento HTML é usando tabelas, que são divididas em linhas que por sua vez são divididas em células. Tabelas podem ser bastante complexas, mas seguem um padrão de codificação relativamente simples: uma tabela deve ser escrita entre as tags <TABLE> e </TABLE>, cada uma de suas linhas deve estar entre as tags <TR> e </TR> e cada uma de suas células entre as tags <TD> e </TD>. Adicionalmente, é possível marcar algumas células como sendo cabeçalhos da tabela usando as tags <TH> e </TH>. Para exemplificar a descrição de uma tabela simples, consideremos a mostrada na Figura 15, cujo resultado em um navegador é mostrado na Figura 16.

<BODY> <TABLE> <TR> <TH>Nome</TH><TH>Tamanho</TH> </TR> <TR> <TD>texture2.png</TD><TD>1456142</TD> </TR> <TR> <TD>pattern.tif</TD><TD>202872</TD> </TR> <TR> <TD>9bands.tif</TD><TD>32237182</TD> </TR> </TABLE> </BODY>

Figura 15 – Código HTML com tags para a formatação de uma tabela simples.

Figura 16 – Resultado da formatação do código da Figura 15.

Tabelas podem ser formatadas de forma mais complexa usando argumentos para as tags <TABLE>, <TR> e <TD>. Para a tag <TABLE>, podemos usar os argumentos BORDER que indica a espessura da borda; CELLSPACING que define o tamanho do espaço entre células; CELLPADDING que define o tamanho do espaço entre as bordas das células e o conteúdo das mesmas e WIDTH, que pode receber um valor para determinar o percentual da área do navegador ocupada pela largura da tabela.

Alguns dos argumentos que podem ser usados para a tag <TR> são ALIGN, que pode ser igual a LEFT, CENTER ou RIGHT, e

852

853Introdução à Programação com Java Server Pages e Servlets

que alinhará o conteúdo de todas as células daquela linha à esquerda, centro ou direita, respectivamente; VALIGN, que pode ser igual a TOP, MIDDLE e BOTTOM, e que alinhará verticalmente o conteúdo das células naquela linha para a parte de cima, meio ou parte de baixo da célula, respectivamente; e BGCOLOR, que recebe um nome de cor ou cor especificada em hexadecimal e determinará a cor de fundo das células daquela linha. Para as tags <TD> podemos usar os mesmos argumentos usados para as tags <TR>, exceto que a alteração será somente para a célula e não para a linha. Para as tags <TD> e <TH> podemos usar o argumento COLSPAN que indica que a célula pode se espalhar por mais de uma coluna.

Além dos argumentos mencionados, é possível adicionar uma legenda à tabela usando as tags <CAPTION> e </CAPTION>.

Os conteúdos das células, entre <TD> e </TD> ou <TH> e </TH>, também podem ser formatados com outras tags de HTML.

O exemplo mostrado na Figura 17 demonstra a formatação de uma tabela mais complexa. O resultado, como visto por um navegador, é mostrado na Figura 18.

<BODY> <TABLE BORDER=1 CELLPADDING=5 WIDTH=100%> <CAPTION> Lista de arquivos para <I>download</I> </CAPTION> <TR BGCOLOR="#E0E0E0"> <TH>Nome</TH><TH COLSPAN=2>Tamanho</TH> </TR> <TR> <TD> <A HREF="texture2.png">texture2.png</A> </TD> <TD ALIGN=RIGHT><TT>1456142B</TT></TD> <TD ALIGN=RIGHT><TT>1.39M</TT></TD> </TR> <TR> <TD> <A HREF="pattern.tif">pattern.tif</A> </TD> <TD ALIGN=RIGHT><TT>202872B</TT></TD> <TD ALIGN=RIGHT><TT>0.19M</TT></TD> </TR> <TR> <TD> <A HREF="9bands.tif">9bands.tif</A> </TD> <TD ALIGN=RIGHT><TT>32237182B</TT></TD> <TD ALIGN=RIGHT><TT>30.74M</TT></TD> </TR> </TABLE> </BODY>

Figura 17 – Código HTML com tags para formatação de uma tabela mais complexa.

Figura 18 – Resultado da formatação do código da Figura 17.

Formulários e Interação entre Cliente e Servidor As tags mais importantes, para as finalidades deste curso, são as

que permitem a criação de formulários em HTML. Estes formulários podem ser usados para a coleta de dados, e enviados para uma aplicação em um servidor que os processará.

As tags que definem um formulário são, apropriadamente, <FORM> e </FORM>. A tag <FORM> aceita vários parâmetros, sendo que os mais importantes são ACTION, que especifica a URL de uma aplicação que irá receber os dados que serão submetidos, e METHOD, que define a maneira com que estes dados serão enviados, podendo ser igual a GET ou POST. A diferença principal entre os métodos GET e POST, para fins práticos, é que o método GET anexa os dados do formulário à URL da aplicação, e POST envia os dados para o servidor separadamente. É sempre preferível usar o método POST.

As tags de HTML permitem a criação de formulários com diversos controles de interfaces para usuários. A maioria destes controles é criada com a tag <INPUT> com argumentos que definem o tipo de controle, valor default, etc. Veremos alguns destes controles em exemplos nesta seção.

Dois dos controles mais usados são para entrada de texto e envio do formulário. Podem ser criados com os argumentos TYPE=”TEXT” e TYPE=”SUBMIT”, respectivamente, para a tag <INPUT>. Controles de entrada de texto devem ter um parâmetro adicional chamado NAME que indica qual o nome do campo de texto, e podem ter um campo adicional chamado SIZE que indica o número de caracteres visíveis simultaneamente no campo de texto. O controle de envio de formulário pode ter um argumento opcional chamado VALUE que indica o texto que deve aparecer no botão de envio do formulário.

A listagem na Figura 19 demonstra a criação de um formulário simples com um campo de texto.

<BODY> <FORM ACTION = "http://www.abc.br/processa.jsp" METHOD=POST> Nome: <INPUT TYPE="TEXT" NAME="NOME" SIZE="20"> <INPUT TYPE="SUBMIT" VALUE="Enviar"> </FORM> </BODY>

Figura 19 – Código HTML com tags para criação de um formulário simples.

Na listagem da Figura 19 temos, além do campo de texto, um botão de envio de dados que, ao ser clicado, enviará o conteúdo do campo de texto associado ao nome da campo NOME para a

853

854 Santos

aplicação cuja URL é http://www.abc.br/processa.jsp. A aparência do formulário como vista em um navegador é mostrada na Figura 20.

Figura 20 – Resultado da formatação do código da Figura 19.

Existem opções para a tag <INPUT> para marcar outros tipos de campos de texto: a opção TYPE=”PASSWORD” funciona como a opção TYPE=”TEXT”, mas mostrando asteriscos (“*”) ao invés de texto quando algo for digitado no campo correspondente. As opções para este tipo de controle são as mesmas de para o tipo texto.

Existe também um par de tags que cria uma área de texto com mais de uma linha de altura: as tags <TEXTAREA> e </TEXTAREA>. O tamanho da área de texto pode ser passado como argumento para a tag inicial, usando COLS para indicar o número de colunas e ROWS para indicar o número de linhas.

Um exemplo de formulário mais complexo usando estas tags pode ser visto na Figura 21. Os campos são inseridos dentro de células de uma tabela, para forçar uma determinada aparência visual. O resultado, como visto por um navegador, é mostrado na Figura 22.

<BODY> <FORM ACTION = "http://www.abc.br/processa.jsp" METHOD=POST> <TABLE> <TR> <TD>Nome:</TD> <TD> <INPUT TYPE="TEXT" NAME="NOME" SIZE="20"> </TD> </TR> <TR> <TD>Senha:</TD> <TD><INPUT TYPE="PASSWORD" NAME="SENHA" SIZE="20"><TD> </TR> <TR> <TD COLSPAN=2 ALIGN=CENTER> <TEXTAREA COLS="20" ROWS="5"> Entre texto aqui. </TEXTAREA> </TD> </TR> <TR> <TD COLSPAN=2 ALIGN=RIGHT> <INPUT TYPE="SUBMIT" VALUE="Enviar"> </TD> </TR> </TABLE> </FORM> </BODY>

Figura 21 – Código HTML com tags para criação de um formulário com vários campos de texto.

Figura 22 – Resultado da formatação do código da Figura 21.

Outros tipos de controles permitem a seleção de um valor entre vários ou marcação ou não de um controle: são os botões de rádio e checkboxes, respectivamente. Para criar um botão de rádio usamos a tag <INPUT> com o parâmetro TYPE=”RADIO”. Devemos usar dois parâmetros adicionais: um, NAME, indica qual é o nome associado a este botão de rádio, e o outro, VALUE, indica qual valor será passado para o servidor se este botão de rádio estiver marcado. Vários botões de rádio podem compartilhar o mesmo valor do argumento NAME, se isto acontecer, o navegador somente deixará um destes botões ser selecionado a cada momento (isto é, ao selecionar um dos botões com o mesmo NAME, os outros serão desmarcados).

Checkboxes são como botões de rádio individuais, podendo estar marcados ou não independentemente de outros. Checkboxes podem ser criados usando a tag <INPUT> com o parâmetro TYPE=”CHECKBOX” e usando o argumento NAME para indicar o nome da variável que será enviada ao servidor. Tanto checkboxes quanto botões de rádio podem receber um parâmetro adicional, CHECKED, que indica se o botão ou checkbox deve estar inicialmente selecionado.

Para exemplificar o uso de checkboxes e botões de rádio, consideremos o trecho de código na Figura 23.

<BODY> <FORM ACTION = "http://www.abc.br/processa.jsp" METHOD=POST> Seu pedido:<br> <INPUT TYPE="RADIO" NAME="PEDIDO" VALUE="FILE">Filé<br> <INPUT TYPE="RADIO" NAME="PEDIDO" VALUE="FRANGO" CHECKED>Frango<br> <INPUT TYPE="RADIO" NAME="PEDIDO" VALUE="PEIXE">Peixe<br> <INPUT TYPE="CHECKBOX" NAME="SALADA" CHECKED> Salada<br> <INPUT TYPE="CHECKBOX" NAME="ARROZ"> Arroz<br> <INPUT TYPE="CHECKBOX" NAME="BATATAS"> Batatas<br> <INPUT TYPE="SUBMIT" VALUE="Enviar"> </FORM> </BODY>

Figura 23 – Código HTML com tags para criação de um formulário com checkboxes e botões de rádio.

854

855Introdução à Programação com Java Server Pages e Servlets

Figura 24 – Resultado da formatação do código da Figura 23.

Outro componente de interface gráfica que permite que o usuário selecione um de vários valores possíveis é o criado pelas tags <SELECT> e </SELECT>. Entre estas tags podemos escrever várias opções, denotadas por <OPTION> e </OPTION>. Este componente mostrará uma lista ou menu ativado por botão no navegador. A tag <SELECT> deve ter um nome que identifique o dado que será enviado ao servidor, este nome é especificado usando-se o argumento NAME. Outro argumento que pode ser usado para <SELECT> é o SIZE, que indica o número de opções a ser mostrado simultaneamente.

As tags <OPTION> podem receber opcionalmente o argumento VALUE que indica qual valor será enviado associado ao nome passado para a tag <SELECT>. Se este argumento VALUE não for passado, o texto escrito entre <OPTION> e </OPTION> será usado.

Um exemplo de formulário que usa a tag <SELECT> é mostrado na Figura 25. Este formulário, visto por um navegador, é mostrado na Figura 26.

<BODY> <FORM ACTION="http://www.abc.br/processa.jsp" METHOD="POST"> <SELECT NAME="PEDIDO" SIZE=3> <OPTION VALUE="FF"> Filé com fritas</OPTION> <OPTION VALUE="FC"> Frango com creme de milho</OPTION> <OPTION VALUE="PA"> Peixe com alcaparras</OPTION> <OPTION VALUE="BB"> Buchada de bode com jiló</OPTION> </SELECT><BR> Bebida: <SELECT NAME="BEBIDA"> <OPTION>Vinho</OPTION> <OPTION>Refrigerante</OPTION> <OPTION>Água</OPTION> </SELECT><BR> <INPUT TYPE="SUBMIT" VALUE="Enviar"> </FORM> </BODY>

Figura 25 – Código HTML com tags para criação de um formulário com seletores de opção.

Figura 26 – Resultado da formatação do código da Figura 25.

Duas outras tags para criação de formulários merecem atenção: a tag <INPUT> com TYPE=”RESET” cria um botão, semelhante ao criado com TYPE=”SUBMIT”, mas que ao ser clicado irá retornar o formulário ao seu estado original, isto é, desfazendo todas as seleções e entradas feitas por um usuário. Esta tag também pode receber o argumento VALUE, que indica o texto que deverá aparecer no botão.

Outra tag interessante para o desenvolvimento de aplicações é a tag <INPUT> com TYPE=”HIDDEN”. Esta tag aceita dois parâmetros adicionais, NAME e VALUE, e possibilita o envio da variável cujo nome é NAME e valor VALUE para o servidor. Esta tag não cria nenhum elemento gráfico correspondente na interface com o usuário, e pode ser usada para enviar valores de forma invisível para o usuário.

Mais informações sobre HTML Existem muitas outras tags que podem ser usadas para criar

interfaces com o usuário em HTML, mas não é a intenção deste tutorial apresentá-las: vimos somente as básicas, que permitem a criação de interfaces minimamente úteis e interessantes.

Mais informações sobre HTML podem ser obtidas nas referências (Darnell, 1998) e (Hall, 1998).

INTRODUÇÃO À LINGUAGEM JAVA

Introdução Nesta seção veremos os conceitos mínimos da linguagem Java

que possibilitarão a criação de scripts em JSP e servlets. Java é uma linguagem com uma ampla API (Application Programming Interface, ou conjunto de funções prontas para uso), que não serão cobertas por causa do escopo do tutorial, então veremos somente conceitos básicos aplicáveis ao tutorial. Mais informações sobre a linguagem Java podem ser vistas em (Santos, 2003) ou (Horstmann et. al., 2001).

Conceitos fundamentais Java é uma linguagem orientada a objetos: considerando

modelos do que queremos processar, criamos classes que representam estes modelos em Java (contendo campos para representar os dados do modelo e métodos para processar informações do modelo) e a partir daí podemos criar objetos ou instâncias destas classes.

Um exemplo de classe que representa os dados de um aluno matriculado em algumas disciplinas em um curso qualquer pode ser vista na Figura 27. Além da lista de disciplinas nas quais o aluno está matriculado, a classe também representa o nome do aluno e armazena uma flag indicando se o aluno é bolsista ou não.

855

856 Santos

import java.util.Vector; public class Aluno { os com informações sobre o aluno. // Camp private String nome; private boolean éBolsista; private Vector disciplinas; // lista // Construtor da classe. public Aluno(String n) { nome = n; disciplinas = new Vector(); } o ara indicar se o é bolsista. // Mét do p o alun public void setÉBolsista(boolean bolsista) { éBolsista = bolsista; } // Método que calcula a mensalidade. public double calcMensalidade() { double mens = disciplinas.size()*125; if (éBolsista) mens = mens * 0.75; return mens; } // Método que efetua a matrícula em uma // disciplina. public void matricula(String disc) { disciplinas.add(disc); } // Método que imprime os dados do aluno. public void imprime() { System.out.print("O aluno "+nome); System.out.println(" está matriculado em:"); for(int d=0;d<disciplinas.size();d++) System.out.println(disciplinas.get(d)); System.out.println("Sua mensalidade é "+ calcMensalidade()); } }

Figura 27 – A classe Aluno.

Algumas observações interessantes sobre a classe Aluno (Figura 27) estão listadas a seguir:

• Os campos da classe, listados logo no seu início, são privados, significando que não podem ser acessados ou modificados de fora da classe. Um campo do tipo String (ou, mais corretamente, uma instância da classe String) permite o armazenamento de cadeias de caracteres de tamanho indeterminado, o tipo boolean permite o armazenamento de um valor booleano (que só pode assumir os valores true ou false) e a instância da classe Vector permite que armazenemos uma lista de tamanho indeterminado de qualquer tipo de objetos.

• O construtor da classe (método que tem o mesmo nome da classe, mas não tem tipo de retorno) recebe como argumento um nome para inicializar o nome do aluno e cria o Vector para armazenar a lista de disciplinas.

• O método setÉBolsista recebe um argumento do tipo boolean para inicializar o campo éBolsista e não

retorna nenhuma informação (void). Este tipo de método é chamado genericamente de set pois permite a modificação de um campo privado por outra classe. De forma similar podemos ter em uma classe métodos do tipo get que retornam os valores de campos da classe.

• O método calcMensalidade calcula e retorna a mensalidade do aluno, usando como dados o número de disciplinas no qual o aluno está matriculado e verificando se o aluno é bolsista para aplicação de um desconto.

• O método matricula recebe um nome de disciplina e insere este nome na lista de disciplinas nas quais o aluno está matriculado.

• O método imprime exibe no console ou terminal os dados deste aluno, incluindo a lista de disciplinas nas quais está matriculado e a mensalidade calculada para o mesmo.

É interessante notar que esta classe não é uma aplicação, ela somente representa (de forma simplificada) informações e algoritmos relativos a um aluno para fins de matrícula em um curso. O que define uma aplicação em Java é a existência de um método main, que será o ponto de entrada da aplicação. Uma classe que contém este método main é mostrada na Figura 28.

public class TestAluno { // Método que permite a execução de uma classe // como uma aplicação. public static void main(String[] args) { Aluno joão = new Aluno("João Exemplar"); joão.matricula("Progr. Orient. a Objetos I"); joão.matricula("Inglês Técnico II"); joão.matricula("Lógica de Programação"); joão.imprime(); } }

Figura 28 – Uma aplicação em Java.

A aplicação mostrada na Figura 28, ao ser executada, mostraria no console a saída mostrada na Figura 29.

O aluno João Exemplar está matriculado em: Progr. Orient. a Objetos I Inglês Técnico II Lógica de Programação Sua mensalidade é 375.0

Figura 29 – Resultado da execução da aplicação da Figura 28.

Para que aplicações funcionem corretamente, o método main deve ser definido como public static, ter o tipo de retorno void e receber como argumento um array de instâncias da classe String.

Herança Um tópico sobre a linguagem Java que deve ser apresentado

para melhor compreensão do funcionamento das páginas em Java Server Pages e servlets é uma introdução ao mecanismo de herança de classes. Basicamente, este mecanismo permite que criemos classes a partir de outras já existentes, possibilitando o reuso: métodos públicos de classes existentes são herdados para a nova classe, e se forem aproveitáveis, não precisarão ser reescritos.

Para exemplificar o conceito de herança, vamos usar a classe Aluno, mostrada na Figura 27, como base para uma classe AlunoPG, que representará um aluno matriculado em um curso de pós-graduação. Consideraremos que para representar as

856

857Introdução à Programação com Java Server Pages e Servlets

informações sobre um aluno de pós-graduação devemos usar as mesmas informações de um aluno de graduação mais o nome do orientador. A classe AlunoPG, que representa um aluno de pós-graduação, é mostrada na Figura 30.

public class AlunoPG extends Aluno { private String orientador; // Construtor da classe. public AlunoPG(String n,String o) { super(n); orientador = o; } // Mét do qo ue imprime os dados do aluno. public void imprime() { super.imprime(); System.out.println("Seu orientador é "+ orientador); } }

Figura 30 – A classe AlunoPG.

Podemos ver na listagem da Figura 30 que a classe AlunoPG somente declara dois métodos: o construtor e o método imprime. O construtor, ao ser executado, chamará por sua vez o construtor da classe ancestral (usando a palavra-chave super) e depois inicializará o campo orientador.

O método imprime faz coisa similar, executando o método imprime da classe ancestral e depois imprimindo o nome do orientador. Todos os outros métodos da classe Aluno (matricula, calcMensalidade, etc.) são herdados e podem ser usados pelas instâncias da classe AlunoPG.

É interessante notar que instâncias da classe AlunoPG poderão ser consideradas como um tipo especial de instâncias da classe Aluno, o que pode ser útil em aplicações.

Exceções Exceções são erros ou comportamentos inesperados que podem

ocorrer em determinados trechos de código em Java. Alguns exemplos de exceção são tentativas de conversão de strings para inteiros onde as strings não podem ser convertidas, tentativas de acesso a arquivos que não existem, etc.

Uma das maneiras usada por classes e aplicações em Java para processar exceções é cercar o trecho de código onde a exceção pode ocorrer com um bloco try (a palavra-chave try seguida do bloco de comandos que podem causar exceções), seguida por um ou mais blocos catch que capturam as exceções que podem ocorrer.

Um exemplo de exceção em potencial é mostrado no código da Figura 31. Nesta aplicação tentamos converter uma string (que será entrada através do método showInputDialog da classe JOptionPane) para um valor inteiro usando o método parseInt da classe Integer.

import javax.swing.JOptionPane; public class Excecoes { public static void main(String[] args) { String temp =

JOptionPane.showInputDialog("Valor:"); int valor = Integer.parseInt(temp); } }

Figura 31 – Aplicação am Java onde uma exceção pode ocorrer.

Se a string contiver caracteres que podem ser convertidos para um valor inteiro, a aplicação será executada sem problemas, mas se algum valor que não puder ser convertido for entrado, a execução da classe será interrompida e uma mensagem sobre a exceção NumberFormatException será exibida.

Podemos evitar a exibição desta mensagem tomando providências para que se a conversão for impossível, um valor default seja usado. Para isso podemos usar os blocos try/catch, tentando executar a conversão no bloco try e, caso uma exceção ocorra, usando outro valor no bloco catch. Esta abordagem é mostrada na aplicação listada na Figura 32.

import javax.swing.JOptionPane; public class Excecoes { public static void main(String[] args) { String temp = JOptionPane.showInputDialog("Valor."); int valor; // Tentamos converter a string para // inteiro... try { valor = Integer.parseInt(temp); } // Se ocorrer uma exceção de formato de // números, consideramos o valor como // sendo igual a zero. catch (NumberFormatException e) { valor = 0; } } }

Figura 32 – Aplicação em Java que usa um bloco try/catch para processar exceções.

Existem exceções que não precisam ser processadas pelos métodos que contém código que as possa causar, NumberFormatException é uma destas. Outras exceções devem ser obrigatoriamente processadas: ou devemos colocá-las em um bloco try com um bloco catch correspondente ou devemos indicar que as exceções podem ocorrer quando declararmos o método que contém o código que pode causar exceções. Esta declaração é feita colocando-se, depois da declaração do método, a palavra-chave throws e os nomes das classes de exceções correspondentes.

Embora os exemplos mostrados nesta seção sejam simples (e de certa forma, incompletos) eles servem para exemplificar a criação de classes e objetos em Java e serão usados como base para exemplos mais complexos em seções seguintes.

ESCREVENDO SCRIPTS EM JAVA SERVER PAGES

Introdução Um script em Java Server Pages (JSP) é uma documento com

estrutura bem parecida com a de HTML, mas que contém tags

857

858 Santos

especiais que permitem a inclusão de código em Java (com algumas diferenças) que serão executados quando aquela página for carregada por um navegador. A execução será feita do lado do servidor, então o código em Java não será visto pelo cliente e terá acesso aos recursos instalados no servidor (bancos de dados, etc.) desde que devidamente configurados. Internamente, uma página em JSP será convertida dinamicamente para uma servlet, mas não entraremos em detalhes sobre o funcionamento deste mecanismo.

O código incluído nas páginas em JSP pode ser simples, desde a exibição de um valor obtido de alguma forma pelo servidor até ter algoritmos complexos de busca em bancos de dados e formatação de saída em HTML.

Nesta seção veremos inicialmente como funciona a interação entre páginas em HTML e aplicações do lado do servidor escritas em JSP. Veremos também como escrever scripts simples que não usam muitos conceitos de orientação a objetos para executar aplicações simples, e finalmente como usar classes criadas pelo usuário em aplicações escritas em JSP.

Interação entre páginas em HTML e scripts em JSP

A interação entre páginas em HTML e aplicações em um servidor funciona nas seguintes linhas gerais:

1. O cliente solicita uma página do servidor, que é enviada e exibida pelo navegador. Esta página pode ser estática (isto é, ser um arquivo já existente no servidor) ou dinâmica (gerada para o cliente no momento em que é solicitada).

2. Se a página tiver links que apontem para aplicações no servidor, e um dos links for clicado, o servidor irá executar a aplicação e retornar o conteúdo para o navegador, como no passo 1. Se a página conter um formulário cuja ação (parâmetro ACTION da tag <FORM>) seja uma aplicação no servidor a mesma será chamada e terá acesso à todas as variáveis definidas no formulário.

Não é necessário que as páginas e aplicações estejam em um mesmo servidor, é possível fazer um servidor enviar uma página cuja aplicação associada esteja em outro servidor e por assim em diante. Para finalidades deste tutorial, entretanto, consideraremos que todas as aplicações, páginas, etc. estão localizadas no mesmo servidor.

JSP Básico: Declarações e expressões Dois dos elementos mais simples de JSP são declarações e

expressões. Ambas podem ser incluídas em páginas JSP através de pares de tags especiais, <%! e %> no caso de declarações e <%= e %> no caso de expressões.

Nas declarações podemos definir variáveis e instâncias que serão usadas dentro da página em JSP; e nas expressões podemos incluir pequenas expressões em Java que serão executadas e convertidas para strings para inclusão na página que será enviada para o cliente.

Um exemplo bem simples de página em JSP que usa declarações e expressões pode ser visto Figura 33.

<BODY> <%! String parte1="Primeira "; %> <%= parte1+" página em "+parte2 %> <%! String parte2="JSP!"; %> </BODY>

Figura 33 – Primeiro exemplo de página em JSP.

O código mostrado na Figura 33 segue o mesmo padrão dos códigos em HTML mostrados anteriormente: somente o trecho entre as tags <BODY> e </BODY> são mostrados. Neste trecho de

código temos duas declarações, cada uma definindo uma instância da classe String, e uma expressão. É interessante observar que as variáveis ou instâncias declaradas dentro das tags de declaração são válidas por toda a página, independente da posição onde foram declaradas, embora seja interessante, para manter a legibilidade do código, que sejam feitas antes das expressões. Podemos ver também que o conteúdo de uma tag de expressão simplesmente declara o que deve ser exibido na página – no caso, o conteúdo da concatenação das declarações com mais algum texto. Como é de se esperar, o resultado desta página em JSP, quando mostrada em um navegador, mostra o texto “Primeira página em JSP!”.

Um exemplo ligeiramente mais complexo de uso de declarações e expressões pode ser visto no código da Figura 1Figura 34. Neste código temos a declaração de uma variável do tipo double e a exibição do resultado do cálculo de várias expressões matemáticas, organizadas em uma tabela. O resultado visual do código da Figura 34 pode ser visto na

<BODY> <%! double angulo = 3*Math.PI/4; %> <TABLE BORDER=1> <TR> <TH>Ângulo</TH> <TH ALIGN=RIGHT><%= angulo %></TH> </TR> <TR> <TD>Seno</TD> <TD ALIGN=RIGHT><%= Math.sin(angulo) %></TD> </TR> <TR> <TD>Coseno</TD> <TD ALIGN=RIGHT><%= Math.cos(angulo) %></TD> </TR> <TR> <TD>Tangente</TD> <TD ALIGN=RIGHT><%= Math.tan(angulo) %></TD> </TR> </TABLE> </BODY>

Figura 34 – Página em JSP mais complexa.

Figura 35 – Resultado da execução do código da Figura 34.

JSP Básico: Scriptlets e diretivas Até este momento criamos páginas com código que será

executado sempre da mesma forma – de certa forma estas páginas são tão estáticas quando páginas criadas usando somente HTML. Podemos declarar variáveis e avaliar e exibir expressões, mas não temos como inserir trechos de código nas páginas em JSP.

Para inserir estes trechos de código que dão um comportamento mais complexo às páginas, devemos usar um terceiro tipo de tag, que declara scriptlets, ou pequenos scripts em Java. Scriptlets devem estar entre as tags <% e %>, e serão processadas pelo servidor antes do envio para o cliente (os passos envolvem uma

858

859Introdução à Programação com Java Server Pages e Servlets

transformação da página JSP em uma servlet, mas não entraremos em detalhes sobre esta transformação).

Dentro de uma scriptlet podemos executar código mais complexo e que usa algumas instâncias de classes já definidas. Estas instâncias são listadas a seguir:

• request é uma instância da classe HTTPServletRe-quest que contém informações sobre o pedido que foi feito à aplicação no servidor. Através desta instância é possível recuperar informações sobre o servidor e sobre o cliente.

• response é uma instância de HTTPServletRes-ponse que contém métodos que permitem indicar como a resposta da execução do script será enviada para o cliente.

• session contém informações sobre a sessão, se existente (mais informações sobre sessões adiante).

• out permite o uso dos métodos print e println para fazer a saída de expressões para a página que será enviada ao cliente.

Um último tipo de tag define diretivas, que podem servir para inclusão de classes existentes ou arquivos externos no script em JSP, entre outras funções. Diretivas são criadas usando o par de tags <%@ e %>. A diretiva de importação de classes da API de Java tem a forma <%@ page import = ”” %>, onde os nomes das classes a ser importadas devem estar entre as aspas, separadas por vírgulas.

Um exemplo simples de scriptlet é mostrado na Figura 36. Neste exemplo, declaramos alguns arrays de strings, e imprimimos uma mensagem aleatória usando estes arrays e outro número aleatório. Ao final do script, usamos uma referência ao nome da página (criada com request.getRequestURL()) para criar um link para a própria página. Ao clicar neste link ou recarregar a página, o usuário verá uma mensagem aleatória diferente.

Um dos possíveis resultados da execução deste script pode ser visto na Figura 37.

<BODY> <% // Imprimimos algumas mensagens aleatórias. String[] cores = {"Verde","Azul","Vermelho", "Rosa Flamingo"}; String[] pedras = {"Ametista","Diamante", "Rubi","Granito"}; int random; out.print("Sua cor da sorte é <B>"); random = (int)(Math.random()*cores.length); out.print(cores[random]+"</B><P>"); out.print("Seu número da sorte é <B>"); random = 1000000000+ (int)(Math.random()*1000000000); out.print(random+"</B><P>"); out.print("Sua pedra da sorte é <B>"); random = (int)(Math.random()*pedras.length); out.print(pedras[random]+"</B>"); // Fazemos um link para a própria página. out.print("<HR>"); out.print("<A HREF=\""+request.getRequestURL()+ "\">"); out.print("De novo !</A>"); %> </BODY>

Figura 36 – Um exemplo de scriptlet.

Figura 37 – Resultado da execução do código da Figura 36.

Outro exemplo mais complexo de scriptlets é mostrado na Figura 38.

<BODY> <%@ page import = "java.util.*" %> <% // Criamos um HashSet com alguns nomes e // categorias de lutadores de sumô. HashMap sumo = new HashMap(); sumo.put("Dewanoumi","Sekiwake"); sumo.put("Futagoyama","Ozeki"); sumo.put("Isegahama","Ozeki"); sumo.put("Isenoumi","Sekiwake"); sumo.put("Kitanoumi","Yokozuna"); sumo.put("Musashigawa","Yokozuna"); sumo.put("Oshima","Ozeki"); sumo.put("Sadogatake","Yokozuna"); // Contadores para as categorias. int yokozuna = 0; int ozeki = 0; int sekiwake = 0; // Criamos uma tabela que mostra estas // categorias. %> <TABLE BORDER=1> <TR> <TH>Nome</TH> <TH>Categoria</TH> <TR> <% Object[] nomes = sumo.keySet().toArray(); for(int i=0;i< nomes.length;i++) { out.print("<TR>"); out.print("<TD>"); out.print(nomes[i]); out.print("</TD>"); String cor = "#000000"; String cat = (String)sumo.get(nomes[i]); if (cat.equals("Yokozuna")) { cor = "#C00000"; yokozuna++; } else if (cat.equals("Ozeki")) { cor = "#0000FF"; ozeki++; } else if (cat.equals("Sekiwake")) {

859

860 Santos

cor = "#00A030"; sekiwake++; } out.print("<TD>"); out.print("<FONT COLOR=\""+cor+"\">"); out.print(cat); out.print("</FONT></TD>"); out.print("</TR>"); } out.print("</TABLE>"); %> <UL> <LI>Yokozuna: <%= yokozuna %> <LI>Ozeki: <%= ozeki %> <LI>Sekiwake: <%= sekiwake %> </UL> </BODY>

Figura 38 – Outro exemplo de scriptlet.

Alguns pontos interessantes do script JSP da Figura 38 são: • Neste exemplo usamos a diretiva de importação de classes

para importar todas as classes do pacote java.util para poder usar a classe HashMap.

• Podemos notar que o scriptlet é dividido em partes: em determinado ponto, fechamos o scriptlet para exibir HTML puro e depois retomamos o scriptlet. Todas as variáveis declaradas anteriormente continuam podendo ser acessadas normalmente, esta técnica é interessante para evitar muitos comandos out.print para código HTML imutável no script JSP.

• Variáveis declaradas no escopo da scriptlet podem ser acessadas por expressões, como visto no final do script JSP.

O resultado da execução do script da Figura 38 é mostrado na Figura 39.

Figura 39 – Resultado da execução do código da Figura 38.

Pode ser argumentado que o scriptlet mostrado como exemplo é complexo demais e o seu resultado (mostrado na Figura 39) é tão

simples que poderia ser codificado na mão. No entanto, consideremos a manutenção da página: se for necessário incluir na mesma o nome e a categoria de mais alguns lutadores de sumô, basta incluir, na página em JSP, uma linha de código para cada, mas se a página fosse feita em HTML puro o desenvolvedor teria que tomar cuidados para usar a cor correta na tabela e atualizar o contador de categorias.

As páginas em JSP mostradas até agora não usam interação com o usuário, ou seja, não há maneira de elas se comportarem de forma diferente dependendo de alguma entrada do usuário. Para que isso ocorra, é necessário que o usuário preencha alguns dados em um formulário em HTML cuja ação será executada por um script em JSP.

Um exemplo simples de formulário executado por uma página em JSP é mostrado a seguir. A Figura 40 mostra um formulário simples que pede ao usuário para digitar o valor de um ângulo (em radianos). A Figura 41 mostra o resultado deste formulário como visto em um navegador.

<BODY> <FORM ACTION = "angulo.jsp" METHOD=POST> Ângulo: <INPUT TYPE="TEXT" NAME="ANGULO" SIZE="20"> <INPUT TYPE="SUBMIT" VALUE="Enviar"> </FORM> </BODY>

Figura 40 – Um formulário cujos dados serão processados por uma página em JSP.

Figura 41 – Resultado do código da Figura 40 mostrado por um

navegador.

Sabemos que o formulário passará os campos e respectivos valores para a aplicação indicada pelo campo ACTION da tag <FORM>. A aplicação, por sua vez, se estiver escrita em JSP, pode usar o método getParameter da instância request da classe HTTPServletRequest para recuperar os valores das variáveis do formulário usando como argumento os nomes dos campos, um de cada vez. Para recuperar o valor da variável ANGULO, usaremos request.getParameter(“ÂNGULO”). Todos os valores de campos de texto são passados para a aplicação como strings, então algumas conversões podem ser necessárias.

O script em JSP que exemplifica isto é mostrado na Figura 42. Este script recupera o valor do ângulo (convertendo-o para double) e imprime uma tabela com o seno, co-seno e tangente daquele ângulo. O resultado, como mostrado em um navegador, pode ser visto na Figura 43.

<BODY> <% double angulo = Double.parseDouble( request.getParameter("ANGULO")); %> <TABLE BORDER=1> <TR> <TH>Ângulo</TH> <TH ALIGN=RIGHT><%= angulo %></TH> </TR> <TR>

860

861Introdução à Programação com Java Server Pages e Servlets

<TD>Seno</TD> <TD ALIGN=RIGHT><%= Math.sin(angulo) %></TD> </TR> <TR> <TD>Co-seno</TD> <TD ALIGN=RIGHT><%= Math.cos(angulo) %></TD> </TR> <TR> <TD>Tangente</TD> <TD ALIGN=RIGHT><%= Math.tan(angulo) %></TD> </TR> </TABLE> </BODY>

Figura 42 – Script em JSP que processa os dados do formulário da Figura 40.

Figura 43 – Resultado da execução do código da Figura 42.

O código mostrado na Figura 40 (formulário) e na Figura 42 (página em JSP) mostra como podemos recuperar valores declarados em um formulário para uso em uma aplicação em JSP. No exemplo, um campo do tipo TEXT foi usado. Variáveis declaradas como campos do tipo TEXT, PASSWORD e HIDDEN podem ser recuperados na aplicação como strings. Campos declarados em formulários com a tag <TEXTAREA> serão também recuperados como strings pela aplicação, mas com todas as linhas inseridas no campo correspondente à área de texto concatenadas como uma só.

Campos do tipo RADIO são declarados com argumentos NAME e VALUE (veja código na Figura 23), sendo que se vários campos do tipo RADIO compartilharem o mesmo valor de NAME, somente um deles poderá ser selecionado a cada momento. Para verificar, em uma aplicação, qual dos campos do tipo RADIO foi selecionado, podemos usar o método getParameter da instância request passando para ele como argumento o nome usado para identificar o campo (NAME). O resultado da chamada a este método será o argumento VALUE do botão de rádio selecionado.

Campos do tipo CHECKBOX que estiverem marcados serão passados para a aplicação associados à string “ON”, este valor poderá ser obtido usando o método getParameter da instância request passando para ele como argumento o nome (NAME) usado para identificar o checkbox. Se o checkbox não tiver sido marcado, o método retornará null.

A página JSP mostrada na Figura 44 será capaz de processar os dados do formulário mostrado na Figura 23. A página mostrará como resultado o pedido principal feito (escolhido através dos botões de rádio, deverá ser ou FILE ou FRANGO ou PEIXE), um dos valores para o botão de rádio identificado com o nome PEDIDO. O código da Figura 44 também mostrará os valores dos checkboxes que estiverem selecionados quando os valores dos

campos do formulário forem enviados, ignorando os que não estiverem marcados.

<BODY> <% out.println("O seu pedido foi: "+ request.getParameter("PEDIDO")+"<BR>"); out.println("Acompanhamentos:"); out.println("<UL>"); if (request.getParameter("SALADA") != null) out.println("<LI>Salada"); if (request.getParameter("ARROZ") != null) out.println("<LI>Arroz"); if (request.getParameter("BATATA") != null) out.println("<LI>Batata"); %> </BODY>

Figura 44 – Código JSP que pode processar os dados do formulário mostrado na Figura 23.

Valores de campos que foram declarados em formulários como sendo do tipo SELECT poderão ser acessados nas aplicações da mesma forma que campos de outros tipos, ou seja, usando o método getParameter da instância request. Este método deve receber como argumento o nome indicado para o tipo SELECT e retornará o nome da opção selecionada (a string entre <OPTION> e </OPTION>) ou o parâmetro VALUE indicado na tag OPTION, se existir.

A Figura 45 mostra código em JSP que pode processar os campos declarados no formulário da Figura 25. Este código mostrará qual foi a opção selecionada para os campos PEDIDO e BEBIDA (ou null se nenhuma opção tiver sido selecionada). No caso do campo PEDIDO, ao invés do nome do pedido como aparece no navegador, o valor do seu atributo VALUE será retornado (isto é, FF se a opção escolhida for Filé com fritas, etc.).

<BODY> <% out.println("O seu pedido foi: "+ request.getParameter("PEDIDO")+"<BR>"); out.println("Acompanha bebida: "+ request.getParameter("BEBIDA")+"<BR>"); %> </BODY>

Figura 45 – Código JSP que pode processar os dados do formulário mostrado na Figura 25.

Sessões A comunicação entre cliente (navegador) e servidor é feita de

forma que não existe memória entre uma interação e outra – em outras palavras, valores não são preservados entre uma execução das aplicações e outra. Isto ocorre porque cada vez que uma página é requisitada do servidor, uma nova conexão é feita entre o servidor e o cliente, e o protocolo HTTP (de comunicação entre clientes e servidores na WWW) não oferece um mecanismo automático de preservar informações passadas anteriormente.

Existem várias aplicações para as quais ia ser interessante ter um mecanismo que preservasse os dados coletados durante a navegação de várias páginas/aplicativos. Um destes exemplos, talvez o mais clássico, é o de um carrinho de compras – um usuário pode navegar em várias páginas de um servidor que contém um sistema de compras na Internet, coletando dados (por

861

862 Santos

exemplo, sobre os produtos que deseja comprar), até decidir finalizar a compra. É essencial, neste exemplo, ter um mecanismo que guarde, durante a navegação, quais itens o usuário deseja comprar.

Uma maneira de implementar este mecanismo é fazendo com que todas as páginas de uma aplicação sejam formulários, e que estes formulários tenham campos do tipo HIDDEN (escondido), que funcionam da mesma maneira que campos do tipo TEXT, exceto que o componente da interface com o usuário (o campo de texto) não é exibido na página. Esta abordagem é complexa e sujeita a falhas, já que todas as páginas deveriam ter este campo escondido, cujo valor poderia ser modificado entre cada iteração.

Outra maneira de manter um mecanismo de memória entre interações é usando cookies, mas por razões de segurança muitos usuários não habilitam esta função em seus navegadores. Uma terceira maneira é anexar à cada URL um código que possa ser usado para recuperar informações do lado do servidor. Esta técnica é conhecida como uso de apêndices em URLs.

Páginas em JSP tem um mecanismo melhor para manter o estado ou memória entre interações: o mecanismo de sessões. Este mecanismo usa ou cookies ou apêndices de URLs, automatica-mente, para armazenar valores coletados durante a navegação, poupando trabalho para o desenvolvedor da aplicação.

Em uma determinada sessão de uso do navegador para acessar um servidor qualquer, podemos armazenar vários pares de chaves-valor como atributos da sessão. Estes pares, onde a chave é uma string e o valor é uma instância de uma classe qualquer, podem ser armazenados, modificados e removidos de uma sessão.

Para adicionar um par chave/valor, podemos usar o método setAttribute da instância session, passando a string e o objeto a ser armazenados como argumentos. Para remover um par chave/valor, podemos usar o método removeAttribute, que recebe como argumento somente a chave do par a ser removido. Para modificar o valor de um par chave-valor basta inseri-lo novamente na sessão usando a mesma chave.

Como exemplo de uso do mecanismo de sessões, consideremos um exemplo bem simples: um formulário de pedidos de fitas de vídeo (ou livros). A Figura 46 mostra o código de uma aplicação que quando executada mostra um formulário que permite a entrada de um título e um valor numérico (quantidade) de itens que serão adquiridos. Cada vez que um item for adquirido, a aplicação verificará se o título do vídeo já existe como chave na sessão. Se o título já existir na sessão, a aplicação recuperará a quantidade de itens já encomendados (inseridos anteriormente), e inserirá novamente o par chave-valor na sessão. Desta forma, durante uma sessão os títulos dos vídeos e a quantidade de cada serão armazenados de forma transparente para o usuário e de forma simples para o desenvolvedor.

<BODY> <FORM ACTION = "sessao.jsp" METHOD="POST"> <TABLE BORDER=1> <TR> <TH COLSPAN=2 ALIGN=CENTER> Adicione mais pedidos: </TH> </TR> <TR> <TD>Título:</TD> <TD><INPUT TYPE="TEXT" NAME="TITULO" SIZE=32></TD> </TR> <TR> <TD>Quantidade:</TD> <TD><INPUT TYPE="TEXT"

NAME="QUANT" SIZE=3></TD> </TR> <TR> <TD COLSPAN=2 ALIGN=CENTER> <INPUT TYPE="SUBMIT" VALUE="Adiciona"> </TD> </TR> </TABLE> </FORM> <HR> <%@ page import="java.util.*" %> <% // Recuperamos o campo TITULO do formulário. String título = request.getParameter("TITULO"); // Só executamos o resto do código se este campo // existir. if (título != null) { // Recuperamos o campo QUANT do formulário. int quant = 0; try { quant = Integer.parseInt( request.getParameter("QUANT")); } catch (Exception e) { quant = 0; } // Verificamos se já existe algum pedido // de cópias para este título. int quantTotal = 0; try { Integer atributo = (Integer)session.getAttribute(título); quantTotal = atributo.intValue(); } catch (Exception e) { quantTotal = 0; } // Armazenamos a quantidade de cópias como // atributos da sessão. session.setAttribute(título, new Integer(quantTotal+quant)); // Imprimimos a última entrada. out.print("<B>Último adicionado:</B>"); out.print(título); if (quantTotal == 0) out.print(" (novo pedido:"+quant+" cópias)"); else out.print(" (aumenta o pedido de "+ quantTotal+ " cópias para mais "+ quant+" cópias)"); out.print("<HR>"); // Imprimimos todos os atributos da sessão. out.print("<TABLE BORDER=1>"); Enumeration enum = session.getAttributeNames(); while(enum.hasMoreElements()) { String umTítulo = (String)enum.nextElement(); out.println("<TR><TD>"+umTítulo+"</TD>"); Integer atributo = (Integer)session.getAttribute(umTítulo); int umaQuant = atributo.intValue(); out.println("<TD>"+umaQuant+"</TD></TR>");

862

863Introdução à Programação com Java Server Pages e Servlets

} out.print("</TABLE>"); out.println(); } %> </BODY>

Figura 46 – Exemplo de página em JSP que armazena informações entre interações.

A Figura 47 mostra a primeira execução do código da Figura 46. Como a sessão não contém pares chave/valor, somente o formulário é apresentado. A Figura 48 mostra a aplicação várias interações depois, quando o usuário já digitou vários títulos de filmes, inclusive alguns mais de uma vez, para demonstrar o mecanismo que armazena os filmes já encomendados.

Figura 47 – Primeira execução do código mostrado na Figura 46.

Figura 48 – Aparência da página criada pelo código mostrado na

Figura 46 depois de várias execuções.

Programando SERVLETS Páginas em Java Server Pages podem ser rapidamente

desenvolvidas quando a aplicação em vista é simples: basta inserir trechos de código para executar a aplicação entre os trechos que

contém a apresentação da aplicação (em HTML). O servidor converterá estes trechos e o código HTML em uma servlet, que é uma pequena aplicação existente no servidor, que será executada quando for requisitada.

É possível escrevermos diretamente servlets, em vez de usar a conversão automática de scripts em JSP. Para que uma classe seja reconhecida pelo servidor como uma servlet, ela deve herdar da classe HTTPServlet e implementar alguns métodos específicos. No caso, dois métodos serão freqüentemente implementados: o método doGet e o método doPost, que serão executados, respectivamente, quando a servlet for executada através dos métodos GET e POST. Ambos os métodos recebem como argumentos uma instância da classe HttpServletRequest e uma instância da classe HttpServletResponse, não retornam valores e são declarados como protected void. Ambos os métodos declaram que as exceções ServletException e IOException podem ocorrer.

Um esqueleto (que não executa nenhum comando) de uma classe que pode ser executada como uma servlet é mostrado na Figura 49.

import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet1 extends HttpServlet { protected void doGet( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doPost( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }

Figura 49 – Esqueleto de uma servlet.

Um segundo exemplo, que executa algum processamento básico, é mostrado na Figura 50. Esta servlet mostra, dependendo do método que causou a sua execução (GET ou POST), um formulário com um botão chamando a mesma servlet com o método diferente, ou seja, se a servlet tiver sido chamada com o método POST, o formulário a executará novamente com o método GET e vice-versa. O resultado, como aparece em um navegador, é mostrado na Figura 50.

import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet2 extends HttpServlet { protected void doGet( HttpServletRequest request, HttpServletResponse response)

863

864 Santos

throws ServletException, IOException { // Indicamos que a saída será em HTML. response.setContentType("text/html"); ServletOutputStream out = response.getOutputStream(); out.print("<HTML><HEAD><TITLE>"+ "Exemplo de Servlet"+ "</TITLE></HEAD><BODY>"); // Imprimimos a mensagem. out.print("Você está acessando esta "+ "<I>servlet</I> usando o método "+ "<B>GET</B>.<P>"); // Imprimimos um formulário. out.print("<FORM ACTION=\"Servlet2\" "+ "METHOD=\"POST\""); out.print("<INPUT TYPE=\"SUBMIT\" "+ "VALUE=\"Clique aqui para "+ "acessar com o método POST\">"); out.print("</FORM>"); out.print("</BODY></HTML>"); } protected void doPost( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Indicamos que a saída será em HTML. response.setContentType("text/html"); ServletOutputStream out = response.getOutputStream(); out.print("<HTML><HEAD><TITLE>"+ "Exemplo de Servlet"+ "</TITLE></HEAD><BODY>"); // Imprimimos a mensagem. out.print("Você está acessando esta "+ "<I>servlet</I> usando o método "+ "<B>POST</B>.<P>"); // Imprimimos um formulário. out.print("<FORM ACTION=\"Servlet2\" "+ "METHOD=\"GET\""); out.print("<INPUT TYPE=\"SUBMIT\" "+ "VALUE=\"Clique aqui para "+ "acessar com o método GET\">"); out.print("</FORM>"); out.print("</BODY></HTML>"); } }

Figura 50 – Uma servlet que processa um formulário básico.

Figura 51 – Resultado da execução da servlet da Figura 50.

Podemos notar que em uma servlet devemos escrever código

em Java que gera a saída de HTML – diferentemente de uma página em JSP, não podemos simplesmente inserir tags de formatação no código. Se a página a ser gerada pela servlet contiver muito código em HTML, o código da servlet se tornará denso ou ilegível. Uma solução para este problema é preparar métodos, na própria servlet ou em uma outra classe, que façam

toda a saída em HTML, deixando para a servlet em si a parte de processamento.

É possível que para uma servlet, o método de chamada (POST ou GET) seja indiferente. Neste caso podemos simplesmente implementar o código da servlet em um dos métodos, por exemplo, doPost e simplesmente chamar este método de dentro do método doGet, como será exemplificado a seguir.

Um terceiro exemplo, mais complexo, mostra o código da Figura 46 reescrito como uma servlet.

import java.io.IOException; import java.util.Enumeration; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class ServletS extends HttpServlet { protected void doGet( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Simplesmente executamos o método doPost. doPost(request,response); } protected void doPost( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Indicamos que a saída será em HTML. response.setContentType("text/html"); // Obtemos um stream para enviar // texto para o navegador. ServletOutputStream out = response.getOutputStream(); // Montamos o formulário em HTML. out.print("<FORM ACTION = \"ServletS\""+ " METHOD=\"POST\">"); out.print("<TABLE BORDER=1>"); out.print("<TR>"+ "<TH COLSPAN=2 ALIGN=CENTER>"+ "Adicione mais pedidos:"+ "</TH></TR>"); out.print("<TR><TD>Título:</TD><TD>"+ "<INPUT TYPE=\"TEXT\""+ " NAME=\"TITULO\" SIZE=32>"+ "</TD></TR>"); out.print("<TR><TD>Quantidade:</TD><TD>"+ "<INPUT TYPE=\"TEXT\""+ " NAME=\"QUANT\" SIZE=3>"+ "</TD></TR>"); out.print("<TR>"+ "<TD COLSPAN=2 ALIGN=CENTER>"+ "<INPUT TYPE=\"SUBMIT\" "+ "VALUE=\"Adiciona\">"+ "</TD></TR>"); out.print("</TABLE>"); out.print("</FORM>"); out.print("<HR>"); // Recuperamos o campo TITULO do // formulário. String título = request.getParameter("TITULO"); // Só executamos o resto do código

864

865Introdução à Programação com Java Server Pages e Servlets

se este cam xistir. // po e if (título != null) { int quant = 0; try { quant = Integer.parseInt( request.getParameter("QUANT")); } catch (Exception e) { quant = 0; } // Verificamos se já existe algum // pedido de cópias para este título. int quantTotal = 0; // Recuperamos a sessão. HttpSession session = request.getSession(); try { Integer atributo = (Integer)session.getAttribute(título); quantTotal = atributo.intValue(); } catch (Exception e) { quantTotal = 0; } // Armazenamos a quantidade de cópias // como atributos da sessão. session.setAttribute(título, new Integer(quantTotal+quant)); // Imprimimos a última entrada. out.print("<B>Último adicionado:</B>"); out.print(título); if (quantTotal == 0) out.print(" (novo pedido:"+quant+ " cópias)"); else out.print(" (aumenta o pedido de "+ quantTotal+ " cópias para mais "+ quant+" cópias)"); out.print("<HR>"); // Imprimimos todos os atributos da sessão. out.print("<TABLE BORDER=1>"); Enumeration enum = session.getAttributeNames(); while(enum.hasMoreElements()) { String umTítulo = (String)enum.nextElement(); out.println("<TR><TD>"+umTítulo+"</TD>"); Integer atributo = (Integer) session.getAttribute(umTítulo); int umaQuant = atributo.intValue(); out.println("<TD>"+umaQuant+ "</TD></TR>"); } out.print("</TABLE>"); } // fim if título != null } }

Figura 52 – O código da Figura 46, reescrito como uma servlet.

É indiferente se a servlet mostrada na Figura 52 é chamada pelo método GET ou POST, então o código do método doGet simplesmente executa o código do método doPost.

O código da listagem na Figura 52 é praticamente idêntico ao da listagem na Figura 46, exceto pelos seguintes pontos:

• A servlet precisa indicar qual é o tipo de documento que será enviado, usando o método setContentType da classe HttpServletResponse. Para páginas em HTML, o tipo de documento é text/html.

• Em servlets temos que recuperar algumas instâncias de classes utilitárias manualmente, que estão disponíveis automaticamente em páginas em JSP, como a instância out da classe ServletOutputStream que é usada para enviar dados para o cliente (navegador) e a instância session da classe HTTPSession, que é usada para manter dados sobre a sessão.

• Todo o código HTML teve que ser inserido como argumentos para o método out.print, tornando o código da servlet denso.

Foi comentado anteriormente que páginas em JSP são processadas e transformadas em servlets antes da sua execução. Vale a pena notar que a servlet gerada automaticamente é consideravelmente mais complexa do que as convertidas “manualmente”.

Exemplo mais complexo de servlets Para mostrar um exemplo simples, porém mais completo,

consideremos o caso do Empório de Plantas Exóticas, especializado em vender mudas de plantas nativas exóticas pela Internet. Vamos implementar o site de vendas do Empório, que consistirá basicamente de um catálogo virtual (onde um usuário poderá verificar o preço e estoque de cada uma das mudas à venda) e um subsistema de vendas. Para manter o exemplo simples, vamos considerar somente as operações mínimas para cada um destes subsistemas.

Este site é executado em um servidor que permite o acesso a um banco de dados. Na implementação, foi usado o banco de dados Postgres, mas poderia ser qualquer outro que tivesse drivers JDBC (Java Database Connection). O banco de dados para este site contém uma única tabela, que contém os campos DESCRICAO que descreve uma planta, ESTOQUE que mostra quantas mudas existem no estoque e CUSTO que contém o valor unitário de cada muda para venda.

Uma página principal mostrará ao usuário do sistema links para as duas outras aplicações. Embora não seja necessário, esta página principal também será implementada como uma servlet – isso facilita a manutenção de um layout consistente entre os subsistemas da aplicação.

A servlet de consulta mostrará ao usuário um formulário onde este pode entrar um texto. Ao clicar no botão “Consulta...” do mesmo formulário, este será recarregado e executará uma busca na tabela do banco de dados mostrando todos os registros cujo campo DESCRICAO contenha o texto entrado no formulário.

A servlet de vendas será um pouco mais complexa, mostrando para o usuário um formulário cujos campos serão obtidos do próprio banco de dados. O usuário poderá então selecionar um nome de planta e a quantidade de mudas que deseja comprar. O sistema calculará o faturamento e decrementará o estoque.

Evidentemente um sistema completo faria muito mais do que isto, mas para exemplificar os conceitos neste tutorial e para manter o código-fonte curto o suficiente para ser inteligível, bastam estas funções.

Este exemplo consistirá de quatro listagens, correspondentes a três servlets e uma classe com vários campos e métodos estáticos úteis. As listagens são comentadas para facilitar a compreensão.

A primeira classe, EPEUtils, contém os campos e métodos estáticos usados nas outras classes desta aplicação, e é mostrada

865

866 Santos

A servlet que executa a função de venda de mudas de plantas é mostrada na Figura 56. Esta servlet consulta inicialmente o banco de dados para montar o formulário de vendas, recuperando todos os nomes de plantar para criar um componente de seleção de opções. A servlet também cria um formulário usando este componente de seleção de opções e um campo de texto para a entrada do número de mudas que serão vendidas. Se o método doPost tiver sido chamado através de um formulário, os dados do formulário são recuperados e a servlet calcula o valor do pedido (faturamento) e decrementa o estoque de mudas da planta selecionada.

na Figura 53. Alguns dos métodos nesta classe facilitam a manutenção de um layout comum à todos os subsistemas.

A servlet que corresponde à página principal é mostrada na Figura 54. Esta classe herda de HTTPServlet e implementa seus métodos doGet e doPost, sendo que o método doGet simplesmente executa o método doPost, para simplificar (não se espera que esta classe seja chamada com o método POST).

A servlet que executa a função de consulta ao cadastro é mostrada na Figura 55. Esta servlet mostra um formulário no navegador e, se existir um campo chamado planta, usa o valor associado a este campo para fazer uma busca no banco de dados, recuperando e mostrando todas as plantas cuja descrição contenha o texto passado no campo planta.

// Classe que contém vários campos e métodos estáticos. public class EPEUtils { // Mensagem de copyright. private static final String copyright = "&copy; Empório de Plantas Exóticas, 2004"; b ma. // URL ase do siste private static final String baseURL = "http://localhost/Demos/"; c r al do sistema. // Apli ação p incip private static final String mainURL = baseURL+"servlet/EPEMain"; o cria o cabeçalho em HTML usando o título passado como argumento. // Mét do que public static String header(String title) { return "<HTML><HEAD><TITLE>"+title+"</TITLE></HEAD><BODY>"; } // Método que cria um rodapé padrão. public static String footer() { return "<HR><CENTER><A HREF=\""+mainURL+"\">"+copyright+"</A></CENTER></BODY></HTML>"; } o ring para exibição do logotipo do Empório. // Ret rna St public static String logo() { return "<CENTER><IMG SRC=\""+baseURL+"img/logo.png\"></CENTER>"; } o ring com link para aplicação local. // Ret rna St public static String link(String url,String text) { return "<A HREF=\""+baseURL+url+"\">"+text+"</A>"; } }

Figura 53 – Código-fonte para a classe EPEUtils.

import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //Classe que implementa a Servlet. public class EPEMain extends HttpServlet { // Método que responderá a pedidos POST. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Saída em HTML. response.setContentType("text/html"); // Obtemos um stream de saída. ServletOutputStream out = response.getOutputStream();

866

867Introdução à Programação com Java Server Pages e Servlets

// Enviamos cabeçalho e logotipo. out.println(EPEUtils.header("Empório de Plantas Exóticas")); out.println(EPEUtils.logo()+"<P>"); // Montamos links para outras servlets. out.println(EPEUtils.link("servlet/EPEConsulta","Consulta")+"<BR>"); out.println(EPEUtils.link("servlet/EPEVenda","Venda")+"<BR>"); // Enviamos o rodapé do documento. out.println(EPEUtils.footer()); } // Caso esta servlet seja chamada diretamente (pelo método get, deverá ser o mais comum), // simplesmente executamos o método doPost. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } } // fim da classe EPEMain.

Figura 54 – Código-fonte para a classe EPEMain.

import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; // Cla se qu a Servls e implementa et. public class EPEConsulta extends HttpServlet { responderá a pedidos POST. // Método que protected void st(HttpServletRequest request, HttpServletResponse response) doPo throws ServletException, IOException { // Saída em HTML. response.setContentType("text/html"); // Obtemos um stream de saída. ServletOutputStream out = response.getOutputStream(); // Enviamos cabeçaalho e logotipo. out.println(EPEUtils.header("Empório de Plantas Exóticas - Consulta")); out.println(EPEUtils.logo()); // Criamos o formulário para entrada de um texto. out.println("<P><FORM ACTION=\"EPEConsulta\" METHOD=\"POST\">"); out.println("Planta: <INPUT TYPE=\"TEXT\" NAME=\"planta\" SIZE=20>"); out.println("<INPUT TYPE=\"SUBMIT\" VALUE=\"Consulta...\">"); out.println("</FORM>"); // Esta servlet foi chamada com um parâmetro chamado "planta" ? String planta = request.getParameter("planta"); if (planta != null) { // Imprimimos o cabeçalho da tabela com resultados da pesquisa. out.println("<HR>"); out.println("<TABLE BORDER=1>"); out.println("<TR>"); out.println("<TH>Nome</TH>"); out.println("<TH>Quantidade</TH>"); out.println("<TH>Preço</TH>"); out.println("</TR >"); Connection con = null; try { // Tentamos obter um driver para o banco de dados. Class.forName("org.postgresql.Driver"); String dsn = "jdbc:postgresql://127.0.0.1:5432/comercio"; String user = "comercio"; String password = "comercio"; // Criamos uma conexão e uma query.

867

868 Santos

con = DriverManager.getConnection(dsn, user, password); Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet srs = stmt.executeQuery("SELECT DESCRICAO,ESTOQUE,CUSTO FROM ITENS "+ "WHERE DESCRICAO LIKE '%"+planta+"%'"+ "ORDER BY DESCRICAO"); // Para cada resultado na query... while (srs.next()) { // Recuperamos os campos e formatamos na tabela. String nome = srs.getString("DESCRICAO"); int num = srs.getInt("ESTOQUE"); float custo = srs.getFloat("CUSTO"); out.println("<TR>"); out.println("<TD>"+nome+"</TD>"); out.println("<TD ALIGN=RIGHT>"+num+"</TD>"); out.println("<TD ALIGN=RIGHT>"+custo+"</TD>"); out.println("</TR>"); } stmt.close(); } // Se houver qualquer exceção... catch(Exception e) { out.println("Erro !"+e); } // Ao final, fechamos a conexão com o banco de dados. if (con != null) try { con.close(); } catch (SQLException e) { out.println("Erro !"+e); } // Fechamos a tabela. out.println("</TABLE>"); } // Enviamos o rodapé do documento. out.println(EPEUtils.footer()); } // Caso esta servlet seja chamada diretamente (pelo método get), // simple ments e executamos o método doPost. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } } // fim da classe EPEConsulta.

Figura 55 – Código-fonte para a classe EPEConsulta.

import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; // Classe que implementa a Servlet. public class EPEVenda extends HttpServlet { // Método que responderá a pedidos POST. protected void doPost(HttpServletRequest request, HttpServletResponse response)

868

869Introdução à Programação com Java Server Pages e Servlets

throws ServletException, IOException { // Saída em HTML. response.setContentType("text/html"); // Obtemos um stream de saída. ServletOutputStream out = response.getOutputStream(); // Enviamos cabeçalho e logotipo. out.println(EPEUtils.header("Empório de Plantas Exóticas - Venda")); out.println(EPEUtils.logo()); // Para conseguir a lista de plantas à venda, procuramos no banco de dados. // Tentamos obter um driver para o banco de dados. try { Class.forName("org.postgresql.Driver"); } catch (ClassNotFoundException e1) { out.println("Erro carregando a classe org.postgresql.Driver"); } String dsn = "jdbc:postgresql://127.0.0.1:5432/comercio"; String user = "comercio"; String password = "comercio"; // Criamos uma conexão e uma query. Connection con = null; Statement stmt; try { con= DriverManager.getConnection(dsn, user, password); stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); // Criamos o formulário. out.println("<P><FORM ACTION=\"EPEVenda\" METHOD=\"POST\">"); out.println("Planta: <SELECT NAME=\"planta\">"); // Para o nome da planta, pegamos todas existentes no banco de dados. ResultSet srs = stmt.executeQuery("SELECT DESCRICAO FROM ITENS ORDER BY DESCRICAO"); while (srs.next()) { // Recuperamos os campos e formatamos na tabela. String name = srs.getString("DESCRICAO"); out.println("<OPTION>"+name+"</OPTION>"); } out.println("</SELECT><BR>"); out.println("Quantidade: "); out.println("<INPUT TYPE=\"TEXT\" NAME=\"quant\" SIZE=4><BR>"); out.println("<INPUT TYPE=\"SUBMIT\" VALUE=\"Vender...\">"); out.println("</FORM>"); // Esta servlet foi chamada com um parâmetro chamado "planta" ? String planta = request.getParameter("planta"); if (planta != null) { int quant = 0; if (request.getParameter("quant") != null) quant = Integer.parseInt(request.getParameter("quant")); out.println("Pedido de venda: <B>"+quant+"</B> mudas de <B>"+planta+"</B><BR>"); // Mostramos o faturamento com esta venda. srs = stmt.executeQuery("SELECT CUSTO,ESTOQUE FROM ITENS "WHERE DESCRICAO = '"+planta+"'"); srs.next(); float custo = srs.getFloat("CUSTO"); int estoque = srs.getInt("ESTOQUE"); out.println("Estoque: "+estoque+" mudas.<BR>"); int novoEstoque = estoque-quant; out.println("Faturamento: "+quant+"x"+custo+" = <B>"+(quant*custo)+"</B><BR>"); // Efetuamos a baixa no estoque. int updates = stmt.executeUpdate("UPDATE ITENS SET ESTOQUE = "+novoEstoque+ " WHERE DESCRICAO = '"+planta+"'"); out.println("Estoque atualizado...<BR>"); // Verificamos novo estoque. srs = stmt.executeQuery("SELECT ESTOQUE FROM ITENS WHERE DESCRICAO = '"+planta+"'"); srs.next(); out.println("Novo estoque:"+srs.getInt("ESTOQUE")); stmt.close(); } } // fim do bloco try. catch (SQLException e) {

869

870 Santos

out.println("Erro SQL:"+e.getMessage()); } // Fechamos a conexão com o banco de dados. try { con.close(); } catch (SQLException e) { out.println("Erro SQL"); } // Enviamos o rodapé do documento. out.println(EPEUtils.footer()); } // Caso esta servlet seja chamada diretamente (pelo método get), // simple ments e executamos o método doPost. protected void oGet(HttpServletRequest request, HttpServletResponse response) d throws ServletException, IOException { doPost(request,response); } } // fim da classe EPEVenda.

Figura 56 – Código-fonte para a classe EPEVenda.

Os resultados da execução das servlets desta aplicação podem ser vistos nas figuras a seguir. A Figura 57 mostra a exibição em navegador da aplicação principal, que apresenta links para as aplicações de consulta e venda. A Figura 58 mostra a aplicação de consulta antes de executarmos a consulta por plantas que contenham o texto “x” em suas descrições, e a Figura 59 mostra o resultado desta consulta.

A Figura 60 mostra a aplicação de vendas, exibindo a lista de plantas cadastradas no banco de dados, que foi usada para criar a seleção de opções. A Figura 61 mostra o formulário preenchido para exemplificar uma execução de operação de venda. A Figura 62 mostra o resultado da operação de venda.

Figura 57 – Aplicação principal (servlet EPEMain).

Figura 58 – Aplicação de consulta (servlet EPEConsulta).

870

871Introdução à Programação com Java Server Pages e Servlets

Figura 59 – Aplicação de consulta (servlet EPEConsulta) mostrando resultados.

Figura 60 – Aplicação de vendas (servlet EPEVenda) mostrando o menu de seleção cujas opções foram obtidas do banco de dados.

Figura 61 – Aplicação de consulta (servlet EPEVenda) mostrando o

formulário preenchido.

Figura 62 – Aplicação de consulta (servlet EPEVenda) mostrando

resultados da execução.

Tópicos intermediários e AVANçADOS Vimos, neste tutorial, como programar páginas em Java Server

Pages e servlets simples. Existem outros conceitos sobre JSP e servlets que não foram cobertos no tutorial, pois são conceitos intermediários e avançados. Alguns destes conceitos são apresentados a seguir, sendo sugerido que o leitor procure, nas referências ou na Internet, avançar em seus estudos nestes tópicos.

• Classes em Java que seguem certos padrões (métodos get e set para alguns campos privados, construtor “vazio”) são consideradas JavaBeans, que podem ser usadas de maneira simplificada em páginas em JSP com a tag <jsp:useBean>. Podemos modificar e recuperar campos em JavaBeans com o

871

872 Santos

uso destas tags sem precisar escrever código explícito para isto. Beans podem ser compartilhados entre sessões e até mesmo aplicações no mesmo servidor, sendo um interessante mecanismo para preservar dados entre interações.

• É possível definir tags customizadas, que são agrupadas em tag libraries ou tag libs. Estas tags podem ser usadas para inserir elementos complexos, incluindo processamento de dados efetuado por classes em Java, em páginas JSP.

• Servlets podem retornar outros tipos de documentos além de texto em HTML (tipo text/html). Uma forma de retornar gráficos que são criados dinamicamente ou mesmo páginas básicas para visualização no software Excel são mostradas em (Hall, 2000).

Bibliografia e Referências DARNELL, R. et. al. HTML 4 Unleashed. Indiana, EUA: Editora SAMS.NET, 1998.

HALL, M. Core Web Programming. New Jersey, EUA: Editora Prentice-Hall, 1998.

HALL, M. Core Servlets and Java Server Pages. New Jersey, EUA: Editora Prentice-Hall, 2000.

HORSTMANN, C. S.; CORNELL, G. Core Java (Volumes I e II). California, EUA: Editora Sun Microsystems Press, 2001.

SANTOS, R. Introdução à Programação Orientada a Objetos usando Java. Rio de Janeiro: Editora Campus, 2003.

SANTOS, R. Material adicional para o mini-curso. Disponível em http://www.directnet.com.br/users/rafael.santos. Maio de 2004.

872