You are on page 1of 99

Introdução a

Java Server Pages


por Christian Cleber Masdeval Braz
Sumário

I - Fundamentos Básicos 3

- A plataforma Web (HTTP) 3


- Tecnologias de conteúdo dinâmico 5
- Aplicações Web e Java 10
- Como executar servlets e jsp 12
- Web Container Tomcat 12

II – Servlets 16

- O que são Servlets? 16


- Ciclo de Vida 16
- Inicialização 17
- Finalização 17
- Métodos de Serviço 17
- Como criar um http servlet 18

III – Scripts JSP 20

− Elementos de criação de scripts 20


− Declarações 22
− Expressões 23
− Scriptlets 24
− Controle de Fluxo 26
− Comentários 30
− Diretivas JSP 32

IV – Objetos Implícitos 41

- Objetos Implícitos 41
− Relacionados a Servlets 42
− Relacionados ao Input/Output 43
− Contextuais 48
− Tratamento de Erros 55
− Ações 56

V – Cookies 61

VI – Enviando e-mail com JSP 67

VII – Trabalhando com Banco de Dados 71

− Introdução a API JDBC 71


− Como instalar um driver JDBC 71
− Como estabelecer uma conexão com um banco de dados 72
− Interagindo com banco de dados 73
− Executando consultas 73
− Executando alterações 74
− Executando stored procedures 75

2
− A classe ResultSet 76

VIII – Java Util 83

Apêndice A – Tratando Formulários 87

Apêndice B – Instalando um container JSP – TOMCAT 92

Apêndice C – HTTP - Hypertext Transfer Protocol 95

3
I - Fundamentos Básicos
Este capítulo cobre os seguintes tópicos :

- A plataforma Web (HTTP)


- Tecnologias de conteúdo dinâmico
- Aplicações Web e Java
- Como executar servlets e jsp
- O Web Container Tomcat

A plataforma Web
 Baseada em HTTP (RFC 2068)
 Protocolosimples de transferência de arquivos
 Sem estado (não mantém sessão aberta)

 Funcionamento simplificado: Máquina


www.xyz.com
Abre conexão para www.xyz.com:80
Soquete de Serviço:80
Cliente
Uma requisição : GET /index.html ... Servidor
HTTP
HTTP
(browser) Uma resposta: HTTP/1.1 200 Ok ...

Fecha conexão index.html


Desenvolvido pelo ESMS.C 3

Cliente e Servidor HTTP


 Servidor HTTP
 Mapeia pastas do sistema de arquivos local (ex:
c:\htdocs) a diretórios virtuais (ex: /) acessíveis
remotamente (notação URI)
 Interpreta requisições HTTP do cliente (método GET,
POST, HEAD, ...)
 Devolve resposta HTTP à saída padrão
 Cliente HTTP
 Envia requisições HTTP a um servidor. Requisições
contém URI do recurso remoto, cabeçalho, dados
 Processa respostas HTTP (interpreta cabeçalhos)
Desenvolvido pelo ESMS.C 4

4
Principais m étodos H T T P
 G ET – pede ao servidor um arquivo, inform ando
sua U R I absoluta
 Pode enviar dados porém o tam anho é lim itado
 PO ST – envia dados ao servidor (com o fluxo de
bytes)
 É o m étodo preferido quando se está usando
form ulários para subm issão
 H EA D – U sado para obter inform ações do
docum ento. A penas o cabeçalho é retornado

D esen volvid o p elo E SM S.C 5

Tecnologias do lado Cliente


 As principais tecnologias para criação de páginas
interativas no lado cliente são:
 HTM L
 CSS – Cascading Style Sheets
 DHTM L - Dynamic HTM L
 JavaScript
 VBScript
 Plug-ins – applest, activeX
 Nenhuma delas atende completamente a
necessidade das aplicações web modernas
Desenvolvido pelo ESM S.C 6

Tecnologias do lado Servidor


 Estendem as funções básicas do servidor HTTP:
 CGI – Common Gateway Interface
 APIs: ISAPI, NSAPI, Apache API, Servlet API
 Scripts:ASP, JSP, Cold Fusion, PHP
 Rodam do lado servidor, portanto, não dependem
de suporte por parte dos browsers
 Interceptam o curso normal da comunicação
 Recebem dados via requisições HTTP (GET e POST)
 Devolvem dados através de respostas HTTP

Desenvolvido pelo ESM S.C 7

5
O que é JSP ?

JSP é um acrônimo para Java Server Pages e consiste numa linguagem de script baseada
em java para criação de sites com conteúdos dinâmicos.

Inicialmente as páginas na Web eram apenas páginas estáticas, isto é, seu conteúdo não
variava a cada solicitação conforme algum parâmetro. Com a sofisticação dos serviços
disponibilizados via Web, surgiu a necessidade de disponibilizar informações com
natureza dinâmica (lista de preços atualizados, compras on-line, etc). Isso exigiu que o
servidor web fizesse algum processamento adicional da solicitação a fim de gerar uma
resposta personalizada. Algumas tecnologias para geração de conteúdo dinamicamente
são :

CGI – Common Gateway


Interface
 Especificação que determina como construir uma
aplicação que será executada pelo servidor Web
 Programas CGI podem ser escritos em qualquer
linguagem de programação. A especificação
limita-se a determinar os formatos de entrada e
saída dos dados (HTTP).
 O que interessa é que o programa seja capaz de
 Obter dados de entrada a Requisição Resposta
partir de uma requisição HTTP HTTP HTTP
 Gerar uma resposta HTTP
CGI
incluindo os dados e cabeçalho
Desenvolvido pelo ESMS.C 8

CGI – Common Gateway Interface

O CGI foi primeiro padrão para conteúdo da Web dinâmico. Ele é um protocolo de
comunicação que o servidor HTTP utiliza para conversação com outro programa. Um
CGI script é qualquer programa (PERL, C, Java) que se comunica com o servidor WEB
através do protocolo CGI. Um script CGI (como ficou conhecido este mecanismo) é um
programa que atende às requisições enviadas por um cliente e a ele repassadas pelo
servidor HTTP.

A Figura abaixo apresenta o funcionamento de uma requisição envolvendo CGI.

Figura 1 – Processo do servidor para rodar um programa de CGI

6
Um CGI tradicional possui algumas ineficiências que limitam sua aplicabilidade em
sistemas Web de grande escala. Uma delas deve-se ao fato de que um programa CGI
roda fora do servidor Web e não como um subprocesso do servidor. Dessa forma um
novo processo deve ser criado cada vez que um programa CGI precisa ser executado, o
que ocasiona um overhead considerável para o servidor. Outro problema é que os
programas de CGI são projetados para tratar de apenas uma única solicitação específica,
na qual um novo processo é criado, as informações da solicitação são enviadas para ele,
espera-se o processamento, a resposta é repassada de volta para o navegador e o
processo é finalizado. Com isso fica difícil, por exemplo, dois CGI’s compartilharem
recursos, o que otimizaria em muito a performance dos sistemas. É fácil imaginar os
problemas de performance ocasionados por este modelo num site que atenda a milhares
de solicitações simultâneas.

Para amenizar estes problemas, os novos sistemas para geração de conteúdo dinâmico
assumem a forma de módulos que alavancam as interfaces de programas aplicativos
específicos de servidor, a fim de interagir diretamente com o processo do servidor Web
como um subprocesso do mesmo, evitando assim muito do overhead associado aos
programas CGI convencionais.

APIs do Servidor
 Podem substituir totalmente o CGI com vanta-gens
 Melhor interação como servidor
 Múltiplos clientes são atendidos por processos internos
(threads)
 Muito mais rápidos e eficientes
 Desvantagens
 Em geral dependem de plataforma, fabricante e linguagem
 Soluções proprietárias
 Ex: ISAP (Microsoft), NSAPI (Netscape), etc

Desenvolvido pelo ESMS.C 10

S e r v le t A P I

 A P I in d e p e n d e n te d e p la ta f o r m a e p r a tic a m e n te
in d e p e n d e n te d e f a b r ic a n te
 C o m p o n e n te s s ã o e s c r ito s e m J a v a e s e
c h a m a m S e r v le ts
 C o m o o s c o m p o n e n te s S A P I p r o p r ie tá r io s ,
r o d a m d e n tr o d o s e r v id o r , m a s a tr a v é s d e u m a
M á q u in a V ir tu a l

D e s e n v o l v id o p e lo E S M S . C 11

7
Vantagens dos Servlets
 ... sobre CGI
 Cada nova requisição inicia um novo thread, não um
novo processo
 Mais integrado ao servidor, rodam como parte deste :
mais facilidade para compartilhar informações,
recuperar e decodificar dados enviados pelo cliente
 ... sobre APIs proprietárias
 Não dependem de único servidor ou sistema
operacional
 Têm toda a API Java à disposição

Desenvolvido pelo ESMS.C 12

Servlets e JSP

Servlets são a alternativa Java para CGI Scripts e assim possuem todas as vantagens da
plataforma à sua disposição : APIs, multiplataforma, multithreading, OO. Sua
desvantagem é que tanto o conteúdo estático quanto o dinâmico residem no código
fonte do programa, o que acarreta sérios problemas de manutenção.
JSP é a combinação de HTML com Java dentro de uma mesma página (como ASP e
PHP), porém, usando-se tags especiais do tipo HTML que interagem com objetos java
no servidor, podemos introduzir conteúdo dinâmico em qualquer parte da página sem
necessidade que código Java bruto apareça. Em princípio, todo o código fora dos tags é
HTML puro. Isso possibilita gerar um código mais manutenível pois permite a
separação do código que se destina a apresentação (HTML e tags) do código
responsável por gerar o conteúdo dinâmico (tipicamente Java).

Execução de Servlets
Servidor Web (Host)

1 Container de Servlet
1
Cliente Servidor Web 2 - Carrega Servlet se
5
necessário
3 - Cria encadeamento que
4
vai processar solicitação
(thread)
4 - Thread executa, retorna
resultado e finaliza

Desenvolvido pelo ESMS.C 13

8
Execução de Servlets/JSP

Uma página JSP é tipicamente convertida para um servlet quando de sua compilação,
por isso trataremos a forma de execução de ambos de forma indistinta.
Um servidor HTTP com suporte a servlets deve possuir um ServletEngine (container
servlet) que é o software responsável por executá-los. Este software corresponde a um
processo em Java separado do servidor HTTP rodando uma JVM e recebe todas as
solicitações para execução de um servlet/jsp.

O fluxo para execução ocorre da seguinte maneira :

1. O servidor HTTP recebe a solicitação para execução de um servlet/jsp e a repassa,


juntamente com os dados da solicitação, para o container.

2. O container verifica se aquele servlet já está carregado na memória. Se não estiver


ou se houver uma versão mais nova do servlet, o container o carrega. O fato dos
servlets mais recentes já estarem carregados na memória, representa em ganho de
performance.

3. Uma vez inicializado, o servlet estará apto a lidar com centenas de acessos
simultaneamente, disparando para cada acesso uma nova thread para atendê-lo
(encadeamento), ao invés de criar um novo processo. As threads são muito menos
custosas do que os processos convencionais, gerando um overhead muito menor
para sua criação e destruição. Elas compartilham a mesma memória que a do
processo pai e assim podem compartilhar recursos como conexões com banco de
dados, dentre outros.

4. Ao término do processamento, o resultado é enviado de volta para o servidor Web e


apenas a thread é encerrada, permanecendo o processo pai (servlet) ainda na
memória.

Problemas dos servlets, CGIs


e APIs
 Paragerar páginas dinâmicas é preciso embutir
o HTML dentro de instruções de um programa
out.print(“<h1>Servlet</h1>”);
for(int num=1; num <= 5 ; i++){
out.print(“<p>Parágrafo ” + num + </p>);
}
 Compromete a manutenção
 O design acaba ficando a cargo do programador
e não do Web designer

Desenvolvido pelo ESMS.C 14

9
Solução: scripts de servidor
 Colocaa linguagem de programação dentro do
HTML (e não o contrário)
<h1>Servlet </h1>
<% for(int num=1; num <= 5 ; i++){ %>
<p>Parágrafo ” + num + </p> <%}%>
O Web designer pode projetar as páginas em
ferramentas como DreamWeaver
 Página fica mais legível
 Quando houver muita programação, código
pode ser escondido em servlets, JavaBeans, etc
Desenvolvido pelo ESMS.C 15

Scripts de servidor
 Alguns dos mais populares:
 Microsoft Active Server Pages (ASP)
 Sun Java Server Pages (JSP)
 Macromedia Cold Fusion
 PHP
 As páginas são processadas pelo servidor
apropriado que retorna apenas conteúdo HTML
para o cliente

Desenvolvido pelo ESMS.C 16

ASP - Active Server Pages

É a solução da Microsoft para criação de páginas dinâmicas e suporta múltiplas


linguagens de criação de scripts incluindo PerlScript , JScript e principalmente
VBScript, um subconjunto da linguagem Visual Basic. Grande parte do poder desta
solução está no fato de ser possível acessar componentes ActiveX através do VBScript.

PHP

É uma linguagem de script Open Source que disponibiliza suporte para uma vasta gama
de recursos como acesso a banco de dados, comunicação com servidores de diretório,
manipulação de arquivos, e-mail , dentre muitos outros.

10
Benefícios de JSP

JSP oferece diversos benefícios como um sistema para geração de conteúdo dinâmico.
Sendo uma tecnologia baseada em Java, ela se aproveita de todas as vantagens que a
linguagem Java fornece : orientação a objetos, tratamento de exceções, gerenciamento
automático de memória, dentre outros aspectos que conduz a um ganho significativo de
produtividade.

Pelo fato do bytecode de Java compilado ser portável através de todas as plataformas
que possuam uma JVM, o uso de JSP não o restringe a uma plataforma de hardware,
sistema operacional ou software específico (o que não é verdade com o ASP). Pelo fato
de JSP ser neutra a fornecedores, os desenvolvedores e arquitetos de sistemas podem
selecionar melhores soluções em todas as etapas de acionamento de JSP.

JSP pode se aproveitar de todas as APIs de Java padrão, incluindo aquelas para acesso a
bancos de dados compatíveis com muitas plataformas, serviços de diretório,
processamento distribuído, criptografia, etc.

Embora JSP permita que programadores implementem a geração de conteúdo dinâmico


diretamente em páginas da web, ele também inclui um conjunto de tags do tipo HTML
para interagir com objetos Java no servidor. Em especial, estas tags são projetadas para
criar, realizar consultas e modificar JavaBeans no servidor. Ao se aproveitar do suporte
embutido de JSP para JavaBeans, é possível manter uma rígida separação entre a
apresentação dos dados ao usuário final e a implementação do código que gerou estes
dados. Assim, uma manutenção na parte estática não interfere em qualquer código Java
da programação e vice-versa.
Essa separação promove uma clara divisão de trabalho no desenvolvimento e
manutenção dos sites com conteúdo dinâmico, o que possibilita melhor organizar
equipes de desenvolvimento aproveitando o perfil de cada membro : designers, artistas
gráfico, codificadores HTML cuidam da apresentação, enquanto programadores Java
ficam responsáveis pela implementação.

Aplicações Web e Java


 Servlets e JSP são as soluções Java para
estender o servidor e gerar conteúdo dinâmico
 Páginas JSP são traduzidas para servlets e então
compiladas (o processo de execução é o mesmo)
 Suportam os métodos de requisição padrão
HTTP (GET, POST, etc)
 Interagem com cookies
 Suportam controle de sessão de forma
transparente

Desenvolvido pelo ESMS.C 17

11
Exemplo de um Servlet
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class SimpleServlet extends HttpServlet{
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException,IOException{
PrintWriter out;
response.setContentType(“text/html”);
out = response.getWriter();
String user = request.getParameter(“usuario”);
if (user == null) user = “World”;
out.println(“<html><body>”);
out.println(“<h1>Simple Servlet Output</h1>”);
out.println(“<p>Hello, ” + user);
out.println(“</body></html>”); out.close(); }
Desenvolvido pelo ESMS.C 18

E x e m p lo d e u m J S P e q u iv a le n te
< h tm l> < b o d y >
<%
S tr i n g u s e r = r e q u e s t.g e tP a r a m e te r ( “ u s u a r io ” ) ;
if ( u s e r = = n u ll)
u s e r = “ W o r ld ” ;
%>
< h 1 > S im p le S e r v le t O u t p u t < /h 1 >
< P > H e llo , < % = u s e r % >
< /b o d y > < /h tm l>
D e s e n v o l v id o p e lo E S M S . C 19

Página recebida no brow ser


 U rl da requisição
 http://servidor/servlet/Sim pleServlet?usuario=R ex
 http://servidor/hello.jsp?usuario=R ex
 C ódigo fonte visto no cliente
<htm l><body>
<h1>Sim ple Servlet O utput<h1>
<P>H ello, R ex
</body >
</htm l>

D esen volvid o p elo E SM S.C 20

12
C om o executar Servlets e JSP
 Para executar Servlets e JSP é preciso im plantá-
los em um W eb C ontainer
 U m W eb C ontainer pode estar executando com o
parte de um servidor H TT P que o repassa as
requisições destinadas a servlets e JSP
 N este curso usarem os o Tom cat W eb C ontainer,
que pode tanto funcionar conectado a outro
servidor com o usar seu próprio servidor W eb
 E m produção geralm ente é acoplado num
servidor de páginas estáticas eficiente
D esen volvid o p elo E SM S.C 21

Estrutura do Tomcat

bin Executáveis (startup.sh , startup.bat)


webapps Contém pastas de contextos
ROOT Contexto raiz default
common Arquivos comuns a todas aplicações
classes Classes utilitárias, beans, servlets
lib Arquivos JAR
conf Arquivos de configuração (server.xml)
logs Logs para todas aplicações
work Contém servlets gerados a partir de JSP
Desenvolvido pelo ESM S.C 22

C om o im plantar um a aplicação
no T om cat
 H á três m aneiras
 T ransferir os arquivos da aplicação (JSP, servlets)
para contextos já reconhecidos pelo servidor
 C onfigurar um novo contexto (server.xm l)
 Im plantar a aplicação com o um W ebA rchive(W A R )
 C ontextos são diretórios devidam ente
configurados que o Tom cat reconhece com o
aplicações W eb
 D ois contextos default: exam ples e R O O T

D esen volvid o p elo E SM S.C 23

13
Como usar o contexto ROOT
 Para usar o contexto ROOT:

Copie arquivos JSP, HTM L, imagens, etc em
$TOM CAT_HOM E/webapps/ROOT
 Coloque beans, classes e servlets em
$TOM CAT_HOM E/webapps/ROOT/W EB-IN F/classes
 Acesse páginas JSP usando
http://servidor:8080/
 Acesse servlets usando
http://servidor:8080/servlet/
Desenvolvido pelo ESM S.C 24

C om o usar o contexto exam ples


 Para usar o contexto exam ples:

C opie arquivos JSP, H TM L, im agens, etc em
$TO M C A T_H O M E/w ebapps/exam ples
 C oloque beans, classes e servlets em
$TO M C A T_H O M E/w ebapps/exam ples/W EB -IN F/classes
 A cesse páginas JSP usando
http://servidor/exam ples/pagina.htm l
 A cesse servlets usando
http://servidor/exam ples/servlet/pacote.C lass

D esenvolvido pelo E SM S.C 25

Contextos
 Contextos são quase a mesma coisa que
aplicações web
 Definem a porta de entrada da aplicação
 Cada nova aplicação requer um novo contexto
(server.xml)
 No Tomcat os contextos estão definidos no
diretório webapps
 Podemos criar novos contextos dentro do
webapps ou em qualquer outro diretório
Desenvolvido pelo ESM S.C 26

14
Contextos
 Todo diretório de contexto tem uma estrutura
padrão
 Diretório raiz (JSP, HTML, imagens, etc)
 Diretório WEB-INF - possui um arquivo de
configuração padrão (web.xml)
 O WEB-INF pode conter dois diretórios
reconhecidos pelo servidor
 /WEB-INF/classes – onde ficam os servlets e classes
utilitárias
 /WEB-INF/lib – onde ficam as bibliotecas JAR que serão
carregadas como parte da aplicação
Desenvolvido pelo ESM S.C 27

Nome do contexto e URL


 Geralmente o nome do contexto aparece na
URL após o nome/porta do servidor
http://serv:8080/contexto/subdir/pagina.html
http://serv:8080/contexto/servlet/pacote.Servlet

Na verdade, o nom e a ser usado


(url) para acessar um servlet está
configurado no web.xm l. Neste
exem plo está com o /servlet/* mas
poderia ser qualquer coisa.

Desenvolvido pelo ESM S.C 28

Configuração da Instalação
 Para que um contexto possa inicializar corretamente,
deve haver um arquivo web.xm l no diretório W EB-
IN F do contexto.
 O arquivo web.xm l configura inúm eros parâmetros
relacionados à aplicação
 Inicialização de servlets
 M apeamentos de nomes de servlets
 Inicialização do contexto
 Parâm etros de servlets
 ...

Desenvolvido pelo ESM S.C 29

15
Exemplo de web.xml (1/3)
Parâmetro que pode ser lido por
<web-app> qualquer componente
<context-param>
<param-name>tempdir</param-name>
<param-value>/tmp</param-value>
</context-param> Instância de
um servlet
<servlet>
<servlet-name>myServlet</servlet-name>
<servlet-class>pacote.myServlet</servlet-class>
<init-param> Parâmetro que pode
<param-name>password</param-name> ser lido pelo servlet
<param-value>123456</param-value>
</init-param> Ordem para carga
<load-on-startup>1</load-on-startup> prévia do servlet
</servlet>
Desenvolvido pelo ESM S.C 30

Exem plo de w eb.xm l (2/3)


...
<servlet-m apping>
<servlet-nam e>m yServlet</servlet-nam e>
<url-pattern>/abacaxi/m yServlet</url-pattern>
</servlet-m apping> Este é um mapeam ento exato. Q uando o
padrão abacaxi/m yServlet aparecer na
U R L o servlet a ser cham ado será o
<servlet-m apping> m yServlet
<servlet-nam e>m yServlet</servlet-nam e>
<url-pattern>/abacaxi/*</url-pattern>
</servlet-m apping> M apeamento de caminho. Q uando
o padrão abacaxi/* for encontrado
então m yServlet será chamado

D esenvolvido pelo E SM S.C 31

Exemplo de web.xml (3/3)


...
<servlet-mapping>
<servlet-name>myServlet</servlet-name>
<url-pattern>*.ext</url-pattern>
</servlet-mapping> Este é um mapeamento de extensão.
Qualquer arquivo que apareça na URL
com a extensão ext na solicitação será
<servlet-mapping> redirecionado para myServlet.
<servlet-name>myServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> Mapeamento default. Este servlet será
chamado se nenhum outro mapeamento
</web-app> combinar com a requisição.

Desenvolvido pelo ESM S.C 32

16
II - Servlets

II - S erv lets
 E ste c ap ítulo co b re o s se g u in tes tó pico s :
 O q u e são S erv lets?
 C iclo d e V ida
 In icializaç ão
 F in alização
 M éto d o s de S erv iço
 C o m o criar u m H T T P serv le t

D ese n vo lv id o p elo E S M S.C 33

O q u e são S erv lets H T T P


 E xtensão java para servidor W eb
 E stendem
javax.servlet.http.H ttpS ervlet
 L idam co m características típicas do
H T T P co m o m étodos G E T , P O S T ,
C ookies, etc

D ese n volvid o p elo E S M S.C 34

C iclo d e V id a
 Q u a n d o o se rv id o r rece b e u m a re q u isiç ão p o r
u m serv le t, ele a rep assa p ara o co n tain e r q u e :
 C ria u m a in stân cia d a classe d o serv let
 C h am a o m éto d o d e inicialização in it()
 C a d a req u isição é tra ta d a p o r u m m éto d o
serv ic e()
 O C o n tain e r cria u m ob je to d e re q u isição
(S erv le tR eq u est) e u m d e resp o sta
(S ertv letR esp o n se) e os p assa co m o p arâm etro
 Q u a n d o o co n ta in er d ec id ir re m o v er o serv let d a
m e m ó ria e le o fin aliza ch am an d o d estro y()
D ese n vo lv id o p elo E S M S.C 36

17
Inicialização de um servlet
 Tarefa realizada apenas um a vez
 O perações com uns : carregar parâm etros de
inicialização, dados de configuração, etc
 Ex: A cessa os parâm etros de
public void init () inicialização
throw s S ervletE xception{
S tring dirIm agens = getInitP aram eter(“im agens”);
if (dirIm agens == null) {
throw new U navailableE xception(‘C onfiguração
Incorreta’);
} }
D esen volvid o p elo E SM S.C 37

F in a liz a ç ã o
O m é to d o d e stro y () é c h a m a d o e p o d e se r
u sa d o p a ra lib e ra r re c u rso s, c o m o c o n e x õ e s
c o m b a n c o d e d a d o s , e tc
 Ex:
p u b lic v o id d e stro y () {
b a n c o .c lo se ();
b a n c o = n u ll;
}

D e se n vo lv id o p e lo E S M S .C 37

Métodos de Serviço
São os métodos que implementam
operações de resposta executadas quando o
cliente envia uma requisição
Todos os métodos de serviço recebem dois
parâmetros: um objeto ServletRequest e
outro ServletResponse
Nos servlets HTTP estes métodos estão
divididos em doPost() e doGet()

Desenvolvido pelo ESMS.C 38

18
Como criar um servlet HTTP
 Crieuma classe que estenda de HttpServlet e
implemente um ou mais dos seus métodos de
serviço:
import javax.servlet.*;
import javax.servlet.http.*;
import javax.io.*;
public class ServletWeb extends HttpServlet {
public void doGet (HttpServletRequest request,
HttpServletResponse response)
throws IOException {
PrintWriter out = response.getWriter();
response.setContentType(“text/html”);
out.println(“<h1>Hello, World!</h1>”);
out.close();
}}
Desenvolvido pelo ESMS.C 39

C o m o u sa r d o G e t() e d o P o st()
 U se d o G e t() p a ra re c e b e r re q u is iç õ e s
GET
 L in k s c lic a d o s o u U R L d ig ita d a s
d ire ta m e n te
 A lg u n s fo rm u lá rio s q u e u sa m G E T
 U se d o P o st() p a ra re c e b e r d a d o s d e
fo rm u lá rio s
 O JS P tra ta in d isc rim in a d a m e n te o s d o is
m é to d o s
D e se n v o lv id o p e lo E S M S .C 40

C o m o a cessar p arâm etro s d a


so licita ção
 T an to p a ra G E T co m o p ara P O S T u se
req u e st.g e tP ara m eter()
S trin g p arâm etro = req u e st.g etP aram e ter(“n o m e” );
 P arâm e tro s c o m o m esm o n o m e p o d e m esta r
rep etid o s, n este c aso , g e tP ara m eter() irá
reto rn ar so m en te a p rim eira o co rrên cia. P a ra
o b ter to d as u se
S trin g [] p aram s =
req u est.g etP aram eterV alu es(“n o m e”);

D ese n vo lv id o p elo E S M S.C 41

19
Como gerar uma resposta
 Primeiro é preciso obter de response um fluxo
de saída
Writer out = response.getWriter();
 Deve-se também definir o tido de dados a ser
gerado. Isso é importante para que o browser
saiba exibir as informações
response.setContentType(“text/html”);
 Depois, pode-se gerar os dados imprimindo-os
no objeto de saída (out) obtido anteriormente
out.println(“<h1>Hello, world!</h1>”)
Desenvolvido pelo ESMS.C 42

Exercícios

1 – Crie um servlet chamado hello.java que deve ler o valor de um parâmetro de


inicialização e imprir na tela “Hello, <valor do parâmetro>!”. O parâmetro deve se
chamar nome.

a) Abra um editor de texto qualquer e digite o código abaixo:

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class hello extends HttpServlet {

public void doGet (HttpServletRequest request,


HttpServletResponse response)
throws IOException {

PrintWriter out = response.getWriter();


response.setContentType(“text/html”);
out.println(“<h1>Hello, ” + getInitParameter(“nome”)+”</h1>”);

}
}

b) Salve o arquivo no seu diretório de exercícios com o nome hello.Java


c) Entre no prompt de comando e compile o arquivo : javac hello.Java
d) Copie o arquivo hello.class que foi gerado com a compilação para o diretório WEB-
INF/classes do seu contexto. Com isso você está instalando o servlet na sua aplicação.

20
e) Vamos agora configurar o arquivo web.xml com o servlet hello acrescentando o
parâmetro de inicialização que este está lendo. Acrescente as seguintes linhas no /WEB-
INF/web.xml:

<servlet>
<servlet-name>
hello
</servlet-name>
<servlet-class>
hello
</servlet-class>
<init-param>
<param-name>nome</param-name>
<param-value>SEUNOME</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/servlet/hello</url-pattern>
</servlet-mapping>

f) Uma vez tendo alterado o arquivo web.xml, você deve fazer um reload no contexto.
Para isso o Tomcat disponibiliza uma página de gerenciamento que pode ser acesada em
http://servidor:8080/manager/html. Entre nesta página, procure pelo seu contexto e
clique em reload.

g) Agora é só testar acessando a URL = http://servidor/contexto/servlet/hello

2) Modifique o servlet anterior de forma que este leia o nome do parâmetro de


solicitação e não mais dos parâmetros de inicializaação. Utilize o método
getParameter() do objeto HttpServletRequest. Teste sua aplicação passando um valor na
URL:

http://servidor/contexto/servlet/hello?nome=<SEUNOME>

21
III - Scripts JSP
Este capítulo cobre os seguintes tópicos :

− Elementos de criação de scripts


− Declarações
− Expressões
− Scriptlets
− Controle de Fluxo
− Comentários
− Diretivas JSP

Vimos que é possível utilizar JavaBeans para mantermos a separação entre apresentação
e implementação e as vantagens que isso proporciona, principalmente em grandes
projetos. No entanto, esta abordagem “purista” para o desenvolvimento de JSP nem
sempre é a mais adequada para todos os casos. Para páginas simples, que precisam ser
implementadas em curto espaço de tempo, talvez seja melhor uma abordagem mais
direta e prática.

Neste capítulo, mostraremos como criar páginas JSP que mesclam HTML e código Java
para obtenção do conteúdo dinâmico. Estes códigos são denominados scripts e, apesar
de JSP permitir linguagens alternativas para criá-los, focaremos aqui exclusivamente em
scripts na linguagem Java.

Elementos de Criação de Scripts


• Elementos de criação de scripts permitem
que os programadores embutam diretamente
código em uma página JSP
• Três tipos de elementos de criação de
scripts :
– declarações
– scriptlets
– expressões

Desenvolvido pelo ESMS.C 7

Os elementos de criação de scripts permitem que os programadores embutam código


Java diretamente numa página JSP, inclusive código que gera output para aparecer nos
resultados enviados de volta para o usuário.
JSP oferece três tipos de elementos de criação de scripts : declarações, scriptlets e
expressões.

22
Hello World !
Para quebrar o gelo, vamos analisar nossa
primeira página JSP. Ela lê um parâmetro da
solicitação e utiliza seu valor para apresentar
uma mensagem na tela.
<html>
<body>
<h1> <%= request.getParameter("text") %> </h1>
</body>
</html>

Desenvolvido pelo ESMS.C 8

Para construir uma página usando JSP, você geralmente escreve o texto HTML
normalmente e inclui o código entre as tags JSP. As tags normalmente começam com
"<%" e terminam com "%>". Vamos mostrar uma possibilidade de implementação para
o clássico exemplo do "Hello World” :

Ex. helloworld.jsp :

<html>
<body>

<h1><%= request.getParameter("msg") %></h1>

</body>
</html>

Se fizermos http://.../helloworld.jsp?msg=Hello+World receberemos numa página


HTML o conteúdo do parâmetro msg,, que foi montado na própria URL, como resposta
da solicitação. Se você verificar o código da página que apareceu no seu browser, verá o
seguinte:

<html>
<body>

<h1>Hello World </h1>

</body>
</html>

O que aconteceu foi que o servidor JSP executou os comandos entre as tags especiais
"<%" e "%>", gerou e enviou para o browser um código puramente HTML.

23
Declarações
• Servem para definir variáveis e métodos
específicos para uma página JSP
• Sua sintaxe é : <%! declarações %>
• Os métodos e variáveis declarados podem
ser referenciados por outros elementos de
criação de script dentro da mesma página
JSP independente da ordem na qual a
declaração ocorre em relação a estes
elementos
Desenvolvido pelo ESMS.C 9

Declarações
• Declaração de variáveis :
<%! int x=0, y; String text = “Texto”; %>
• Declaração de métodos :
<%! int soma (int x, int y) { return (x + y); } %>
• As variáveis aqui declaradas são criadas na
inicialização da página e seus valores são
compartilhados por todos que a acessarem.Se
uma pessoa mudar o valor de x para 1, todos
que acessarem o servlet depois disso verão x=1
Desenvolvido pelo ESMS.C 10

Os métodos jspInit e jspDestroy

Estes são métodos especiais para tratar os eventos de inicialização (jspInit) e finalização
(jspDestroy) dos servlets. Se o método jspInit() for definido, pode-se garantir que o
container JSP o chame depois que a classe de servlet tenha sido instanciada, mas antes
que a primeira solicitação seja processada. Similarmente, se o método jspDestroy()
estiver definido numa página JSP, este será executado quando o container JSP precisar
descartar a classe de servlet, seja porque o container está sendo desligado, ou porque a
página não tenha sido solicitada recentemente e o container precisa liberar recursos (ex.
memória). O formato geral para declará-los é :

public void jspInit () { /*Código de Inicialização*/ }


public void jspDestroy () {`/*Código de Finalização*/ }

24
Expressões
• O resultado da avaliação de uma expressão
é inserido no output da página no lugar da
tag de expressão original
• Sua sintaxe é : <%= expressão %> (não
requer ; no final)
• Não há restrição quanto ao tipo de retorno
das expressões
• Exs:<%= “Mensagem” %> --> imprime : Mensagem
<%= msg %> --> imprime o conteúdo da var. msg
<%= fatorial(0) %> --> imprime o resultado da func
Desenvolvido pelo ESMS.C 11

As declarações são usadas para adicionar variáveis e métodos a uma página JSP, mas
não são capazes de contribuir diretamente para o output da página. As expressões em
JSP possuem o objetivo explícito de geração de output.

Pode-se observar que na sintaxe da expressão não há o ponto e vírgula no final da


mesma. Isso porque o ponto e vírgula em Java é um delimitador de instrução e não é
isto que estamos criando quando especificamos uma tag de expressão. Já que não é
possível acrescentar instruções numa tag de expressão, é claro que não se pode incluir
if/then, pois estes correspondem a instruções em Java, como fazer output condicional
utilizando-se uma tag de expressão ? Felizmente Java aceita o operador condicional
terciário, que retorna um valor baseado no resultado de um teste condicional. A sintaxe
do operador terciário é a seguinte :

test_expr ? true_expr : false_expr

Exemplo :

<%= (hours < 12 ? “AM” : “PM” %>

Neste exemplo, hours é verificada para determinar se é menor que 12. Se sim, o
operador terciário retorna a cadeia “AM”, caso contrário retorna “PM”. O valor
retornado é adicionado ao output da página.

25
Scriptlets
• São blocos de código executados cada vez
que a página JSP é processada
• Servem para criação de scripts de objetivos
gerais
• Sua sintaxe é : <% scriptlet %>
• Uma variável definida num scriptlet estará
disponível para uso em expressões e
scriptlets subseqüentes na mesma página

Desenvolvido pelo ESMS.C 12

Os scriptlets são utilizados para criação de códigos arbitrários, que realizam qualquer
processamento que se queira. Dentro de uma tag de scriptlet é possível declarar
variáveis, instanciar objetos, imprimir no output da página, enfim, realizar qualquer
codificação válida com a linguagem de script que está sendo utilizada, no nosso caso
Java.

Vamos analisar o exemplo abaixo :

1 - <html>
2 - <body> <h1>Intruder Alert</h1>
3 - <% GameGrid grid = GameGrid.getGameGrid();
4- Recognizer r1 = new Recognizer (grid,0,0);
5- Recognizer r2 = new Recognizer (grid,100,100);
6- r1.findProgram (“Flynn”);
7- r2.findProgram (“Flynn”); %>
8 - <h2> Status </h2>
9 - <ul>
10 - <li> Recognizer : <%= r1.statusReport() %>
11 - </ul>
12 - Alert Level : <%= grid.alertLevel() %>
13 - </body>
14 - </html>

Misturado ao código HTML temos o código Java. Na linha 3 a variável grid recebe uma
instância da classe GameGrid retornada pelo método getGameGrid(). Nas linhas 4 e 5
novas instâncias da classe Recognizer são criadas e atribuídas às variáveis r1 e r2.
Como os scriptlets são executados toda vez que a página é solicitada, novas instâncias
dessa classe são criadas e atribuídas a r1 e r2 a cada nova solicitação. Na linha 10 uma
tag de expressão é utilizada para imprimir o retorno do método statusReport() executado
a partir da variável r1. Só foi possível acessar r1 na linha 10 porque ele foi declarado
num scriptlet anterior a este ponto.

26
Exercícios

1 – Criar uma página JSP que possua uma variável soma, do tipo inteiro, inicializada
com 0 e definida numa tag de declaração. Incrementar essa variável de 10 cada vez que
a página for solicitada e imprimir o seu conteúdo. Criar uma outra variável sub, também
do tipo inteiro, inicializada com 100 e declarada dentro de um scriptlet. Essa variável
deve ser subtraída de 10 cada vez que a página for solicitada. Explique qual está sendo o
comportamento das variáveis após solicitações simultâneas da página e o motivo do
mesmo.

2 – Fazer uma página JSP que receba dois números reais (double) como parâmetros
(num e porcent) e execute um método que calcule a porcentagem porcent de num
retornando também um double. O resultado deve ser impresso na tela.

Dicas : Para ler o valor de um parâmetro utilizar : request.getParameter(“nome”) que


retorna uma string
Para transformar uma String em um double utilizar : Double.parseDouble
(“string”) que retorna um double referente a String passada como parâmetro

3 – Fazer uma página JSP que recebe um número inteiro como parâmetro, calcule seu
fatorial através do método fatorial e imprima o resultado na tela. O método fatorial pode
ser como descrito abaixo :

long fatorial (int x ) {

if (x == 0) return 1
else return x * fatorial (x-1) ; }

Dica : Para converter uma String para um número inteiro utilizar : Integer.parseInt
(“string”)

27
Embora já possamos escrever algumas aplicações em JSP com o que já aprendemos até
agora, elas serão ainda fracas. Um dos grandes potenciais de qualquer linguagem de
programação é a utilização de controles de fluxo (condicionais e loops) para executar
diferentes partes de um programa baseado em testes. Nas próximas páginas
aprenderemos os seguintes tópicos:

• Comandos condicionais;
• Comandos de loops

Controle de Fluxo
• Comandos Condicionais : IF
<html> <body>
<% java.util.Date dateNow = new java.util.Date();
int hourNow = dateNow.getHours(); %>
<% if ((hourNow >= 5) && (hourNow < 13)) { %>
<font face="verdana">Bom Dia!!!</font>
<% } else if ((hourNow >= 13) && (hourNow < 19)) { %>
< font face="verdana">Boa Tarde!!!</font>
<% } else if ((hourNow >= 19) && (hourNow < 24)) { %>
<font face="verdana">Bom Noite!!!</font>
<% } else { %>
<font face="verdana">Boa Madrugada!!!</font>
<% } %>
</body></html>
Desenvolvido pelo ESMS.C 15

Condicionais if contém a palavra-chave if, seguida de um teste booleano, e de uma


instrução (na maioria das vezes um bloco de instruções) para ser executada se o teste for
verdadeiro (exemplo no arquivo if.jsp).

Controle de Fluxo
• Comandos Condicionais : switch
<html> <body>
<% java.util.Date dateNow = new java.util.Date();
int monthNow = (dateNow.getMonth()+1); %>
<% String mes;
switch (monthNow){
case 1: mes="Janeiro"; break;
case 2: mes="Fevereiro"; break;
...
case 10: mes="Outubro"; break;
case 11: mes="Novembro"; break;
default: mes="Dezembro"; break;
} %>
<font face="verdana"> Nós estamos em <%= mes %></font>
</body></html>
Desenvolvido pelo ESMS.C 16

28
Na instrução switch, o teste (um tipo primitivo de byte, char, short ou int) é comparado
com cada valor em questão. Se um valor coincidente é achado, a instrução (ou
instruções) depois do teste é executada. Se nenhum valor for encontrado, a instrução
default é executada (exemplo no arquivo switch.jsp).

Controle de Fluxo
• Comandos de loops : for
<html>
<body>
<% for (int i = 2; i < 8 ; i++) { %>
<font size = <%= i %> > Bom Dia!!! - Fonte: <%= i %>
</font>
<% } %>
</body>
</html>

Desenvolvido pelo ESMS.C 17

O loop for (exemplo no arquivo for.jsp), repete uma instrução ou um bloco de


instruções algum número de vezes até que a condição seja satisfeita. Loops for são
freqüentemente usados para simples iterações na qual você repete um bloco de
instruções um certo número de vezes e então pára; mas você pode usar loops for para
qualquer espécie de loop. A sintaxe do loop for no Java é a seguinte:

for (initialization ; test ; incremet)


{
statements
}

Onde:
initialization - é uma expressão que inicia o começo do loop;
test - é o teste que ocorre depois de cada passo do loop;
increment - é qualquer chamada de expressão ou função.

29
Controle de Fluxo
• Comandos de loops : while
<html>
<body>
<% int i = 0;
while (i < 8) { %>
<font size = <%= i %>> Bom Dia!!! - Fonte: <% = i %>
</font> <br>
<% i++; } %>
</body>
</html>

Desenvolvido pelo ESMS.C 18

O loop while (exemplo no arquivo while.jsp) é usado para repetir uma instrução ou
bloco de instruções até que uma condição particular seja verdadeira. Loops while se
parecem com o seguinte:

while ( condition) {

bodyOfLoop

Observe que se a condição é inicialmente falsa na primeira vez que é testada o corpo do
loop while nunca será executado. Se você precisa executar o corpo, pelo menos uma
vez, você pode usar o código do..while que será visto a seguir.

Controle de Fluxo
• Comandos de loops : do while
<html>
<body>
<% int i = 0;
do { %>
<font size=<%= i %>>Bom Dia!!! - Fonte: <%= i %>
</font> <br>
<% i++;
} while ( i < 8 ); %>
</body></html>

Desenvolvido pelo ESMS.C 19

30
O loop é exatamente como o loop while, exceto pelo fato de o loop do executar uma
dada instrução ou bloco até que uma condição seja falsa. A diferença principal entre os
dois é que os loops while testam a condição antes de iniciar o loop, tornando possível
que o corpo do loop nunca seja executado caso a condição seja inicialmente falsa. Os
loops do...while executam pelo menos uma vez antes de testar a condição (exemplo no
arquivo do_while.jsp)

Os loops do...while tem o seguinte formato:

do {

bodyOfLoop

}
while ( condition );

Interrupção de Loops

Em todos os loops (for, while e do), o loop termina quando a condição que você está
testando é atingida. Porém, em algumas situações você desejará sair do loop antes do
seu término normal. Para isso, você pode usar as palavras chaves break e continue.

Controle de Fluxo
• Interrupção de loops : break
<html>
<body>
<% int j;
for (int i = 1; i < 8 ; i++) {
j = i%5; => j recebe o resto da divisão por cinco
if (j == 0){ break; } %> => se for 0 é divisível por 5 e pára
<font size= <%= i %>> Bom Dia!!! - Fonte: <%= i %>
</font> <br>
<% } %>
</body></html>
Desenvolvido pelo ESMS.C 20

No exemplo acima, o código dentro do loop é executado até que a variável i assuma um
valor que seja divisível por 5. Quando isso ocorre, o loop é finalizado e o programa
continua a ser executado após o final do código do loop (exemplo no arquivo break.jsp).

31
Controle de Fluxo
• Interrupção de loops : continue
<html>
<body>
<% int j;
for (int i = 1; i < 8 ; i++) {
j = i%5;
if (j == 0){ continue; } %> => quando i for divisível por 5,
a linha não será impressa
<font size=<%= i %>>Bom Dia!!! - Fonte: <%= i %>
</font><br>
<% } %>
</body>
</html>
Desenvolvido pelo ESMS.C 21

A palavra chave continue pára o loop e começa novamente na próxima iteração.


continue é útil quando você quer ter situações de casos especiais dentro de loop. Esse
código é semelhante ao anterior, contudo, ao invés de finalizar a execução do loop, ele o
reinicia em uma nova iteração. O resultado obtido é a geração de 6 linhas de código
html (a linha cujo teste do if foi verdadeiro, ou seja, onde a variável i assumiu um valor
divisível por 5, não foi gerada) (exemplo no arquivo cotinue.jsp).

Comentários
• Dois tipos de comentários :
– Conteúdo : é quando utilizamos o comentário
HTML dentro da página JSP.
• Ex : <!-- Comentário sobre o conteúdo de x = <%=
x %> -->
– JSP : O corpo deste comentário é ignorado.
Serve principalmente para depuração.
• Ex : 5! = <%= fact(5) %> <br>
<%-- 6! = <%= fact(6) %> <br> --%>
• Comentário da linguagem de script utilizada. No
caso de java : /* comentário */ ou // comentário
Desenvolvido pelo ESMS.C 22

Comentário de Conteúdo: esses comentários são transmitidos de volta para o


navegador como parte da resposta de JSP e são visíveis na visualização do código da
página.

Comentários JSP: não são enviados para o cliente e são visíveis apenas nos arquivos
fonte JSP originais. O corpo do comentário é ignorado pelo container JSP.

32
Exercícios :

4 – Faça uma página JSP que receba como parâmetro um número inteiro e calcule o
fatorial de 0 até este número e imprima os resultados. (Utilize o método para calcular
fatorial dado no exercício 3)

5 – Faça uma página que receba o valor de um salário e uma porcentagem como
parâmetros. Calcule a porcentagem especificada sobre o salário, a qual representa um
aumento do mesmo, utilizando a função func criada no exercício 2. Se o resultado for
menor que R$ 400,00 , imprima “Você recebeu um aumento de <aumento> ! Teu
emprego é um lixo, sai logo daí !”, se o resultado for maior que R$ 400,00 e menor que
R$ 2.999,99, imprima “Você recebeu um aumento de <aumento> ! Até que teu emprego
não é ruin não.”, mas se o resultado for superior a R$ 2.999,99 imprima “Seu novo
salário é de <novo_salario> ! Você é político ?”.

6 – Faça uma página JSP que receba três números inteiros como parâmetros : min, max
e div. Deve ser impresso os números de min a max na tela até que se encontre neste
intervalo um número divisível por div e então o laço deve ser interrompido. Se nenhum
número for encontrado, todos os números entre min e max (inclusive) serão impressos.

33
O último tópico que veremos neste capítulo trata das diretivas JSP. As diretivas são
usadas para fornecer informações especiais ao container JSP sobre a página quando esta
é compilada para servlet. Elas não produzem qualquer output que seja visível, ao invés
disso, elas geram efeitos colaterais que mudam o modo que o container JSP processa a
página. Existem dois tipos principais de diretivas: page e include.

Diretivas JSP
• As diretivas são usadas para fornecer
informações especiais ao container JSP
sobre a página quando esta é compilada
para servlet. Elas não produzem qualquer
output que seja visível, ao invés disso, elas
geram efeitos colaterais que mudam o modo
que o container JSP processa a página.
• Dois tipos : page e include

Desenvolvido pelo ESMS.C 23

Diretivas JSP
• Diretiva page : define atributos que afetam
toda a página JSP
• Sintaxe :
<%@ page attribute1=“valor1” attribute2 =
“valor2” attribute3= ... %>
ou
<%@ page attribute1 = “valor1” %>
<%@ page attribute2 = “valor2” %> ...
Desenvolvido pelo ESMS.C 24

34
Diretivas JSP
• Atributos da diretiva page :
– info : Permite ao autor adicionar uma cadeia de
documentação à página que sumariza sua
funcionalidade. O valor padrão para o atributo
info é a cadeia vazia. Pode ser recuperada pelo
método getServletInfo.
– Ex :
<%@ page info = “Controle de usuários,
Copyright 2002 by ESMS.C” %>
Desenvolvido pelo ESMS.C 25

Diretivas JSP
• Atributos da diretiva page :
– language : Define a linguagem de criação de
scripts da página. O padrão para este atributo é
java.

– Ex :
<%@ page language = “java” %>

Desenvolvido pelo ESMS.C 26

35
Diretivas JSP
• Atributos da diretiva page :
– contentType : Define o tipo MIME, i.e, o tipo
de informação contida em uma resposta de
HTTP. Os tipos mais comuns para JSP são :
“text/html” (padrão), “text/xml” e “text/plain”,
indicando respostas em HTML, XML e texto.
– Ex :
<%@ page contentType = “text/xml” %>

Desenvolvido pelo ESMS.C 27

Diretivas JSP
• Atributos da diretiva page :
– extends : Identifica a super classe a ser usada
pelo container quando ele está traduzindo a
página JSP em um servlet Java. Geralmente
deixamos o próprio container selecionar a super
classe para a página pois isso tipicamente
fornece a melhor peformance.

Desenvolvido pelo ESMS.C 28

36
Diretivas JSP
• Atributos da diretiva page :
– import : Permite especificar quais pacotes
serão importados, estendendo assim o conjunto
de classes que podem ser referenciadas em uma
página. É o único atributo que pode se repetir.
– Ex :
<%@ page import = “java.util.List” %> => importa
a classe List
<%@ page import = “java.util.* , java.text.*” %> =>
importa todas as classes do pacote java.util e
java.text
Desenvolvido pelo ESMS.C 29

Diretivas JSP
• Atributos da diretiva page :
– session : Indica se uma página participa ou não
do gerenciamento de sessão. O valor padrão é
true. Se a página não irá utilizar recursos de
sessão, deve-se passá-lo para false pois isso
resulta em ganho de performance.
– Ex :
<%@ page session = “false” %>

Desenvolvido pelo ESMS.C 30

37
Diretivas JSP
• Atributos da diretiva page :
– buffer : Controla o uso da saída bufferizada. O
padrão é um buffer de 8kb.
– Ex :
<%@ page buffer=“none” %> => sem buffer

<%@ page buffer=“12kb” %> => define um


buffer de 12 kb

Desenvolvido pelo ESMS.C 31

Saída bufferizada

Uma vez que o servidor HTTP tenha começado a enviar um documento para um
navegador, ele não pode “mudar de idéia” e depois pedir para o navegador não exibir o
conteúdo enviado. O servidor Web poderia cancelar a transmissão do documento, mas o
navegador exibiria qualquer conteúdo recebido até então. Se, a medida que uma
página JSP fosse sendo processada o conteúdo HTML gerado fosse enviado
diretamente para o servidor Web, para este encaminhar a resposta para o
navegador, ocorreriam problemas como :

• Numa página HTML todo o cabeçalho (de solicitação e de resposta) deve vir antes
que o corpo da página. Nos cabeçalhos de respostas são definidas informações como
armazenamento em cache da página e, mais importante, dados de cookies. Se uma
página JSP quisesse definir cookies, teria que defini-los antes que qualquer output
de JSP fosse gerado para ser enviado como corpo da resposta, ou seja, no início da
página. Se quiséssemos por algum motivo gerar conteúdo do corpo e depois definir
um cookie, seria muito tarde
• Outro problema está relacionado a erros de processamento. Se um erro ocorreu no
meio do processamento de uma página, todo conteúdo gerado antes daquele
momento apareceria no navegador seguido da mensagem de erro. Não seria possível
descartar o output anterior e exibir apenas a mensagem de erro, ou encaminhar o
controle para uma página especial de tratamento de erros.

Com a bufferização da saída essas limitações foram superadas em JSP. Enquanto


uma página está sendo processada, o conteúdo gerado não é enviado diretamente
para o navegador. Ao invés disso, este é armazenado temporariamente num buffer
de saída. Apenas depois que a página inteira tiver sido processada, o output
armazenado no buffer será enviado para o navegador como corpo de uma resposta de
HTTP do servidor. Isso permite especificar informações de cabeçalho em qualquer
ponto da página. Torna possível também lidar com erros, pois o conteúdo gerado como
resposta pode ser descartado (se um erro é detectado, todo conteúdo gerado até então
pode ser descartado, pois está no buffer, e uma nova resposta pode ser gerada).
38
Diretivas JSP
• Atributos da diretiva page :
– autoFlush : Também controla a saída
buferizada. Se definido como true, quando o
buffer fica cheio seu conteúdo é enviado para o
servidor HTTP para transmissão ao navegador
solicitante. Se definido como false, quando o
buffer fica cheio é disparada uma exceção,
interrompendo o processamento e enviando um
erro como resposta. O padrão para este atributo
é true.
– Ex : <%@ page autoFlush=“true” %>
Desenvolvido pelo ESMS.C 32

Este atributo controla o comportamento do container JSP quando o buffer de saída da


página fica cheio. Se estiver definido como true (o padrão), o buffer de saída será
automaticamente esvaziado e seu conteúdo atual enviado para o servidor HTTP para
transmissão ao navegador da web solicitante. O processamento da página então
continua, com qualquer e todo conteúdo novo sendo buferizado até que o buffer
novamente fique cheio ou o final da página seja alcançado. Uma vez que o buffer
tenha sido esvaziado não é mais possível que a página JSP defina cabeçalhos de
resposta ou encaminhe o processamento para uma página JSP diferente.

Caso o atributo esteja definido como false, quando o buffer fica cheio o container irá
disparar uma exceção e exibirá uma página de erro no navegador que solicitou a página.

Diretivas JSP
• Atributos da diretiva page :
– isThreadSafe : Quando definido para true (o
padrão), um novo encadeamento é criado para
tratar de cada solicitação para a página, de
modo que múltiplas solicitações para a página
sejam tratadas simultaneamente. Caso seja
false, o container irá reponder a cada solici-
tação sequencialmente, na ordem em que foram
recebidas.
– Ex : <%@ page isThreadSafe=“true” %>

Desenvolvido pelo ESMS.C 33

39
O atributo isThreadSafe é usado para indicar se uma página é capaz de responder a
múltiplas solicitações simultâneas. Quando é definido para false, o container JSP
expedirá solicitações destacadas para a página sequencialmente, na ordem em que elas
foram recebidas, esperando a solicitação atual terminar seu processamento antes de
iniciar o próximo. Quando estiver definido para true (o padrão), um novo encadeamento
(uma nova thread) é criado para tratar de cada solicitação para a página, de modo que
múltiplas solicitações sejam tratadas simultaneamente.

Se for possível, este atributo deve estar definido para true, caso contrário, a performance
sofrerá dramaticamente sempre que múltiplos usuários tentarem acessar a página ao
mesmo tempo, já que cada usuário terá que esperar até que todas as solicitações
anteriormente submetidas tenham sido atendidas antes que o processamento da sua seja
iniciado. Se a página estiver com tráfego muito pesado, ou sua geração de conteúdo for
muito intensa em relação ao processamento, esta espera provavelmente não será
aceitável pelos usuários.

Para saber de forma prática se uma página pode estar com este atributo definido como
true, tenha em mente o seguinte :

• Vimos que o container JSP cria threads para tratar de solicitações a uma página e
que threads referentes ao mesmo servlet compartilham espaço de memória. Isso
pode ser utilizado vantajosamente para fins de melhoria de performance.
• A memória compartilhada é aquela definida pelas variáveis declaradas dentro da
tag <%! %> e, uma vez que seu valor tenha sido modificado, o novo valor será
visível a todas as threads do mesmo servlet. Variáveis definidas dentro de
scriptlets são locais a cada thread.
• A definição de variáveis compartilhadas deve ser feita com critério, pois a
seguinte situação pode ocorrer : imagine que X seja uma variável compartilhada
e que João submeteu o valor 10 para X. No final desta página existe o seguinte
código : <%= X %>, que deve imprimir o conteúdo de X submetido por João.
Antes que a thread que estava tratando da solicitação de João terminasse seu
processamento (e imprimisse o valor de X), Pedro faz um acesso a essa mesma
página submetendo o valor 20 para X. Suponha então que o sistema operacional
(que é o responsável por definir qual thread estará ocupando o processamento
num dado instante) pára o processamento da thread de João e coloca a de Pedro
no lugar. A thread de Pedro muda o valor de X para 20, ocupa o processador por
um tempo e então é retirada pelo sistema operacional que recoloca a thread de
João para terminar seu processamento. Quando a thread de João chega no
comando para imprimir o conteúdo de X, irá imprimir 20 e não 10 como havia
submetido João, causando um resultado errôneo.

Para resolver este tipo de inconsistência, pode-se passar o atributo isThreadSafe para
false, pois assim garante-se que cada thread seja processada até o seu término antes que
outra ganhe o direito de processamento, porém, como já vimos, perde-se totalmente as
otimizações de performance do container . O mais indicado é utilizar recursos como o
synchronized quando houver o potencial para inconsistências, ou ainda, considerar a
possibilidade de definir a variável como local (dentro de um scriptlet).

40
Diretivas JSP
• Atributos da diretiva page :

– errorPage : Define uma página alternativa a


ser exibida se um erro (não tratado) ocorrer
enquanto o container estiver processando a
página. A página de erro deve ser local e é
especificada da seguinte forma :
<%@ page errorPage = “/webdev/error/error.jsp ” %>

Desenvolvido pelo ESMS.C 34

Diretivas JSP
• Atributos da diretiva page :

– isErrorPage : Quando true, define que a


página serve como página de erro para uma ou
mais páginas JSP. O valor padrão para este
atributo é false.

– Ex : <%@ page isErrorPage = “true” %>

Desenvolvido pelo ESMS.C 35

Diretivas JSP
• Diretiva include : Permite incluir o
conteúdo de um arquivo em outro. A
diretiva tem o efeito de substituir a si
mesma pelo conteúdo do arquivo indicado.
• O conteúdo pode ser texto estático (HTML)
ou comandos JSP, que serão processados
como se fossem parte da página original.
• Ex : <%@ include file=“localURL” %>
41
Desenvolvido pelo ESMS.C 36
Exercícios :

<%@ isThreadSafe=”true” %>

<%!
//classe que implementa um pool de conexões para um banco de dados
DBConectionPool pool = new DBConectionPool();
//a variável con representa uma conexão para um banco de dados
Conection con = pool.getConection();
//classe que implementa as operações de inserção, deleção e update nas tabelas
DBComands comandos = new BDComands(con);

String Nome, CPF, RG;


%>

<%
Nome = request.getParameter(“nome”);
CPF = request.getParameter(“cpf”);
RG = request.getParameter(“rg”);
Comandos.Insert(Nome,CPF,RG,”EMPREGADO”);
%>

Com base no código acima, responda as questões de 7 a 10 :

7 – As variáveis pool e con deveriam estar declaradas dentro do scriptlet ? Por quê ?

8 – Esta página está suscetível a produzir resultados inconsistentes? Explique.

9 – Caso possa ocorrer algum problema, que mudanças deveriam ser feitas na página
para evitá-lo.

10 – Faz sentido ter uma variável compartilhada sendo que seu valor está relacionado
com os dados específicos de um usuário ?

11 – Crie uma página com o atributo buffer = “1kb” e o atributo autoFlush = “false”.
Primeiramente, faça com que ela imprima apenas uma vez a frase “Testando a
bufferizacao !” e a execute. Agora modifique-a para que ela imprima a mesma frase
1000 vezes e a execute novamente. Explique o resultado da primeira e da segunda
execução relacionando-o ao buffer.

42
IV – Objetos Implícitos
Este capítulo cobre os seguintes tópicos :

− Objetos Implícitos
− Relacionados a Servlets
− Relacionados ao Input/Output
− Contextuais
− Tratamento de Erros
− Ações

Como já vimos anteriormente, podemos criar, dentro de scriptlets na página JSP,


instâncias de uma classe Java e manipulá-las a fim de produzir conteúdo dinâmico. Por
exemplo, podemos criar um objeto de uma classe que acessa uma base de dados e então
usar métodos desse objeto para exibir na página uma consulta. Ou seja, através da
manipulação desse objeto, quer seja acessando seus métodos ou suas variáveis,
podemos gerar conteúdo na página JSP. Além de objetos como esses, que estão
completamente sobre o controle do programador, o container JSP se encarrega de
instanciar automaticamente, durante a execução de uma página JSP, alguns objetos. Tais
objetos podem ser usados dentro da página JSP e são conhecidos como "Objetos
Implícitos", pois sua disponibilidade em uma página JSP é automática. Assim como
todo objeto em Java, cada objeto implícito é uma instância de uma classe ou interface e
segue uma API correspondente. Abaixo segue um resumo dos objetos implícitos
disponíveis em JSP, suas respectivas classes/interfaces e uma pequena descrição do
objeto.
Objetos implícitos de JSP e suas APIS para aplicações de HTTP.
Objeto Classe ou Interface Descrição
page javax.servlet.jsp.HttpJspPage Instância de servlet da página
config javax.servlet.ServletConfig Dados de configuração de servlet
request javax.servlet.http.HttpServletRequest Dados de solicitação, incluindo parâmetros
response javax.servlet.http.HttpServletResponse Dados de resposta
out javax.servlet.jsp.JspWriter Fluxo de saída para conteúdo da página
session javax.servlet.http.HttpSession Dados de sessão específicos de usuário
Application javax.servlet.ServletContext Dados compartilhados por todas as páginas de aplicação
pageContext javax.servlet.jsp.PageContext Dados de contexto para execução da página
exception javax.lang.Throwable Erros não capturados ou exceção

Os nove objetos implícitos fornecidos por JSP podem ser classificados da seguinte
forma:
• objetos relacionados ao servlet da página (page, config) : Os dois objetos
implícitos de JSP nesta categoria se baseiam na implementação da página JSP como
um servlet.
• objetos relacionados ao output e input da página (request, response, out) : Os
objetos classificados nessa categoria se concentram na entrada e saída (input/output)
de uma página JSP.
• objetos contextuais (application, session, pageContext) : Os objetos implícitos
dessa categoria fornece à página JSP acesso ao contexto dentro do qual ela está
respondendo.
• objetos resultantes de erros (exception) : Esta última categoria dos objetos
implícitos fornece apenas um objeto que é usado no tratamento de erros dentro de
uma página JSP.

43
Objetos Relacionados a Servlets
• Objeto page : O objeto page representa a
própria página JSP ou, mais
especificamente, uma instância da classe de
servlet na qual a página foi traduzida.
• Ex :
<%@ page info="Página de Teste" %>
Page Info :
<%= ( (javax.servlet.jsp.HttpJspPage)page).getServletInfo()
%>
Esta expressão irá imprimir o valor da cadeia de documenta-
ção da página
Desenvolvido pelo ESMS.C 38

Objetos Relacionados a Servlets


• Objeto config: Contém os dados de
configuração do servlet definidos como
parâmetros de inicialização.
• Alguns métodos para recuperar parâmetros
de inicialização de servlet:
– getInitParameterNames() : Recupera os nomes
de todos os parâmetros.
– getInitParameter(name) : Recupera o valor do
parâmetro nomeado.
Desenvolvido pelo ESMS.C 39

O objeto config é uma instância da interface javax.servlet.ServletConfig. Os valores


para os parâmetros de inicialização são especificados através do arquivo descritor de
acionamento de uma aplicação da web (no caso do container Tomcat – http://
jakarta.apache.org – este arquivo é o web.xml). Veja o exemplo abaixo :

<%! public void jspInit(){


String username = config.getInitParameter("username");
String password = config.getInitParameter("password"); }%>

Neste exemplo, os valores de nome de usuário e senha foram fornecidos como


parâmetros de inicialização e acessados pelo objeto config. Desta forma, não foram
armazenados diretamente na página JSP, melhorando a segurança da aplicação.

44
Objetos Relacionados a Input/Output

• Objeto request: Representa a


solicitação que acionou o
processamento da página atual
fornecendo acesso a todas as
informações associadas com uma
solicitação HTTP. Os métodos se
encaixam em 4 categorias:
Desenvolvido pelo ESMS.C 40

O objeto request representa a solicitação que requisitou a página. O objeto request


implementa a interface javax.servlet.http.HttpServletRequest (subinterface de
javax.servlet.ServletRequest). É um dos mais complexos e mais utilizados na
construção de páginas JSP. Podemos dividir os métodos desse objeto em quatro
funcionalidades :

Armazenar e Recuperar valores de atributos:


Método Descrição
void setAttribute(String key, Object value) Associa um valor de atributo com um nome.
Enumeration getAttributeNames() Recupera os nomes de todos os atributos associados com o objeto.
Object getAttribute(String key) Recupera o valor de atributo associado com a chave.
void removeAttribute(String key) Remove o valor de atributo associado com a chave.

Recuperar parâmetros de solicitação e cabeçalho de HTTP:


Método Descrição
Enumeration getParameterNames() Retorna os nomes de todos os parâmetros de solicitação.
Retorna os primeiro valor (principal) de um único parâmetro de
String getParameter(String name)
solicitação.
String[] getParameterValues(String name) Recupera todos os valores para um único parâmetro de solicitação.

Recuperar cabeçalhos de solicitação e cabeçalhos de HTTP:


Método Descrição
Recupera os nomes de todos os cabeçalhos associados com a
Enumeration getHeaderNames()
solicitação.
Retorna o valor de um único cabeçalho de solicitação, como uma
String getHeader(String name)
cadeia.
Enumeration getHeaders(String name) Retorna todos os valores para um único cabeçalho de solicitação.
Retorna o valor de um único cabeçalho de solicitação, com um
int getIntHeader(String name)
número inteiro.
Retorna o valor de um único cabeçalho de solicitação, como uma
long getDateHeader(String name)
data.
Cookies[] getCookies() Recupera todos os cookies associados com a solicitação.

45
Diversos métodos da interface que javax.servlet.hhtp.HttpServletRequest:
Método Descrição
Retorna o método de HTTP (e.g, POST, GET, etc) para a
String getMethod()
solicitação.
String getRequestURI() Retorna o URL de solicitação (não inclui a cadeia de consulta).
Retorna a cadeia de consulta que segue o URL de solicitação, se
String getQueryString()
houver algum.
Recupera os dados da sessão para a solicitação (i.e, o objeto
HttpSession getSession()
implícito session).
Recupera os dados da sessão para a solicitação (i.e, o objeto
HttpSession getSession(boolean flag)
implícito session), opcionalmente criando-o se ele ainda não existir.
RequestDispatcher
Cria um dispatcher de solicitação para o URL local indicado.
getRequestDispatcher(String path)
Retorna o nome totalmente qualificado do host que enviou a
String getRemoteHost()
solicitação.
String getRemoteAddr() Retorna o endereço de rede (IP) do host que enviou a solicitação.
String getRemoteUser() Retorna o nome do usuário que enviou a solicitação, se conhecido.

Exemplo :

<html>
<body>
<h2> Alguns Métodos do Objeto Ímplicito Request </h2>
<br><b>Valor do parâmetro Nome:</b> <%= " "+request.getParameter("nome") %>
<br><b>Valor do parâmetro Idade: </b> <%= " "+request.getParameter("idade") %>
<br><b>URL:</b> <%=" "+ request.getRequestURI()%>
<br><b>Cadeia de consulta:</b> <%= " " + request.getQueryString() %>
<br><b>Cliente:</b> <%= " " + request.getRemoteHost() %>
<br><b>Host da URL:</b ><%= " "+ request.getServerName() %>
</body>
</html>

Acessando o arquivo de exemplo request.jsp da seguinte forma :

http://.../request.jsp?nome=MARIA&idade=60

Retornará a seguinte tela :

Alguns Métodos do Objeto Ímplicito Request


Valor do parâmetro Nome : MARIA
Valor do parâmetro Idade: 60
URL: /jsp_dev/sure/escritorios/request_metodos.jsp
Cadeia de consulta: nome=MARIA&idade=60
Cliente: 10.82.0.122
Host da URL: 10.82.0.220

46
O objeto response representa a resposta que será enviada de volta para o usuário como
resultado do processamento da página JSP. Este objeto implementa a interface
javax.servlet.http.HttpServletResponse que é uma subinterface de
javax.servlet.ServletResponse. Podemos dividir os métodos desse objeto em quatro
funcionalidades :

Especificar o tipo de conteúdo e codificação da resposta:


Método Descrição
Define o tipo MIME e, opcionalmente, a codificação de caracteres
void setContentType(String type)
do conteúdo da resposta.
Retorna o conjunto de estilos de codificação de caracteres para o
String getCharacterEncoding()
conteúdo da resposta.

Definir cabeçalhos da resposta:


Método Descrição
void addCookies(Cookie cookie) Adiciona o cookie especificado.
boolean containsHeader(String name) Verifica se a resposta inclui o cabeçalho.
Atribui o valor definido pela variável "value" ao cabeçalho
void setHeader(String name, String value)
especificado por "name"
Atribui o valor de número inteiro especificado por "value" ao
void setIntHeader(String name, int value)
cabeçalho especificado por "name"
Atribui o valor de data especificado por "value" ao cabeçalho
void setDateHeader(String name, long date)
especificado por "name"
Adiciona o valor definido por "value" ao cabeçalho especificado por
void addHeader(String name, String value)
"name"
Adiciona o valor de número inteiro especificado por "value" ao
void addIntHeader(String name, int value)
cabeçalho especificado por "name"
Adiciona o valor de data especificado por "value" ao cabeçalho
void addDateHeader(String name, long date)
especificado por "name"

Definir códigos de resposta:


Método Descrição
Define o código de status para a resposta (para circunstâncias sem
void setStatus(int code)
erro)
void sendError(int status, String msg) Define o código de status e mensagem de erro para a resposta.
Envia uma resposta para o navegador indicando que ele deveria
void sendRedirect(String url)
solicitar um URL alternativo (absoluto)

Reescrita da URL:
Método Descrição
Codifica um URL para uso com o método sendRedirect() para
String encodeRedirectURL(String url)
incluir informações de sessão.
Codifica um URL usado em um link para incluir informações de
String encodeURL(String url)
sessão.

Exemplo 1 :

<% response.setDateHeader("Expires",0);
response.setHeader("Pragma","no-cache");
if(request.getProtocol().equals("HTTP/1.1"))
{
response.setHeader("Cache-Control","no-cache");
}
%>

47
Este scriplet define vários cabeçalhos para evitar que a página seja armazenada em
cache por um navegador.
Primeiro é definido o cabeçalho Expires para uma data no passado. Isto indica para o
navegador que o conteúdo da página já expirou, desta forma, não sendo armazenado em
cache.
O valor no-cache para o cabeçalho Pragma é fornecido pela versão 1.0 do protocolo
HTTP para especificar que os navegadores e servidores proxy não devem armazenar em
cache uma página.. A versão 1.1 de HTTP substitui este cabeçalho por um cabeçalho
Cache-Control mais específico, mas recomenda a inclusão do cabeçalho Pragma
também, para compatibilidade retroativa. Portanto, se a solicitação indicar que o
navegar (ou o servidor proxy) aceita HTTP 1.1, ambos os cabeçalhos são enviados.

Exemplo 2 : Execute o exemplo response.jsp e analise seu código fonte :

<html>
<head>
<title>
Response
</title>
</head>
<body>
<h1>Exemplo de utilização do objeto response.</h1>

<% response.sendError(401,"Esta página não contém erro algum, mas como foi
configurado no cabeçalho um código de erro o browser interpreta como se
houvesse ! "); %>

</body>
</html>

Esta página é bastante simples e seu processamento muito provavelmente não


ocasionaria erro algum. Porém, como foi inserido um código java para setar um código
de erro para página, quando esta é carregada pelo browser este constata a existência do
erro 401 cabeçalho HTTP e imprime a mensagem associada.

48
Objetos Relacionados a
Input/Output
• Objeto out: representa o fluxo de saída para
a página, cujo conteúdo será enviado para o
navegador como o corpo de sua resposta.
• Utilizando este objeto, é possível gerar
output dentro do corpo de um scriptlet sem
ter que temporariamente fechar o scriptlet
para inserir conteúdo estático ou tags de
expressões (<%= expressão %>) JSP.
• Principais métodos : print() e println()
Desenvolvido pelo ESMS.C 50

Este objeto implícito representa o fluxo de saída para a página, cujo conteúdo será
enviado para o navegador com o corpo de sua resposta. O objeto out é uma instância da
classe javax.servlet.jsp.JspWriter. Vejamos o exemplo abaixo (arquivo out.jsp) :

Objetos Relacionados a Input/Output

Exemplo sem o uso do objeto out: Exemplo com o uso do objeto out:
<html><body>
<html><body>
<p> Asteriscos gerados fora do <p> Asteriscos gerados no scriplet:
scriplet: <%
<% int qt = 0;
int qt = 0; while (qt < 5){
while (qt < 5){ qt ++;
qt ++; %> out.print("*");
* }
<% } %> out.print(“<br> Foram gerados” +
<br> qt + “asteriscos”
<%= "Foram gerados " + qt + " %>
asteriscos.” %>
</body> </html> </body> </html>
Desenvolvido pelo ESMS.C 51

Esse objeto é muito utilizado para gerar conteúdo dentro do corpo de um scriptlet, sem
ter que fechá-lo temporariamente para inserir conteúdo de página estático ou tags de
expressão. Contudo, deve-se evitar usar os métodos print() ou println() (imprime
acrescentando um \n no final) para inserir cadeias de caracteres muito grandes. No
próximo caso, é mais aconselhável fechar o script e inserir o conteúdo estático. Veja o
exemplo abaixo:

49
Não Aconselhável: Aconselhável:
<% <%
if(i == 1){ if(i == 1) { %>

out.print("<h6>"+ <h6>
"<font face='verdana'>"+ <font face='verdana'>
"Guga viaja nesta sexta"+ Guga viaja nesta sexta
"para a Suíça para"+ para a Suíça para
"jogar"+ jogar
"</font>"+ </font>
"</h6>"); </h6>
} %> <% } %>

Alguns outros métodos do objeto out são :


Método Descrição
isAutoFlush() Retorna true se o buffer de saída for automaticamente esvaziado quando
ele ficar cheio, false se uma exceção for lançada.
getBufferSize() Retorna o tamanho do buffer de saída (em bytes).
getRemaining() Retorna o tamanho da porção não usada (em bytes) do buffer de saída.
clearBuffer() Apaga o conteúdo do buffer de saída, descartando-o.
clear() Apaga o conteúdo do buffer de saída, assinalando um erro se o buffer
tiver sido anteriormente esvaziado.
newLine() Escreve um separador de linha (específico de plataforma) para o buffer
de saída.
flush() Esvazia o buffer de saída, depois esvazia o fluxo de saída.
close() Fecha o fluxo de saída, se desfazendo de seu conteúdo.

Objetos Contextuais
• Os objetos implícitos dessa categoria
fornecem à página JSP acesso ao contexto
dentro do qual ela está respondendo. Os três
objetos implícitos contextuais são:
– session
– application
– pageContext

Desenvolvido pelo ESMS.C 51

Os objetos implícitos nesta categoria fornecem à página JSP acesso ao contexto dentro
do qual ela está sendo processada. O objeto session, fornece o contexto para a
solicitação à qual a página está respondendo. Que dados já foram associados com o
usuário individual que está solicitando a página ? O objeto application fornece o
contexto no servidor dentro do qual a página está rodando. Já o objeto page-Context se
concentra no contexto da própria página JSP, fornecendo acesso programático a todos

50
os outros objetos implícitos. A tabela a seguir traz os métodos comuns aos quatro
objetos e que são usados para armazenar e recuperar valores de atributos :

Os métodos comuns a esses três objetos, bem como ao objeto request, e que são usados
para armazenar e recuperar valores de atributos, estão resumidos na tabela 1:

Tabela 1
Método Descrição
void setAttribute(String key, Object value) Associa um valor de atributo com um nome.
Enumeration getAttributeNames() Recupera os nomes de todos os atributos associados com o objeto.
Object getAttribute(String key) Recupera o valor de atributo associado com a chave.
void removeAttribute(String key) Remove o valor de atributo associado com a chave.

Objetos Contextuais
• Objeto session : Representa a sessão atual
de um usuário individual.
• Persiste enquanto o usuário estiver intera-
gindo com a página
• Depois de um certo período de inatividade a
sessão expira
• Principais métodos :
– setAttribute (nome, objeto)
– getAttribute (nome)
Desenvolvido pelo ESMS.C 52

O objeto session armazena informações a respeito da sessão. Um dos principais usos


para o objeto session é armazenar e recuperar valores de atributos, a fim de transmitir as
informações específicas de usuários entre as páginas. Abaixo segue um exemplo que
armazena dados na sessão :

<%
session.setAttribute("nome", request.getParameter(“nome”));
session.setAttribute(“senha”, request.getParameter(“senha”))
%>

Uma vez que um objeto tenha sido armazenado através do método setAttibute(), ele
pode ser recuperado - na mesma página ou em outra acessada pelo usuário. O código
abaixo ilustra a recuperação do objeto armazenado no código anterior:

<%
String nome = (String) session.getAttribute("nome");
String senha = (String) session.getAttribute("senha");
.....
%>

51
Perceba que o método getAttribute() retorna um objeto da classe Object, portanto, é
necessário fazermos um cast para converter o objeto retornado em uma instância da
classe desejada.
O objeto session implementa a interface javax.servlet.http.HttpSession. A tabela
abaixo traz os principais métodos utilizados por esse objeto, além daqueles descritos
anteriormente:

Método Descrição
Object getAttibute(String nome) Recupera o objeto identificado por "nome".
String getId() Retorna o Id da sessão.
long getCreationTime() Retorna a hora na qual a sessão foi criada.
long getLastAccessedTime() Retorna a última vez que uma solicitação associada com a sessão foi recebida.
Retorna o tempo máximo (em segundos) entre solicitações pelo qual a sessão
int getMaxInactiveInterval()
será mantida.
void setMaxInactiveInterval(int Define o tempo máximo (em segundos) entre solicitações pelo qual a sessão
time) será mantida.
boolean isNew() Retorna se o navegador do usuário ainda não tiver confirmado o ID de sessão.
boolean invalidate() Descarta a sessão, liberando quaisquer objetos armazenados como atributos.

Objetos Contextuais
• Objeto application : Representa a aplicação
à qual a página JSP pertence. Ex:
• http:\\server\jsp_dev\index.jsp
• http:\\server\jsp_dev\principal.jsp
• http:\\server\jsp_dev\tutorial\tutorial.jsp
• Seus métodos retornam informações sobre o
container, acessam recursos no servidor,
fornecem suporte a log e, principalmente ,
fornecem acesso a parâmetros de inicia-
lização da aplicação como um todo.
Desenvolvido pelo ESMS.C 54

Este objeto representa a aplicação à qual a página JSP pertence. Ele é uma instância da
interface javax.servlet.ServletContext. Os containers JSP tipicamente tratam do
primeiro nome de diretório em um URL como uma aplicação. Exemplo:

• http://server/jsp_dev/index.jsp
• http://server/jsp_dev/principal.jsp
• http://server/jsp_dev/forum/forum.jsp
• http://server/jsp_dev/tutorial/tutorial.jsp

São todos considerados parte da mesma aplicação jsp_dev. Além dos métodos descritos
na tabela 1, os métodos do objeto application podem ser divididos em quatro
funcionalidades :

52
Recuperar informações de versão do container servlet:
Método Descrição
String getServerInfo() Retorna o nome e versão do container servlet.
int getMajorVersion() Retorna a versão principal da API do servlet para o container servlet.
int getMinorVersion() Retorna a versão secundária da API do servlet para o container servlet.

Interagir com arquivos e caminhos no servidor:


Método Descrição
String getMimeType(String
Retorna o tipo MIME para o arquivo indicado, se conhecido pelo servidor.
filename)
Traduz uma cadeia especificando um URL em um objeto que acessa os
URL getResource(String path)
conteúdos dos URLs, localmente ou na rede.
InputStream Traduz uma cadeia especificando um URL em um fluxo de entrada para ler
getResourceAsStream(String path) seu conteúdo.
String getRealPath(String path) Traduz um URL local em um nome de caminho no sistema de arquivo local.
ServletContext getContext(String
Retorna o contexto de aplicação para o URL local especificado.
path)
RequestDispatcher
Cria um dispacher de solicitação para o URL local indicado.
getRequestDispatcher(String path)

Suporte para log de mensagens:


Método Descrição
void log(String message) Grava a mensagem o arquivo de log.
void log(String message, Grava a mensagem no arquivo de log, junto com a trilha de pilha para a exceção
Exception e) especificada.

Acessar parâmetros de inicialização:


Método Descrição
Enumerations getInitParameterNames() Recupera os nomes de todos os parâmetros de inicialização.
String getInitParameter(String name) Recupera o valor do parâmetro de inicilização com o nome dado.

Exemplo :

Um grupo de páginas JSP que residem na mesma aplicação podem fazer uso de
atributos do objeto application para disponibilizar recursos que devem estar disponíveis
para todas as páginas da aplicação. Outra utilização muito frequente para o objeto
application é a utilização de parâmetros de inicialização para a aplicação como um todo.
Estas e outras funcionalidades estão ilustradas no código abaixo (arquivo
application.jsp) :

<html>
<body>
<%
//Este trecho de código grava um objeto do tipo String no contexto da aplicação a qual a
//página pertence
String aux = "aux e um objeto armazenado no contexto desta aplicacao e pode ser
recuperado por qualquer pagina que pertença a ela ";
application.setAttribute("aux",aux);
%>

<b>Recuperando objetos armazenados no contexto da aplicação (objeto


application) : </b><br>
<%= application.getAttribute("aux") %>

53
<br><br>
<b>Informaçoes sobre o container : </b><br>
<%= application.getServerInfo() %>
<br><br>
<b>Caminho no servidor onde está armazenada esta página : </b><br>
<%= application.getRealPath("application.jsp") %>
<br><br>
<b>Recuperando parâmetros de inicialização : </b><br>
<%= "Usuário : " + application.getInitParameter("username") %><br>
<%= "Senha : " + application.getInitParameter("password") %>
</body>
</html>

Os valores para os parâmetros de inicialização, como no objeto Config, são


especificados através do arquivo descritor de acionamento de uma aplicação da web, o
Web.xml. Abaixo segue um exemplo de como configurar o arquivo com os parâmetros
acima:

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

<context-param>
<param-name>username</param-name>
<param-value>admin</param-value>

</context-param>

<context-param>
<param-name>password</param-name>
<param-value>teste</param-value>
</context-param>

</web-app>

Neste exemplo, como no exemplo de utilização do objeto Config, os valores de nome de


usuário e senha foram fornecidos como parâmetros de inicialização e são acessados pelo
objeto application. A diferença aqui, é que estes parâmetros estão disponíveis para
qualquer página que pertença a uma mesma aplicação. Já no caso do objeto Config,
estes parâmetros só podem ser acessados pela página para qual eles foram criados.

54
Objetos Contextuais
• Objeto pageContext :
– fornece acesso programático a todos os outros
objetos implícitos.
– este acesso é especialmente útil na perspectiva
de criação de tags personalizadas.
– alguns métodos para recuperar objetos
implícitos são : getPage - retorna o objeto page,
getRequest - retorna o objeto request, getOut -
retorna o objeto out, getSession - retorna o
objeto session e assim para cada um deles.
Desenvolvido pelo ESMS.C 63

Objetos Contextuais
• Objeto pageContext (continuação):
– acesso aos atributos dos objetos que lidam com
atributos, isto é, aqueles que implementam os
métodos : setAttribute, getAttributeNames,
getAttibute (key) e removeAttibute (key)
– estes objetos e seus respectivos escopos são :
• request - REQUEST_SCOPE
• session - SESSION_SCOPE
• application - APPLICATION_SCOPE
• pageContext - PAGE_SCOPE
Desenvolvido pelo ESMS.C 64

Objetos Contextuais
• O bjeto pageContext (continuação):
– alguns m étodos para tratar de atributos são :
• setAttribute (key, value, scope)
• getA ttribute (key, scope)
• removeAttribute (key, scope)
• findAttribute (nam e)
• O objeto pageContext também im plem enta
m étodos que possibilitam transferir o
controle da página atual para outra e serão
vistos com mais detalhes no tópico Ações.
Desenvolvido pelo ESM S.C 65

55
O objeto pageContext fornece várias facilidades como gerenciamento de sessões,
atributos, inclusões e encaminhamento de requisições de fluxo de resposta. O objeto
pageContext é uma instância da classe javax.servlet.jsp.PageContext. Além dos
métodos para lidar com atributos descritos na tabela 1, os principais métodos desse
objeto podem ser divididos em três categorias :

Acessar outros objetos implícitos de JSP:


Método Descrição
Object getPage() Retorna a instância de servlet para a página atual (objeto implícito page).
ServletRequest Retorna a solicitação que iniciou o processamento da página (objeto implícito
getRequest() request).
ServletResponse Retorna a respota para a página (objeto implícito response).
JspWriter getOut Retorna o fluxo de saída atual para a página (objeto implícito out).
Retorna a sessão associada com a solicitação da página atual, se houver alguma
HttpSession getSession()
(objeto implícito session).
ServletConfig
Retorna o objeto de configuração de servlet (objeto implícito config).
getServletConfig()
ServletContext
Retorna o contexto no qual o servlet da página roda (objeto implícito application).
getServletContext()
Para páginas de erro, retorna a exceção passada para a página (objeto implícito
Exception getException()
exception).

Envio de solicitações de uma página JSP para outra:


Método Descrição
void forward(String path) Encaminha o processamento para um outro URL local dado pela String path.
void include(String path) Inclui o output do processamento de um outro URL local.

Acessar atributos através de múltiplos escopos:


Método Descrição
void setAttribute(String key, Object obj, int Associa o valor do atributo "obj" com a chave "key" no escopo
scope) "scope".
Enumeration getAttributeNamesInScope(int Recupera os nomes de todos os atributos associado com "key" no
scope) escopo "scope".
Recupera o valor de tributo associado com "name" no escopo
Object getAttribute(String name, int scope)
"scope"
Remove o valor de atributo associado com "name" no escope
removeAttribute(String name, int scope)
"scope"
Object findAttribute(String name) Procura em todos os escopos pelo atributo associado com "name".
Retorna o escopo no qual o atributo associado com "name" está
int getAttributesScope(String name)
armazenado.

Os últimos dois métodos listados na tabela anterior permitem a procura, através de todos
os escopos definidos, por um atributo associado com uma String passada como
parâmetro. Nos dois casos, o objeto pageContext irá realizar uma busca através dos
escopos na seguinte ordem: pageContext, request, session e application..
A tabela anterior traz métodos que recebe parâmetros para especificar o escopo. A
classe javax.servlet.jsp.PageContext fornece variáveis estáticas para representar estes
quatro escopos diferentes. A tabela a seguir resume estas variáveis:

Variável Descrição
PAGE_SCOPE Escopo para atributos armazenados no objeto pageContext.
REQUEST_SCOPE Escopo para atributos armazenados no objeto request.
SESSION_SCOPE Escopo para atributos armazenados no objeto session.
APPLICATION_SCOPE Escopo para atributos armazenados no objeto application.

56
O exemplo abaixo ilustra o uso do método "getAttribute" e das variáveis estáticas
descritas na tabela anterior :
<%
User uPag=(User)pageContext.getAttibute("user",pageContext.PAGE_SCOPE)
//Recupera o object "usuario" do escopo pageContext

User uReq=(User)pageContext.getAttibute("user",pageContext.REQUEST_SCOPE)
//Recupera o object "usuario" do escopo request

User uSes=(User)pageContext.getAttibute("user",pageContext.SESSION_SCOPE)
//Recupera o object "usuario" do escopo session

User uApp=(User)pageContext.getAttibute("user",pageContext.APPLICATION_SCOPE)
//Recupera o object "usuario" do escopo application
%>

Tratamento de Erros
• Objeto Exception : tem o propósito de
possibilitar o tratamento de erros em
páginas cujo atributo isErrorPage = “true”
• Principais métodos são :
– getMessage : msg de erro descritiva
– printStackTrace(out) : imprime a pilha de
execução para o fluxo de saída designado
– toString() : retorna uma cadeia combinando o
nome da classe da exceção com sua msg de erro
Desenvolvido pelo ESMS.C 61

O objeto exception não está automaticamente disponível em todas as páginas JSP. Este
objeto está disponível apenas nas páginas que tenham sido designadas como páginas de
erro, usando o atributo isErrorPage configurado com true na diretiva page. O objeto
exception é uma instância da classe java.lang.Throwable correspondente ao erro não
capturado que fez com que o controle fosse transferido para a página de erro. Os
principais métodos da classe java.lang.Throwable que são utilizados dentro das páginas
JSP são listados na tabela abaixo:

Método Descrição
String getMessage() Retorna a mensagem de erro descritiva associada com a exceção quando ela foi lançada.
void
Imprime a pilha de execução em funcionamento quando a exceção foi lançada para o
printStackTrace(PrintWri
fluxo de saída especificado pelo parâmetro out.
ter out)
Retorna uma cadeia combinando o nome da classe da exceção com sua mensagem de
String toString()
erro, se houver alguma.

O trecho abaixo ilustra o uso do objeto exception em uma página de erro JSP:

57
<@ page isErrorPage=true %>
<h1>Erro Encontrado</h1>
O seguinte erro foi encontrado:<br>
<b><%= exception %></b><br>
<% exception.printStackTrace(out); %>

Ações
• Forward : A ação <jsp:forward> transfere
permanentemente o controle de uma página
JSP para um outro local no servidor.
• O conteúdo gerado antes é descartado.
• Os objetos request e session serão os
mesmos tanto para a página original quanto
para a página encaminhada.
• Considerações quanto bufferização
• Sintaxe : <jsp:forward page=“localHRL” />
Desenvolvido pelo ESMS.C 67

Ações
fatoração.jsp

<% x = recebe_fatoracao.jsp
request.getParameter(“x”);
<% y =
y = Fatora (x); request.getAttribute(“y”);
if (y != null) { %>

request.setAttribute (“y”,y); Este é o conteúdo de y


passsado na solici- tação pela
%> página fatoração.jsp :

<jsp:forward <%= y %>


page=“recebe_fatoracao.jsp” />
<% } %> resposta

Desenvolvido pelo ESMS.C 68

A ação <jsp:forward page=”localURL” /> é usada para transferir permanentemente o


controle de uma página JSP para um outro local no servidor, que pode ser um
documento estático, um CGI, um servlet ou outra página JSP. Qualquer conteúdo
gerado pela página atual é descartado e o processamento da solicitação começa
novamente no local alternativo.

Quando o controle é transferido para uma outra página JSP, o container irá
automaticamente atribuir um novo objeto pageContext à página encaminhada. O objeto

58
request e session, no entanto, serão os mesmos tanto para página original quanto para a
página encaminhada.

Se é necessário transferir dados de uma página para outra, a abordagem típica é


armazenar estes dados na solicitação (como no exemplo do slide) ou na sessão,
dependendo de por quanto tempo a mais os dados serão necessários. No exemplo acima,
o objeto request foi utilizado para especificar um atributo a mais (y) junto aos
parâmetros de solicitação, para transmitir informação adicional de uma página para
outra. Não há limite para o número de parâmetros de solicitação que podem ser
especificados desta maneira e nem ao tipo dos mesmos.

Um ponto importante quando da utilização desta tag, é sua interação com a


bufferização. Quando o processamento de uma solicitação de página encontra a tag
<jsp:forward>, todo output gerado até então deve ser descartado através do
esvaziamento do buffer de saída. Se no entanto, o buffer de saída associado com a
solicitação da página atual tiver sido esvaziado antes da ação <jsp:forward> ser
executada, a ação irá falhar e uma exceção IllegalStateException será lançada. Sendo
assim, qualquer página que empregue esta tag, deve ser verificada para se certificar que
seu buffer de saída seja grande o suficiente para assegurar que ele não será esvaziado
antes de qualquer chamada para esta ação. Alternativamente, se a bufferização de saída
for desabilitada para a página , então qualquer código que possa chamar a ação
<jsp:forward> deve aparecer na página antes de qualquer elemento estático ou dinâmico
que gere output.

Ações
• Include : A ação <jsp:include> transfere
temporariamente o controle de uma página
JSP para um outro local no servidor.
• O output da página incluída é colocado no
output da página atual que continua seu
processamento.
• Sintaxe :
<jsp:include page=“localHRL” flush=“true” />
• Diretiva include x Ação include
Desenvolvido pelo ESMS.C 69

A ação <jsp:include> permite a incorporação do conteúdo gerado por outro documento


local no output da página atual. Quando uma tag <jsp:include> é encontrada, a
solicitação é redirecionada do arquivo original para a página incluída, o container
realiza as tarefas comuns de execução de uma página (carrega o servlet caso necessário,
recompila caso tenha havido alguma alteração, etc), o output gerado é inserido no
output da página original e depois o processamento da página original continua
normalmente. Sua sintaxe é :

<jsp:include page=”localURL” flush=”true” />

59
A página incluída pode ser um documento estático, um CGI, um servlet ou outra página
JSP. Assim como acontece com a ação <jsp:forward>, o atributo page da ação
<jsp:include> suporta valores obtidos em tempo de execução. O atributo flush controla
se o buffer de saída da página original deve ou não ser esvaziado antes que o novo
output comece a ser incluído. Geralmente é definido como “true”.

Assim como acontece com páginas acessadas através da ação <jsp:forward>, será
atribuído às páginas incluídas um novo objeto pageContext e compartilhado os objetos
session e request. Sendo assim, caso seja necessário passar valores da página original
para a incluída, deve-se usar um destes objetos.

Diretiva Include x Ação Include

Diretiva Include :

• Todas as páginas incluídas são compiladas juntas criando um único servlet.


• Compartilhamento de variáveis entre as páginas (já que na verdade geram um único
servlet).
• Melhor performance tendo em vista que não requer o overhead de despachar a
solicitação para a página incluída e depois incorporar a resposta no output da página
original.
• Quando uma página incluída é alterada, para ter efeito a alteração é necessário
realizar forçosamente uma alteração na página principal, para assim o servlet ser
recompilado.
• A página a ser incluída não pode ser especificada dinamicamente.
• Pode incluir apenas páginas estáticas ou outra página JSP.

Ação Include :

• Cada página incluída é um servlet separado, que deve ser carregado e executado
pelo container.
• Troca de informações entre as páginas através do objeto session ou request.
• Como cada página incluída é um servlet separado, uma alteração em alguma delas
não requer uma alteração forçada na página principal para a alteração ter efeito
(recompilação automática).
• Menores tamanhos de classe, já que o código correspondente ao arquivo incluído
não é repetido nos servlets para todas as páginas JSP que fazem a inclusão.
• Possibilidade de especificar em tempo de execução a página a ser incluída.
• Pode incluir páginas estáticas, CGI’s, servlets ou outra página JSP.

60
Exercícios :

Objetos request e response

1 – Quais os objetos que possibilitam manipular os cabeçalhos HTTP?

2 – Execute o código abaixo e explique o que ele faz.

java.util.Enumeration parameter_names = request.getHeaderNames();


String nome;
while(parameter_names.hasMoreElements())
{
nome = (String) parameter_names.nextElement();
out.println("Parametro " + nome + " = ");
out.println(request.getHeader(nome) + "<br><br>");
}

3 – Crie uma página chamada origem.jsp que recebe um número inteiro como
parâmetro, calcula seu fatorial e acrescenta o resultado como atributo da solicitação.
Depois, crie um objeto do tipo javax.servlet.RequestDispatcher. Para isso utilize o
método getRequestDispatcher(“<pagina destino>”) do objeto request:

javax.servlet.RequestDispatcher dispatcher = request.getRequestDispatcher(“XXX”);

Para comandar o direcionamento para outra página, utilize o método


forward(request,response) do objeto dispatcher. Você deve redirecionar para uma
página local chamada “destino.jsp”, a qual deve imprimir o resultado do fatoramento.
Perceba como é útil poder acrescentar atributos na solicitação para trocar informações
entre páginas.

4 – Refaça o exercício anterior fazendo o redirecionamento utizando o método


sendRedirect(URL) do objeto response ao invés do forward. Veja junto ao instrutor
porque desta forma não funciona e qual a diferença das duas abordagens.

Objeto application

5 – Refaça o exercício 4 porém, ao invés de gravar o resultado do fatorial no objeto


request, grave-o no contexto da aplicação. Modifique a página destino.jsp para pegar o
atributo do lugar apropriado. Explique porque desta forma, mesmo fazendo o
redirecionamento através do sendRedirect(URL), o valor está acessível na página de
destino.

Objeto out

6 - Faça uma página que exiba o status da bufferização, apresentando qual o tamanho
total do buffer, quantos bytes já foram utilizados e qual a porcentagem livre do mesmo.

7 - O método abaixo simula o jogo do lançamento de uma moeda para depois verificar
se ela caiu no lado da cara ou da coroa. O método retorna uma String com o resultado, e
um exemplo da forma como pode ser utilizado a partir de uma página está no quadro
abaixo.

61
<%!
String jogueMoeda(){
String retorno = "";
int i = (int)(Math.random()*10); //um número entre 0 e 10
i = i%2; //resto da divisao de i por 2
if(i==0){ Exemplo de utilização :
retorno = "cara"; <html>
} else { <body>
retorno = "coroa";
} <h1>Deu <%= jogueMoeda() %>!</h1>
return retorno;
} </body>
%> </html>
Modifique o código de forma que o método receba como parâmetro o número de vezes
que irá lançar a moeda. Além disso, utilize o objeto out para imprimir, a partir do
próprio método, os resultados. A inserção deste objeto no método irá causar dois erros
que devem ser tratadados. Algumas dicas para tentar resolvê-los são : lembre-se que o
java exige o tratamento de exceções em determinadas situações, os objetos implícitos
não são visíveis dentro dos métodos criados numa página JSP e o objeto out é da classe
javax.servlet.jsp.JspWriter.

Objeto session

8- Crie uma página chamada testanto_sessao.jsp que lê o atributo “valor” da sessão e


imprime seu conteúdo na tela. Caso este atributo ainda não exista na sessão, deve-se
apresentar uma tela para que seu valor seja informado, com um botão para fazer um
submit para a própria página. O código do formulário HTML pode ser como o abaixo:

<html>
<body>

<form action=”testando_sessao.jsp” method=”post”>


Entre com o valor a ser armazenado na sessão:
<input type=”text” name=”valor” size=”10”> <br>
<input type=”submit” value=”Enviar”>

</body>
</html>

Ação Forward e Include

9 - Crie uma página que leia um valor numérico passado pelo usuário, multiplique seu
valor por 10, e então encaminha o processamento utilizando a ação <jsp:forward> para
outra página que irá imprimir o resultado.

10 - Numa situação em que queremos utilizar uma página que cria inúmeros objetos que
serão compartilhados por outras, qual melhor opção, utilizar a diretiva include ou a ação
include ?

62
V - Cookies

IV - Cookies

• Mecanismo padrão fornecido pelo protocolo


HTTP que permite gravar pequenas
quantidades de dados no lado do usuário
• Por razões de segurança, um cookie só pode
ser recuperado pelo servidor que o forneceu
• Opcionalmente pode ser tornado acessível
para outros servidores que compartilham o
mesmo domínio do servidor original
• São definidos em cabeçalhos de resposta e
recuperados em cabeçalhos de solicitação
Desenvolvido pelo ESMS.C 70

Cookie é um mecanismo padrão fornecido pelo protocolo HTTP e que permite


gravarmos pequenas quantidades de dados persistentes no navegador de um usuário.
Tais dados podem ser recuperados posteriormente pelo navegador. Esse mecanismo é
geralmente usado quando queremos armazenar/recuperar informações de algum usuário.
Com os cookies, pode-se reconhecer quem entra num site, de onde vem, com que
periodicidade costuma voltar, dentre inúmeras outras utilizações. No Internet Explore
5.1, os cookies ficam armazenados em c:\windows\cookies e no Communicator 4.7,
ficam em c:\arquivos de programas\netscape\users.

Como padrão, os cookies expiram tão logo o usuário encerra a navegação naquele site,
porém, podemos configurá-los para persistirem por vários dias, até uma data de
expiração especificada. Por razões de segurança, um cookie só pode ser recuperado pelo
servidor que o forneceu. Opcionalmente, um cookie pode ser tornado acessível para
outros servidores que compartilham o mesmo domínio do servidor original que o gravou
. Eles ainda podem ser restritos a uma hierarquia de diretórios de URL específico no
servidor, ou servidores, do qual ele é acessível. Cada cookie recebe um nome, e um
servidor pode então definir múltiplos cookies e fazer a identificação entre eles através
dos seus nomes.

Gerenciando Cookies

Como vimos, os cookies estão relacionados a um servidor da web. Quando um usuário


solicita um URL cujo servidor e diretório correspondam àqueles de um ou mais de seus
cookies armazenados, o próprio browser se encarrega de enviar os cookies
correspondentes de volta para o servidor na forma de cabeçalhos de solicitação. Os
cookies são definidos através de cabeçalhos de resposta HTTP.

As páginas JSP acessam os seus cookies associados através do método getCookies() do


objeto implícito request. De forma similar, as páginas JSP podem criar ou alterar
cookies através do método addCookie() do objeto implícito response. Esses métodos são
resumidos na tabela abaixo :
63
Objeto Implícito Método Descrição
request getCookies() retorna uma matriz de cookies acessíveis da página
response addCookie(cookie) envia um cookie para o navegador para armazenagem/modificação

Para ambos os métodos os cookies são representados como instâncias da classe


javax.servlet.http.Cookie. O método getCookies () retorna um array de instâncias da
classe Cookie, enquanto o método addCookie() recebe uma instância dessa classe como
seu argumento.

Como Funcionam os Cookies


grava_cookie.jsp
Para gravar um cookie no lado cliente,
.... usamos recursos de JSP que o definem no
addCookie(x) cabeçalho de resposta. Quando o browser
recebe uma página, ele lê este cabeçalho,
...
identifica os cookies existentes e os grava.

le_cookie.jsp
Toda vez que uma página é submetida
.... para o servidor web, o browser antes
getCookies() verifica se há algum cookie referente àquele
servidor (ou domínio) e os envia no cabeçalho
...
de solicitação. Quando a página chega no
servidor, é possível ler este cabeçalho e
recuperar os cookies enviados.

Desenvolvido pelo ESMS.C 71

A classe Cookie

Manipulando Cookies
• Manipulamos um cookie através de
instâncias da classe Cookie
• Construtor :
Cookie cookie = new Cookie("nome" , “valor");
• Principais Métodos :
– getValue() - setValue()
– getDomain() - setDomain()
– getMaxAge() - setMaxAge(int i)
– getName()

Desenvolvido pelo ESMS.C 72

64
Manipulamos um cookie através de instâncias da classe javax.servlet.http.Cookie, que é
automaticamente inserida no servlet associado que é gerado na compilação da página
JSP. Essa classe fornece apenas um tipo de construtor que recebe duas variáveis do tipo
String, que representam o nome e o valor do cookie :

Cookie cookie = new Cookie("nome" , “valor");

Abaixo apresentamos os métodos fornecidos pela classe Cookie:

Método Descrição
getName() retorna o nome do cookie
getValue() retorna o valor armazenado no cookie
getDomain() retorna o servidor ou domínio do qual o cookie pode ser acessado
getPath() retorna o caminho deURL do qual o cookie pode ser acessado
getSecure() indica se o cookie acompanha solicitações HTTP ou HTTPS.
setValue() atribui um novo valor para o cookie
setDomain() define o servidor ou domínio do qual o cookie pode ser acessado
setPath(nome do path) define o caminho de URL do qual o cookie pode ser acessado
setMaxAge(inteiro) define o tempo restante (em segundos) antes que o cookie expire
retorna o valor de um único cabeçalho de solicitação como um
setSecure(nome)
número inteiro

Depois de construir uma nova instância, ou modificar uma instância recuperada através
do método getCookies(), é importante ter em mente a necessidade de usar o método
addCookie( ) para atualizar no navegador do usuário as alterações feitas no cookie. Para
apagar um cookie utilizamos a seguinte técnica : chamamos o método "setMaxAge(0)"
com valor zero e depois mandamos gravar chamando o método "addCookie( )". Isso faz
com que o cookie seja gravado, substituindo o de mesmo nome, e imediatamente (após
zero segundos) expira.

Os dados do cookie são comunicados através do servidor para o navegador através de


cabeçalhos de resposta. Lembre-se que todos os cabeçalhos devem ser definidos antes
que qualquer conteúdo de corpo seja enviado para o navegador. Assim, a fim de que o
método addCookie tenha sucesso em uma página JSP, ele deve ser chamado antes que o
buffer de saída da página seja esvaziado. Isto pode ocorrer quando o buffer fica cheio ou
quando é executada uma ação <jsp:include>. O status da bufferização de saída é
portanto, uma consideração importante ao construir páginas JSP que definem cookies.

Definindo um cookie

O primeiro passo ao usar um cookie dentro de uma página é defini-lo. Isto é feito
criando uma instância da classe Cookie e chamando os métodos "sets" para definir os
valores de seus atributos.

Vamos ver o seguinte exemplo da página addcookie.jsp :

<%
String email = request.getParameter("email");
String cookieName = "cookieJSP";
Cookie cookieJSP = new Cookie(cookieName, email);
cookieJSP.setMaxAge(7 * 24 * 60 * 60); //define o tempo de vida como 7 dias (604800
//segundos)
cookieJSP.setVersion(0); //versão 0 da especificação de cookie
65
cookieJSP.setSecure(false); //indica que o cookie deve ser transferido pelo protocolo
//HTTP padrão
cookieJSP.setComment("Email do visitante"); //insere um comentário para o cookie
response.addCookie(cookieJSP); //grava o cookie na máquina do usuário
%>
<html> <head>
<title>Grava Cookie</title>
</head>
<body>
<h1>Grava Cookie</h1>
Esta página grava um cookie na sua máquina.<br>
<a href='readcookie.jsp'>Lê conteúdo do cookie</a>
</body> </html>

A página que irá fornecer um email que será gravado pela página "addcookie.jsp" pode
ser da seguinte forma :

<html> <body>
<form action="addcookie.jsp">
<input type="text" name="email">
<input type="submit" value="ok">
</body> </html>

No exemplo acima o cookie é identificado pelo nome cookieJSP e recebe o valor


passado pelo usuário através de um formulário.

Recuperando um Cookie

A página jsp vista anteriormente tem a finalidade de receber um valor (email) passado
através de um formulário de uma página html. Este valor é armazenado de forma
persistente em um cookie e poderá ser acessado pelas outras páginas JSP que
compartilham o domínio e o caminho originalmente atribuídos ao cookie. Os cookies
são recuperados através do método getCookies() do objeto implícito request. A página
abaixo (readcookie.jsp) mostra um exemplo de recuperação do valor de um cookie.

<%
String cookieName = "cookieJSP";
Cookie listaPossiveisCookies[] = request.getCookies();
Cookie cookieJSP = null;
if (listaPossiveisCookies != null) {
//quando não existe cookies associados, o método getCookies() retorna um valor null
int numCookies = listaPossiveisCookies.length;
for (int i = 0 ; i < numCookies ; ++i) {
if (listaPossiveisCookies[i].getName().equals(cookieName)) { //procura pelo cookie
cookieJSP = listaPossiveisCookies[i];
break;
}
}
} %>

<html> <body>
<h1>Lê Cookie</h1>

66
<% if (cookieJSP != null) { %>
A pagina "addcookie" gravou o seguinte email: <%= cookieJSP.getValue() %>
<% }
else { %>
O cookie não gravou ou o prazo do cookie expirou.
<% } %>
</body> </html>

O primeiro scriptlet nesta página recupera os cookies associados àquela página e depois
tenta encontrar um cookie identificado pelo nome "cookieJSP".

Considerações finais sobre cookies

Restrições Quanto a Utilização

• Restrições quanto a utilização :


– o tamanho dos dados armazenados (nome e
valor) não devem ultrapassar 4K
– um navegador armazena até 20 cookies por
configuração de domínio e também 300 cookies
em geral
– o domínio atribuído a um cookie deve ter pelo
menos dois pontos, por exemplo :
www.exemplo.com ou .exemplo.com (se
nenhum é especificado, somente o host original
poderá lê-lo)
Desenvolvido pelo ESMS.C 75

Apesar da praticidade de se utilizar os cookies oferecidos pelo protocolo HTTP,


devemos fazer algumas considerações quanto a sua utilização :

• o tamanho dos dados armazenados (nome e valor) não devem ultrapassar 4K.
• o navegador pode armazenar múltiplos cookies, contanto obedece um certo limite.
Um navegador armazena até 20 cookies por configuração de domínio. O navegador
armazena também 300 cookies em geral. Se qualquer um destes dois limites forem
alcançados, espera-se que o navegador exclua cookies menos utilizados.
• o domínio atribuído a um cookie deve ter pelo menos dois pontos, por exemplo :
www.exemplo.com ou .exemplo.com. Esta regra existe para evitar a especificação
de cookies que podem ser lidos através de um domínio inteiro de alto nível (.com,
.org, .net, etc). Quando nenhum domínio é especificado na criação de um cookie
através do método setDomain(nome do domínio), então ele poderá ser lido apenas
pelo host que originalmente o definiu.

67
Exercícios :

1 – Explique com suas palavras como os cookies são armazenados no browser do


usuário e como são enviados para o servidor web.

2 – Crie uma página JSP que grava um cookie chamado datecookie com o valor da data
atual do sistema e expira num prazo de dois dias. Ela deve conter um link para uma
outra página que deverá apresentar o conteúdo do cookie ou apresentar uma mensagem
que o cookie não pode ser encontrado ou já expirou. Para obter a data do sistema fazer

java.util.Date data = new Date();

e, para criar um link em HTML :

<a href = “pagina.jsp”> texto_do_link </a>

68
VI - Enviando Email com JSP
O envio de email nos dias de hoje, para quem utiliza a internet, é algo comum e
corriqueiro. É bastante comum encontrarmos sites a partir da qual podemos enviar um
email ou enviar aquela página html para um amigo. Vale citar o fato que o envio de
email via páginas html/jsp pode ser uma excelente ferramenta para webmasters que
precisam enviar periodicamente mensagem padrão para grupos de usuários.

O envio do(s) email(s) é efetuado através da API JavaMail, que pode ser obtida em :
http://www.javasoft.com/products/javamail/index.html. Neste link, encontram-se todas
as informações necessárias para a confecção de aplicações que lidam com emails.
Utilizando esta API você poderá fazer seu próprio WebMail, personalizando-o da forma
como desejar.

Vamos analisar o exemplo abaixo. Neste exemplo construiremos três arquivos:

1. uma página html simples (preencheremail.html);


2. uma página JSP (enviaremail.jsp);

O primeiro destes, a página html, terá um formulário com três objetos do tipo "TEXT",
um do tipo "TEXTAREA" e um botão do tipo "SUBMIT" para enviar o formulário com
os dados do email.Os dados que forem preenchidos neste formulário serão tratados pela
página JSP enviaremail.jsp que foi definida como o action do formulário. Abaixo segue
o código da página “preencheremail.html” :

<html>
<body>

<form action="enviaremail.jsp" method"post">


<table border="0" align="center" bgcolor="tan">
<tr>
<td><b>Para..:</b></td>
<td><input type="Text" name="para"></td>
</tr>
<tr>
<td><b>De..:</b></td>
<td><input type="Text" name="de"
value=”fale_conosco@ms.previdenciasocial.gov.br”></td>
</tr>
<tr>
<td><b>Assunto..:</b></td>
<td><input type="Text" name="assunto"</td>
</tr>
<tr>
<td colspan="2">
<textarea name="mensagem" rows=10 cols=45></textarea>
</td>
</tr>
</table>
<center> <input type="Submit" value="Enviar Email"></center>
</form> </body> </html>

69
Abaixo segue o código da página JSP enviaremail.jsp com a lógica de programação
responsável por criar e enviar o "email" :

<%@page import="javax.mail.*" %>


<%@page import="javax.mail.internet.*" %>
<%@page import="java.util.Date" %>
<%@page import="java.util.Properties" %>

<html>
<body>
<%
try {
//definição do mailserver
Properties props = System.getProperties();
props.put("10.0.134.8", "10.0.134.8");

//obtendo uma sessão de mail


Session mailSession = Session.getDefaultInstance(props, null);

//As duas linhas seguintes de código, colocam no formato de endereços,


//supostamente válidos, de email os dados passados pelos parâmetros to e from.

InternetAddress destinatario = new InternetAddress (request.getParameter("para"));


InternetAddress remetente = new InternetAddress (request.getParameter("de"));

//As linhas de código a seguir, são responsáveis por setar os atributos e


//propriedades necessárias do objeto message para que o email seja enviado.

//Inicialização do objeto Message


Message message = new MimeMessage (mailSession);

//Definição de quem está enviando o email


message.setFrom(remetente);

//define o(s) destinatário(s) e qual o tipo do destinatário.


//os possíveis tipos de destinatário: TO, CC, BCC
message.setRecipient( Message.RecipientType.TO, destinatario );

//definição do assunto do email


message.setSubject (request.getParameter("assunto"));

//definição do conteúdo da mesnagem e do tipo da mensagem


message.setContent (request.getParameter("mensagem"), "text/plain");

//Data de envio
message.setSentDate(new Date());

//a linha de código seguinte é a responsável pelo envio do email


Transport.send (message);

out.println("<p> Email enviado com sucesso ! </p>");

70
}
catch (AddressException e) {
out.println("<p>Endereço de Email inválido</p>");
}

catch (MessagingException e) {
out.println("<p>Impossível enviar o email.</p>");
}
%>
</body>
</html>

No arquivo acima, optamos por levantar as exceções na própria página jsp de onde se
envia o email, poderíamos ter definido uma página de erro para fazer este tratamento.
São dois os possíveis erros decorrentes da tentativa de enviar o email :

O código abaixo, ilustra o tratamento da exceção gerada por endereço de email inválido.

catch (AdressException e) {
out.println(“<p>Endereço de Email inválido</p>”);
}

No trecho de código seguinte, fazemos o tratamento da exceção gerada pelo não envio
da mensagem. Essa exceção pode ser causada por vários problemas, tais como:
problema no servidor de email, problemas na rede, entre outros.

catch (MessagingException e) {
out.println(“<p>Impossível enviar o email.</p>”);
}

Exercício :

1 – Crie uma página JSP que , quando executada, lê um arquivo texto com uma lista de
e-mails e envia um texto pré-definido para cada e-mail da lista. Se ocorrer algum erro
no decorrer deste processo, este deve ser tratado numa página de erro chamada error.jsp.
O código abaixo implementa a funcionalidade de ler um arquivo num formato pré-
definido e armazenar seu conteúdo numa estrutura de dados denominada Properties.
Você deve incrementá-lo com o código de envio de e-mail para todos os e-mails
carregados do arquivo lido.

<%@page import="java.util.Properties" %>


<%@page import="javax.activation.*" %>
<%@page import="java.io.*" %>
<%@page import="java.util.*" %>
Properties table; //declarando uma tabela para armazenar os dados do arquivo
table = new Properties(); //instanciando nova tabela de propriedades

/*
Buscando o arquivo a ser inserido na tabela
O arquivo deve ter o seguinte formato:
email1 curso@dataprev.gov.br
email2 .........

71
email3 .........
email4 .........
*/

FileInputStream input;
input = new
FileInputStream(" Caminho completo para o arquivo ");
table.load(input); //Carregando dados do arquivo
input.close(); //Fechando fluxo entrada de dados
//Laço para varrer a estrutura table com os e-mails lidos do arquivo
for(int i=0; i < table.size(); i++) {

//para recuperar o e-mail 1 fazer : table.getProperty("email1”); e assim


//sucessivamente para cada e-mail

72
VII – Trabalhando com Banco de Dados
Este capítulo cobre os seguintes tópicos :

− Introdução a API JDBC


− Como instalar um driver JDBC
− Como estabelecer uma conexão com um banco de dados
− Interagindo com banco de dados
− Executando consultas
− Executando alterações
− Executando stored procedures
− A classe ResultSet

Hoje em dia, a maioria dos sites da internet que produzem conteúdo dinâmico fazem
uso de algum banco de dados. Gerenciamento de anúncios, informações de usuários,
lista de contato, compras on-line são apenas alguns dos recursos comumente
gerenciados através de um banco de dados.

Diferentemente de outras linguagens (PHP, Cold Fusion, etc), JSP não define um
conjunto próprio de comandos para acessar um banco de dados específico (em PHP por
exemplo, existe um conjunto específico de comandos para acessar cada banco de dados
diferente, consequentemente, uma página projetada para acessar o MySQL tem que ser
refeita se quisermos mudar o banco para Interbase), mas sim utiliza a API JDBC de
java para isso. Como todos os drivers de diferentes fabricantes baseiam sua
implementação nas interfaces e classes definidas nesta API, todos eles implementam o
mesmo conjunto de métodos (com as mesmas assinaturas). Sendo assim, se quisermos
mudar o banco de dados da nossa aplicação java, basta apenas carregar o driver
referente ao novo banco que tudo continuará funcionando com (quase) nenhuma
alteração no código da aplicação.

Instalando um Driver JDBC

O primeiro passo para se estabelecer uma conexão com um banco de dados utilizando
java é obter o driver JDBC do banco em questão. Existe um serviço no site da SUN que
reúne inúmeros drivers de diferentes fabricantes e permite configurar uma consulta para
buscar pelo driver JDBC desejado (http://servlet.java.sun.com/products/jdbc/drivers).

Os drivers geralmente são fornecidos como arquivos com extensão .JAR. Arquivos .jar
são geralmente usados para agrupar todos os arquivos de uma determinada aplicação
Java. Dentro deles pode-se ter desde .class, arquivos html de documentação a arquivos
de áudio. Com esse tipo de recurso você pode criar uma espécie de executável para
Java, bastando para isso, associar o tipo .jar com o java.exe ou com o javaw.exe
facilitando assim a distribuição de suas aplicações. Alem disso, arquivos jar podem ser
úteis para distribuir conjuntos de pacotes que se prestem a realizar alguma operação. É
comum, por exemplo, ver os drivers JDBC(Java Database Connectivity) ou applets
serem distribuídos nesse tipo de arquivo. Os arquivos jar usam um padrão de
compressão baseado no formato de compressão zip de modo que qualquer aplicativo
que suporte esse formato pode abrir e manipular um .jar.

Há várias maneiras de “instalar” um Jar para ser usado pela sua aplicação web:

73
• A forma mais simples é copiar o arquivo para o diretório
<JAVA_HOME>\jre\lib\ext. Isso torna o arquivo automaticamente visível ao
jdk e todas as aplicações, web ou não, irão reconhece-lo.
• Outra forma é copiar o arquivo para qualquer diretório na máquina e então
referenciar seu caminho totalmente qualificado na variável de ambiente
CLASSPATH. O jdk faz uso dessa variável para acrescentar as libs aí definidas
à sua lista de bibliotecas. O incoveniente dessa abordagem é que as IDEs de
desenvolvimento geralmente ignoram o CLASSPATH de maneira que você terá
que adicionar o arquivo jar manualmente ao conjunto de libs reconhecidos pela
sua IDE. Como em cada IDE há uma maneira diferente de se fazer isso, não irei
explicar como fazê-lo.
• Outra alternativa é copiar o arquivo para o diretório WEB-INF/lib do contexto
que sua aplicação faz parte. Isso faz com que somente a aplicação web dentro
deste contexto tenha acesso ao arquivo Jar.

Mais sobre arquivos Jar pode ser encontrado em:

http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jar.html

Conectando um Banco de Dados

Uma vez instalado o driver JDBC do banco que desejamos utilizar, temos que
configurar as informações necessárias para estabelecermos uma conexão. Para tanto,
utilizaremos a classe javax.sql.DataSource implementada pelo driver. Essa classe
encapsula todas as informações necessárias para obtermos uma conexão com um
determinado banco de dados (driver, localização, usuário, senha, etc), permitindo que
eliminemos as informações de conexão do código (caso usemos JNDI para registrá-lo) e
criando uma interface única através da qual iremos nos referir ao banco desejado. Se por
exemplo mudarmos a base de dados de local ou as informações de login mudarem, basta
apenas alterarmos suas propriedades com as novas informações e qualquer código que o
esteja utilizando não precisará ser alterado.

Abaixo seguem alguns exemplos para criação de objetos DataSource :

Para instanciar o objeto, utilizamos o nome de classe totalmente qualificado. Esse nome
vai depender do banco que se deseja acessar. O código abaixo apresenta a definição de
um DataSource para acessar um banco Oracle.

oracle.jdbc.pool.OracleDataSource ds = new oracle.jdbc.pool.OracleDataSource();


ds.setDatabaseName("sart");
ds.setUser("sart");
ds.setPassword("sart");
ds.setPortNumber(1521);
ds.setServerName("10.82.0.205");
ds.setURL("jdbc:oracle:thin:@10.82.0.205:1521:sart");

Já o código abaixo apresenta a configuração de um DataSource para acessar um banco


no Interbase.

interbase.interclient.DataSource ds = new interbase.interclient.DataSource();


ds.setServerName("10.82.0.220");
ds.setDatabaseName("/home/httpd/html/portal_ms/portal.gdb");

74
ds.setUser("SYSDBA");
ds.setPassword("masterkey");

Uma vez tendo instanciado apropriadamente um objeto DataSource, podemos usar seu
método getConnection para obtermos uma conexão com o banco que o objeto
referencia.

java.sql.Connection con = ds.getConnection();

Interagindo com Banco de Dados

Uma vez tendo estabelecido uma conexão com um banco de dados (com um usuário
com privilégios suficientes), podemos comandar os mais diversos tipos de operações
para que este as execute : consultas, alterações nas informações das tabelas ou em sua
estrutura, execução de stored procedures, dentre outras. É importante lembrar que,
sempre depois que a conexão for utilizada, esta deve ser fechada com o comando
close().

 Executando consultas

Para comandarmos a execução de uma consulta utilizamos a classe Statement, cujo


objeto é obtido através do método createStatement() do objeto Connection como
exemplificado no código abaixo :

java.sql.Statement stm = con.createStatement();

Uma vez obtido um objeto Statement, podemos definir uma consulta e submeter sua
execução ao banco através do método executeQuery(String query) do objeto Statement :

java.sql.ResultSet rs = stm.executeQuery(“select * from USERS”);

O parâmetro query é uma String com uma consulta qualquer na linguagem SQL
suportada pelo banco. O método retorna um objeto da classe ResultSet. Falaremos mais
sobre este objeto posteriormente.

Alternativamente à classe Statement, podemos utilizar a classe PreparedStatement para


submetermos nossas consultas. As instruções preparadas nos permitem desenvolver um
modelo de consulta SQL que podemos reutilizar para tratar de solicitações similares,
que diferem, entre cada execução, apenas em alguns parâmetros. Montamos a consulta
deixando as variáveis com valores indefinidos, representados por sinais de interrogação
que serão substituídos antes da execução da consulta. Ao usar instruções preparadas, o
SGBD, a medida do possível, executa o parser na consulta, realiza otimizações, cria o
plano de execução e o armazena para reutilização sempre que esta consulta for
solicitada, sem a necessidade de executar todos esses passos novamente. Um objeto
dessa classe é obtido através do método prepareStatement(query) da classe Connection :

java.sql.PreparedStatement pstm = con.prepareStatement(query);

Vejamos o exemplo abaixo :

String query = “select nome,dt_nascimento,salario from EMPREGADOS where


dt_admissao > PAR_1 and salario < PAR_2”

75
se quiséssemos que os valores de dt_nascimento e salario fossem passados em tempo de
execução utilizando a classe Statement, faríamos da seguinte forma

java.sql.Statement stm = con.createStatement();


//Montagem da consulta
String query = “select nome, dt_nascimento, salario from EMPREGADOS where
dt_admissao > ‘ “ + data_formato_banco + “ ‘ and salario < “+
salario_formato_banco ;
//Execução da consulta
java.sql.ResultSet rs = stm.executeQuery(query);

e, utilizando PreparedStatement seria

//Montagem da consulta
String query = “select nome, dt_nascimento, salario from EMPREGADOS where
dt_admissao > ? and salario < ?” ;
//Substituição dos valores
java.sql.PreparedStatement pstm = con.prepareStatement(query);
pstm.setDate(1,java.sql.Date.valueOf(“data_formato_JDBC”)); // yyyy-mm-dd
pstm.setDouble(2, Double.parseDouble(“salario”));
//Execução da consulta
java.sql.ResultSet rs = pstm.executeQuery();

Perceba como a montagem da consulta para execução através de um Statement pode


rapidamente ficar confusa, especialmente com consultas complexas. Outro benefício da
utilização de instruções preparadas, e talvez o mais importante, é que, quando se insere
um valor com um de seus métodos setter, não é preciso se preocupar sobre a colocação
adequada de aspas em cadeias, com caracteres especiais, inserção de valores nulos e
nem com conversões de datas e outros valores no formato adequado para seu banco de
dados. Já que cada banco de dados pode ter suas próprias peculiaridades de formatação,
especialmente para datas, usar instruções preparadas vai ajudar a distanciar ainda mais
seu código da necessidade de lidar com um banco em particular, tornando sua aplicação
mais genérica e flexível.

 Executando alterações

Já vimos como executar consultas num banco de dados através do método executeQuery
das classes Statement e PreparedStatement, método este que retorna um ResultSet com
o resultado da consulta. Veremos agora como submeter instruções que modificam
valores das tabelas, alteram sua estrutura ou criam novos objetos dentro do banco.

Os comandos SQL para realizar modificações no conteúdo de uma tabela são : update,
insert e delete. Essas instruções podem ser submetidas ao banco através do método
executeUpdate existente em ambas as classes e que retorna um inteiro com o número de
linhas afetadas pela execução do comando. Vejamos os exemplos :

//Com a classe Statement


java.sql.Statement stm = con.createStatement();
//Montagem da instrução de atualização

76
String insert = “insert into EMPREGADOS values ( “ ‘ + request.getParameter(“nome”)
+ “ ’ , ” + request.getParameter(“salario”) + “, ‘ ” +
request.getParameter(“dt_admissao”) + “ ‘ )”;
//Execução da consulta
int x = stm.executeUpdate(insert);

//Com a classe PreparedStatement


//Montagem da consulta
String update = “update EMPREGADOS set salario = ? where dt_admissao < ?” ;
//Substituição dos valores
java.sql.PreparedStatement pstm = con.prepareStatement(update);
pstm.setDouble(1, Double.parseDouble(request.getParameter(“salario”)));
pstm.setDate(2, java.sql.Date.valueOf(request.getParameter(“data”)));
//Execução da consulta
int x = pstm.executeUpdate();

Quando o comando for uma instrução DDL (Database Definition Language), como a
alteração ou criação de uma tabela, o valor de retorno deste método será zero. O
exemplo abaixo mostra um comando que cria uma stored procedure dcentro do banco.

String createProcedure = "create procedure SHOW_SUPPLIERS " +


"as " +
"select SUPPLIERS.SUP_NAME,
COFFEES.COF_NAME " +
"from SUPPLIERS, COFFEES " +
"where SUPPLIERS.SUP_ID = COFFEES.SUP_ID "
+ "order by SUP_NAME";
Statement stmt = con.createStatement();
stmt.executeUpdate(createProcedure);

Há ainda um terceiro método que executa indiscriminadamente qualquer tipo de


comando e retorna um valor booleano com o status da operação. O método

boolean execute(String) – para a classe Statement , e


boolean execute() – para a classe PreparedStatement

executa um comando qualquer, tanto de alteração como de consulta, e retorna true se


sua execução foi bem sucedida e false caso contrário. Caso o comando seja uma
consulta, é possível utilizar o método getResultSet() de ambas as classes para obtermos
o resultset correspondente. Já se o comando for uma alteração, podemos usar o método
getUpdateCount() para sabermos quantos registros foram afetados.

 Executando Stored Procedures

JDBC permite que executemos uma Stored Procedure de um banco de dados a partir de
uma aplicação java. Para isso, devemos criar um objeto da classe
java.sql.CallableStatement, que é uma subclasse de PreparedStatement, a partir de uma
conexão estabelecida com o banco :

java.sql.CallableStatement cs = con.prepareCall ("{call SHOW_SUPPLIERS}");

77
No código acima, instanciamos um objeto CallableStatement apto a executar a
procedure que criamos anteriormente. Quando o driver encontra "{call
SHOW_SUPPLIERS}" , ele irá traduzir esta sintaxe no SQL nativo usado pelo banco
para chamar a stored procedure chamada SHOW_SUPPLIERS. Para efetivamente a
executarmos, devemos fazer :

java.sql.ResultSet rs = cs.executeQuery();

O método que deve ser utilizado para executar a procedure depende do conteúdo da
mesma e está resumido na sequência abaixo :

• executeQuery() : quando a procedure contém apenas um comando que executa uma


consulta retornando apenas um result set
• executeUpdate() : quando a procedure executa uma alteração no conteúdo de uma
tabela ou um comando DDL
• excute() : quando a procedure retorna mais de um result set, mais de um update
count ou uma combinação de ambos

Quando for o caso de usar a terceira opção, deve-se usar o método getResultSet() ou
getUpdateCount() para obter o resultado. Para obter todos os resultados usar o método
getMoreResults() que irá posicionar no próximo result set ou update count. Este método
retorna true caso o próximo resultado retorne um result set e, como o método
getUpdateCount() retorna –1 caso não existam mais resultados, pode-se usar a seguinte
expressão como condição de parada num laço para varrer todos os resultados:

((getMoreResults() == false) && (getUpdateCount() == -1))

Também é possível passarmos parâmetros de entrada ou lermos parâmetros de saída de


uma stored procedure. Imaginem uma stored procedure que retorna o próximo valor de
chave primária de uma tabela. Para a executarmos e lermos seu valor de retorno o
código é o seguinte :

CallableStatement cs = con.prepareCall("{? = call GetPrimaryKey(“XX”)}");


cs.registerOutParameter(1, java.sql.Types.INTEGER);
cs.setInt(“XX”,10);
cs.execute();
return cs.getInt(1);

Primeiro criamos a string que vai representar a chamada à procedure com seu parâmetro
de retorno e entrada - "{? = Call GetPrimaryKey( [arg1, arg2, ...] )}". Depois dizemos
que o primeiro parâmetro da procedure é um parâmetro de saída e que é do tipo inteiro -
registerOutParameter(1, java.sql.Types.INTEGER) e então atribuímos um valor
apropriado para o parâmetro de entrada. Feito isso, basta executarmos a procedure com
o método execute() e então ler o valor retornado - getInt(1).

 A classe ResultSet

Por último, mas não menos importante, vamos aprender um pouco sobre um dos
componentes mais importantes quando estamos trabalhando com banco de dados, o
result set. Quem já desenvolveu uma aplicação que acessa um banco de dados, com
qualquer tecnologia que seja, já deve ter se deparado com algo similar a classe
ResultSet do java. A grosso modo, um result set é uma estrutura de dados em memória,

78
uma matriz que armazena o resultado de uma consulta SQL. Um CURSOR em Oracle é
um result set, o componente Query do Delphi representa um result set, uma classe que
implementa a interface ResultSet do java implementa um result set.

Nas aplicações, muito frequentemente precisamos iterar sobre um result set para
apresentar o resultado de uma consulta, fazer buscas por dados específicos no seu
repositório sem a necessidade de acessar o banco novamente e, quando a tecnologia
permite, alterar os dados diretamente no result set, alterações estas que serão
automaticamente replicadas no banco de dados.

A interface ResultSet pertence ao pacote java.sql e foi definida a primeira vez na


especificação 1.0 da API JDBC. Esta primeira proposta é bastante limitada, sendo
possível iterar apenas numa única direção (para frente) no result set e seus valores são
apenas para leitura porém, é suportada pela maioria dos fabricantes de drivers JDBC. A
especificação 2.0 de JDBC trás uma interface ResultSet muito mais funcional e
poderosa. Agora é possível navegar em qualquer direção (para frente ou para trás) no
result set, mover o cursor para uma posição específica e atualizar valores no próprio
result set ao invés de usar comandos SQL.

Obtendo valores de um ResultSet

Mostraremos nesta sessão como ler o conteúdo de um objeto ResultSet. Apesar dos
métodos aqui definidos fazerem parte da especificação 1.0 de JDBC, eles são
equivalentes para a 2.0.

Usamos os métodos getters do ResultSet para obtermos o valor de uma determinada


coluna. O método get apropriado depende do tipo da coluna em questão. Vejamos o
exemplo abaixo :

String query = "SELECT COF_NAME, PRICE FROM COFFEES";


ResultSet rs = stmt.executeQuery(query);
while (rs.next()){ //este método faz com que o cursor mova-se uma linha para frente
String s = rs.getString("COF_NAME");
float n = rs.getFloat("PRICE");
System.out.println(s + " " + n);
}

O método getString("COF_NAME") retorna o conteúdo da coluna COF_NAME na


linha onde está posicionado o cursor do result set rs. Este método converte o tipo
VARCHAR de SQL para o tipo String de java. O mesmo acontece na linha
getFloat("PRICE"), onde o valor da coluna PRICE é lido e o tipo SQL Float é
convertido para o tipo float de java.

É possível referenciar uma coluna pelo seu nome ou pelo seu índice. Isso é
particularmente útil quando temos duas colunas com o mesmo nome num result set.
Assim, no exemplo acima os métodos get ficariam getString(1), para obter o valor da
coluna COF_NAME e getFloat(2) para obter o valor de PRICE.

Existe uma grande variedade de métodos get para convertemos os diferentes tipos de
dados SQL para tipos da linguagem java. O método getSring pode ser usado para obter
qualquer tipo, convertendo tudo para uma String. Abaixo segue uma tabela com um

79
resumo dos principais métodos get. Um “x” significa que o método pode ser usado para
obter aquele tipo e um “X” significa que o método é recomendado para aquele tipo.

L
L O
O V N T
S
T I D N V N A G I
M B D B
I N F E U A G R V M
A I R O C I D T
N T L C M B R V B A E
L G E U H N A I
Y E O I E I C A I R S
L I A B A A T M
I G A M R T H R N B T
I N L L R R E E
N E T A I A C A I A
N T E Y
T R L C R H R N M
T
A Y A P
R R
Y
getInt x x X x x x x x x x x x x

getFloat x x x x X x x x x x x x x

getDouble x x x x x X X x x x x x x

getBoolean x x x x x x x x x X x x x

getString x x x x x x x x x x X X x x x x x x x

getBytes X X x

getDate x x x X x

getTime x x x X x

getTimestamp x x x x x X

getAsciiStream x x X x x x

getUnicodeStream x x X x x x

getBinaryStream x x X

getObject x x x x x x x x x x x x x x x x x x x

Scrollable e Updatable ResultSet

Abaixo temos as sintaxes para criação deste objeto através de um Statement,


PreparedStatement ou CallableStatement :

• connection.createStatement(int resultSetType, int resultSetConcurrency)


• connection.preparedStatement(String sql, int resultSetType, int resultSetConcurrency)
• connection.prepareCall(String sql, int resultSetType, int resultSetConcurrency)

O parâmetro resultSetType define se o ResultSet irá ser navegável ou não. Os três


valores possíveis são :

• ResultSet.TYPE_FORWARD_ONLY : com este parâmetro o ResultSet não poderá


ser navegável, ou seja, poderemos somente avançar para frente no objeto.

• ResultSet.TYPE_SCROLL_INSENSITIVE : com este parâmetro o ResultSet


poderá ser navegável em qualquer direção, para frente e para trás, e será insensível a
mudanças feitas por outras transações ou por outros Statements da mesma transação.
Isto significa que, se o ResultSet for updatable e sofrer uma modificação, uma
leitura no valor modificado ainda não será visível.

80
• ResultSet.TYPE_SCROLL_SENSITIVE : com este parâmetro o ResultSet poderá
ser navegável para qualquer direção, e será sensível a mudanças feitas por outras
transações ou por outros Statements da mesma transação. Isto significa que, se o
ResultSet for updateable e sofrer uma modificação, uma leitura no valor modificado
já será visível logo após.

Já o parâmetro resultSetConcurrency define se o ResultSet será editável ou não. Os dois


valores possíveis são:

• ResultSet.CONCUR_READ_ONLY: com este parâmetro o ResultSet não poderá


ser manipulável, ou seja, não poderemos alterar os valores contidos no ResultSet.

• ResultSet.CONCUR_UPDATABLE: com este parâmetro o ResultSet poderá ser


manipulável, ou seja, poderemos alterar os valores contidos no ResultSet.

Um ResultSet scrollable tem a capacidade de navegabilidade e de posicionamento. Os


métodos pertinentes à navegação estão resumidos na tabela abaixo :

Método Descrição
boolean first() posiciona o cursor na primeira linha do ResultSet e retorna true, caso não exista
linhas, retorna false.
boolean last() posiciona o cursor na última linha do ResultSet e retorna true, caso não exista
linhas, retorna false.
boolean previous() posiciona o cursor para a linha anterior a posição corrente, retorna true caso a
linha seja válida e false caso contrário.
boolean absolute(int row) posiciona o cursor corrente para a linha especificada pelo parâmetro tendo
como referência o início e o fim do resultset, retorna true caso a linha é valida
ou false caso contrário. Se o valor for negativo, o cursor moverá o valor
especificado a partir do final.
boolean relative(int offset) posiciona o cursor corrente para a linha especificada pelo parâmetro tendo
como referência a posição corrente do cursor, retorna true caso a linha é valida
ou false caso contrário.
void beforeFirst() posiciona o cursor antes da primeira linha.
void afterLast() posiciona o cursor depois da última linha.
boolean isFirst() retorna true caso o cursor corrente está posicionado na primeira linha.
boolean isLast() retorna true caso o cursor corrente está posicionado na última linha.
boolean isBeforeFirst() retorna true caso o cursor corrente está posicionado antes da primeira linha.
boolean isAfterLast() retorna true caso o cursor corrente está posicionado após a última linha.
Int getRow() retorna o número da linha corrente do cursor.

Suponhamos um ResultSet rs com 500 linhas e inicialmente posicionado na primeira


linha. Os códigos abaixo produziriam os seguintes efeitos :

rs.absolute(-1) : move o cursor para a última linha, isto é, linha 500

rs.absolute(-4) : move o cursor para a linha 497

rs.absolute(4) : move o cursor para a linha 4

rs.relative(-3) : move o cursor para primeira linha

rs.relative(2) : move o cursor para terceira linha

81
Com um ResultSet do tipo updatable podemos executar as operações de INSERT,
DELETE e UPDATE sem precisar criar os comandos SQL. Utilizando métodos do
próprio ResultSet, podemos inserir, deletar e alterar seus valores e depois refletir estas
operações para o banco de dados.

Para realizarmos alterações (UPDATE) utilizamos os métodos updateXXX de acordo


com o tipo da coluna que queremos alterar. A tabela abaixo apresenta os principais
métodos para update :

Método Descrição
updateBoolean(String columnName, boolean Atualiza a coluna com um booleano
x)
updateDate(String columnName, Date x) Atualiza a coluna com uma data
updateDouble(String columnName, double x) Atualiza a coluna com um double
updateInt(String columnName, int x) Atualiza a coluna com um int
updateNull(String columnName) Atualiza a coluna com um valor nulo
updateObject(String columnName, Object x) Atualiza a coluna com um objeto
updateString(String columnName, String x) Atualiza a coluna com uma string
updateTimestamp(String columnName, Atualiza a coluna com um Timestamp
Timestamp x)

Como nos métodos getters do ResultSet, todos os métodos acima possuem uma versão
onde, ao invés de passarmos o nome da coluna, passamos o seu índice no result set.

Uma vez alterado o valor de uma coluna, para que a alteração seja refletida na base de
dados utilizamos o método: updateRow(). Este método propaga a alteração feita no
ResultSet para a linha no banco de dados e efetua o commit.

rs.updateFloat("PRICE", 10.99);
rs.updateRow();

Se uma alteração for efetuada e o cursor se mover daquela linha antes do método
updateRow() ser invocado, a alteração é perdida. É possível também cancelarmos
alterações realizadas em uma linha chamando o método cancelRowUpdates().

Para realizarmos inserções (INSERT) utilizamos o método moveToInsertRow(), sendo


o InsertRow uma linha especial dentro do ResultSet diferente das linhas já existentes.
Após a utilização deste método, inserimos os dados utilizando o método updateXXX()
apropriado para cada coluna. Se uma coluna que é NOT NULL no banco não for
preenchida, ao tentar efetivar a inserção será lançado um erro de SQLException. Para
voltarmos o cursor para a posição que estávamos antes da inserção, utilizamos o método
moveToCurrentRow(), que só pode ser chamado se o cursor estiver numa IsertRow.
Depois de terminado o INSERT, utilizamos o método insertRow() para efetuar as
modificações no banco de dados. O fragmento abaixo apresenta a sequência completa
desde a criação do objeto Connection até a inserção de um registro no result set :

Connection con = ds.getConnection();


Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet uprs = stmt.executeQuery("SELECT * FROM COFFEES");
uprs.moveToInsertRow();

82
uprs.updateString("COF_NAME", "Kona");
uprs.updateInt("SUP_ID", 150);
uprs.updateFloat("PRICE", 10.99);
uprs.updateInt("SALES", 0);
uprs.updateInt("TOTAL", 0);
uprs.insertRow();

Para fazer a deleção (DELETE) de uma linha do ResultSet, tudo que temos a fazer é
posicionar o cursor na linha a ser excluída e então chamar o método deleteRow().

Considerações Finais

• É importante estar ciente que apenas especificar que um ResultSet seja updatable
não garante que ele o seja. Se o driver não suporta result sets atualizáveis, ele irá
retornar um apenas para leitura.
• A consulta especificada para criação do result set implica se este poderá ser
atualizável. É aconselhável que a consulta sempre inclua os nomes das colunas e não
o “*” e uma restrição é que não pode haver join entre tabelas e esta deve ter ao
memos uma chave primária definida.

83
Exercícios :

Considere um banco de dados que contenha uma tabela chamada EMPREGADO_JSP


com a seguinte estrutura :

COLUNA TIPO
COD_EMP NUMBER(4) NOT NULL
NOME_EMP VARCHAR(100) NOT NULL
SALARIO_EMP FLOAT
DT_INICIO_EMP DATE

Com base nos dados acima resolva os exercícios.

1 – Faça um página JSP com as seguintes funcionalidades :

- Crie um objeto DataSource para se conectar ao banco. A classe no driver


JDBC do oracle que implementa a interface DataSource é :
oracle.jdbc.pool.OracleDataSource
- Obtenha uma conexão com o banco utilizando o DataSource criado
- Utilizando a classe Statement, crie uma consulta que pegue todo o conteúdo
da tabela
- Utilize o ResultSet retornado para imprimir todas as suas linhas na tela

2 – Crie uma página que apresenta o resultado de duas consultas :

- Na primeira, utilizando a classe Statement, obtenha o nome e salário de


todos os empregados com data de admissão menor que 01/01/2002
- Na segunda, utilizando a classe PreparedStatement, obtenha o nome e salário
de todos os empregados com data de admissão igual ou superior a
01/01/2002.

Dica : Quando possível, utilize o método java.sql.Date.valueOf (“yyyy-mm-dd”)

3 – Utilizando PreparedStatement, inclua um registro com as suas informações


funcionais.

Dica : o comando de inserção é INSERT INTO <tabela> VALUES (valor1,


valor2,valor3, ...)

4 – Faça uma página JSP que cria um objeto ResultSet scrollable e updatable com todos
os registros da tabela e realize as seguintes operações com ele :

- Imprima quantas linhas tem o result set


- Mova o cursor para a linha que tem o seu nome e imprima o nº da linha e o
seu salário
- Atualize a informação do seu salário aumentando-o em 10%
- Imprima o novo valor do seu salário. Você viu a informação já atualizada ?
Explique.

84
VIII - Java Util
Em projetos de software, freqüentemente usamos diversas estruturas de dados. Não
seria interessante ter que a cada estrutura necessária termos que implementá-la, uma vez
que sempre precisamos de rapidez e agilidade no desenvolvimento. Para auxiliar nosso
desenvolvimento usando estruturas de dados prontas existe um pacote na API da
plataforma Java chamado util. Neste pacote encontram-se várias estruturas de dados,
utilitários para manipulação de data e hora, e diversas outras classes utilitárias. Neste
capítulo veremos algumas destas classes a saber : as classes Vector e StringTokenizer,
como também a interface Enumeration.
A classe Vector implementa um vetor que cresce dinamicamente de acordo com as
necessidades e pode armazenar qualquer tipo de dado. Enumeration não é uma classe,
mas sim uma interface. Ela descreve estruturas que devem ser acessadas
sequencialmentes, uma por vez. A classe StringTokenizer é útil para quebrar a string em
partes menores também chamadas de tokens.

A classe Vector

O uso de arrays na maioria das linguagens deve ter o seu tamanho definido no momento
da alocação de espaço de memória ocupado por esta estrutura. Por exemplo, se
quisermos usar o array de 50 posições inteiras fazemos :

int myArray[] = new int[50];

Esta instrução aloca 50 inteiros na memória e torna esta área de memória acessível
através do identificador myArray. No entanto, o que acontece se a nossa lista de inteiros
for maior que 50 posições e eu não consiga conhecer o tamanho no momento da criação
do programa ? Uma alternativa para este problema é usar a classe Vector. Esta classe
fornece uma implementação para arrays que podem crescer dinamicamente. O Vector,
como um array, acessa seus elementos através de um índice e fornece diversos métodos
que auxiliam o seu uso.
Nesta estrutura há um gerenciamento dinâmico do tamanho. Ocorre que quando é
atingido um limite máximo de ocupação da estrutura, ela inclui mais alguns elementos
para manter a possibilidade de novas inserções. Quando deseja-se usar um Vector para
armazenar grandes quantidades de dados podemos definir seu tamanho inicial, evitando
assim que este reajuste de tamanho seja realizado várias vezes, uma vez que o tamanho
inicial de um Vector padrão é baixo (10 elementos).
A classe Vector possui, dentre outros, os seguintes métodos para a sua utilização :

Construtores:
Vector() Cria um Vector de tamanho 10
Vector (int initialCapacity, Cria um vetor com a capacidade inicial e capacidade de
int CapacityIncrement) incremento especificados
Cria um vetor com o tamanho indicado e capacidade de
Vector(int initialCapacity)
incremento igual a 0

85
Métodos para inserção e exclusão:
boolean add(Object obj) Inclui o objeto obj no fim do Vector
Inclui o objeto no Vector na posição indicada por
index. Caso a posição indicada seja inexistente no
boolean add(int index, Object
obj) Vector uma exceção do tipo
ArrayIndexOutOfBoundsException é
disparada.
Inclui o objeto no fim do Vector incrementa ndo seu
boolean addElement(Object obj)
tamanho em 1.
boolean remove(int index) Remove o elemento do índice index
Remove a primeira ocorrência do elemento, caso ele
boolean remove(Object obj)
não exista o vetor é inalterado
void clear() Remove todos os elementos do vetor
void removeAllElements() Remove todos os elementos do Vector e passa
seu tamanho para 0

Alguns métodos importantes:


boolean isEmpty() retorna se o Vector é vazio.
Procura pela primeira ocorrência do elemento elem.
int indexOf(Object elem) Retorna -1 se o elemento não for encontrado.

int capacity () Retorna a capacidade corrente do vetor


int size() Retorna o número de elementos no Vector.
Object elementAt(int index) Retorna o elemento do índice index

Note que todos os objetos que são passados para o Vector são da classe Object. Por
padrão, todo objeto em Java herda da classe Object, logo, por herança, você pode
guardar qualquer objeto dentro de um Vector.

Exemplo:

import java.util.*;

public class Util1 {

private static Vector vetor;

public static void main(String args[]) {

vetor = new Vector();


vetor.add(new Integer(20));
vetor.add(new Double(256.20));

System.out.println("Total : " + vetor.size());


System.out.println("Posição do Inteiro : " + vetor.indexOf(new Integer(20)));

int inteiro = ((Integer) vetor.elementAt(0)).intValue();


double decimal = ((Double) vetor.elementAt(1)).doubleValue();

System.out.println("Inteiro: " + inteiro);


System.out.println("Double : " + decimal);
}

}
86
O programa exemplo acima inclui dois objetos no Vector, imprime o tamanho do
Vector e procura pelo inteiro incluído. Note que não podemos incluir um int ou um
double no Vector pelo fato de tipos primitivos em Java não serem objetos. Por isso, foi
usado Integer e Double, classes que representam um inteiro e um número de ponto
flutuante respectivamente.

Note que na retirada dos elementos do Vetor o casting deve ser realizado. Isto se deve
ao fato do método elementAt retornar um Object que deve ser "convertido" para a classe
que ele realmente representa.

A Interface Enumeration

Objetos que implementam Enumeration são construídos e retornados por diversas


estruturas, como no Vector mostrado abaixo:

Enumeration enum = v.elements();

O objeto retornado pelo método v.elements() implementa a interface Enumeration, logo,


pode ser identificado através da interface. Os objetos que implementam a interface
Enumeration possuem os seguintes métodos obrigatoriamente :

Retorna true se a Enumeração ainda contém elementos a ser


boolean hasMoreElements()
percorrido.
Object nextElement() Retorna o próximo objeto da enumeração

O exemplo abaixo ilustra um uso da estrutura Enumeration :

import java.util.*;

public class Exemplo1 {

static Vector vetor;


public static void main( String args[] ) {

vetor.add( "String 1" );


vetor.add( "String 2" );
vetor.add( "String 3" );

Enumeration enum = vetor.elements();

while ( enum.hasMoreElements() )
System.out.println( enum.nextElement() );
}
}
Neste exemplo, o Vector retorna uma enumeração de todos os seus elementos. O while
imprime os elementos da enumeração enquanto ainda existir elementos .

A classe StringTokenizer

Para finalizar o pacote Util, falaremos um pouco do StringTokenizer. A classe


StringTokenizer é muito útil quando queremos quebrar a String em diversas substrings
delimitadas por uma outra String. Vamos a um exemplo:

87
A String "aaa/bbb/ccc/ddd" pode ser quebrada em quatro Strings "aaa", "bbb", "ccc" e
"ddd" através do delimitador "/". A realização desta separação com o StringTokenizer é
mostrado abaixo:

import java.util.*;

public class TokenizerExemplo {

public static void main ( String args[] ) {


StrinTokenizer st = new StringTokenizer( "aaa/bbb/ccc/ddd", "/" );

while ( st.hasMoreTokens() )
System.out.println ( st.nextToken() );
}
}
Como pode ser visto no exemplo acima, a classe StringTokenizer tem um
comportamento muito parecido com a interface Enumeration, de fato ele implementa
esta interface. Abaixo está a descrição desta classe:

Há três construtores para esta classe:


Cria uma StringTokenizer para a String str com o caractere
StringTokenizer(String str)
de espaço como delimitador.
StringTokenizer(String str, Cria um StringTokenizer com o delimitador definido pela
String delimit) String delimit.
StringTokenizer(String str, Cria um StringTokenizer com o delimitador definido pela
String delimit, boolean String delimit, e caso retDelimit seja true, retorna o
retDelimit) delimitador junto com o método nextToken()

Alguns métodos úteis:


int countTokens() Retorna o número de tokens.
boolean hasMoreTokens() Verifica se existem mais tokens na enumeração
String nextToken() Retorna o próximo token da enumeração

88
Apêndice A

Tratando Formulários
Os formulários são ferramentas úteis e muito usados em diversas aplicações: cadastro de
registros em um banco de dados, validação de um login/senha, envio de email, envio de
dados de um pesquisa, etc. Hoje é difícil desenvolver uma aplicação para Web que não
exija o uso de formulários. Pois bem, na lição de hoje vamos aprender manipular
formulários em aplicações JSP.
Apresentamos abaixo um código para mostrar o formato de um formulário HTML e de
seus objetos.
<html>
<body>

<!-- cabeçalho do formulário -->


<form name="nomedoformulario" action="paginajsp.jsp" method="get">

<!-- caixa de texto -->


<input type="text" name="variavel1" size=40 maxlength=40>

<!-- caixa de texto para senha -->


<input type="password" name="variavel2" size=40 maxlength=40>

<!-objeto do tipo radio -->


<input type="radio" name="variavel2" value="valordavariavel">Texto da Varivavel 2

<!-objeto do tipo checkbox -->


<input type="checkbox" name="variavel3" value="xxxxx"> Texto da Varivavel 3

<!-objeto do tipo select -->


<select name="variavel4">
<option value="valor1">Valor 1
<option value="valor2">Valor 2
<option value="valor3">Valor 3
</select>

<!- area de texto -->


<textarea name="variavel5" cols=40 rows=2>
Texto da Variavel 5
</textarea>

<!- objeto hidden, para enviar dados que o usuário não vê no formulário -->
<input type="hidden" name="asd" value="asd">

<!- botão -->


<input type="button" value="textodobotao">

<!- botao de limpar informações do formulário -->


<input type="submit" value="limpar">

<!- botao de enviar formulário -->


<input type="submit" value="ok">
89
<!- imagem colocada para funcionar com botao de envio de formulário -->
<input type="image" src="pathdaimage/image.gif">

<!- objeto para anexar arquivo -->

<input type="file" name="asdas" accept="asd">

</form>

</body>
</html>

É importante fazermos algumas observações a cerca do código acima :


- no cabeçalho do formulário, indicamos através de
action="pathdoarquivo/paginajsp.jsp" o arquivo JSP que receberá os seus dados.
- cada objeto do formulário recebe um nome. Deve-se tomar bastante cuidado ao
nomear tais objetos, isto porque, como sabemos, as variáveis Java são sensíveis a
maiúscula/minúscula. Portanto, os objetos:
<input name="variavel1" type="text" value="">
<input name="Variavel1" type="text" value="">

são objetos diferentes porque receberam nomes diferentes (variavel1 e Variavel1).

Mostraremos mais um exemplo (bastante simples) de como enviar dados a partir de um


formulário a uma página JSP.
<%-- Arquivo teste.jsp --%>
<html>
<body>

<center><h1> <%= request.getParameter("teste") %> </h1></center>

<form action="teste.jsp" method=get>


<input type="text" name="teste" size=40 maxlength=40><br>
<input type="submit" value="enviar">
</form>

</body>
</html>

A página jsp acima, chamada "teste.jsp", contém um formulário que envia para ela
mesma. O valor digitado em uma caixa de texto será mostrado como título da página.
Observe como fizemos isso:
- a página para qual nós enviaremos os dados do formulário é designada no cabeçalho
do formulário:
<form action="teste.jsp" method=get>

- o nome do objeto caixa de texto ("teste") é usado na expressão


request.getParameter("teste"). Note que se usássemos request.getParameter("Teste")

90
(com T maiúsculo), a página não iria retornar o valor digitado na caixa de texto.

O próximo exemplo é formado por dois arquivos. O primeiro contém apenas códigos
HTML e o segundo contém códigos HTML e JSP.

Arquivo "envia_mês.htm":
<html>
<body>

<h3>Qual o mês do seu aniversário?</h3>


<form action="recebe_mes.jsp" method=get>
<select name="mesNasceu">
<option value="1">Janeiro
<option value="2">Fevereiro
<option value="3">Março
<option value="4">Abril
<option value="5">Maio
<option value="6">Junho
<option value="7">Julho
<option value="8">Setembro
<option value="9">Agosto
<option value="10">Outubro
<option value="11">Novembro
<option value="12">Dezembro
</select>

<input type="submit" value="enviar">


</form>

</body>
</html>

Arquivo "recebe_mês.jsp":
<%@ page import=java.util.Date %>
<%@ page import=java.lang.String %>
<%
String msg = "";
String mesString = request.getParameter("mesNasceu");
int mes = Integer.parseInt(mesString);
Date dateNow = new Date();
int monthNow = dateNow.getMonth() + 1;

mes -= monthNow;

if (mes == 1)
msg = "Falta apenas "+ mes +" mês para o seu aniversário.";

if (mes == -1)
msg = "Seu aniversário foi no mês passado";

91
if (mes > 1)
msg = "Faltam "+ mes +" meses para o seu aniversário.";

if (mes == 0)
msg = "Oba... estamos no mês do seu aniversário.";

else if (mes < 1)


{
mes *= -1;
msg = "Seu aniversário foi a "+ mes +" meses atrás.";
}

%>

<html>
<body>
<center>
<h3><%= msg %></h3>
<br><br><br>
<a href="Javascript:history.back(-1)">voltar</a>
</center>

</body>
</html>

O exemplo acima é um pouco menos simples que o primeiro. O arquivo "envia_mes-


jsp" contém um formulário com um objeto select que envia o mês que a pessoa nasceu.
Após escolher o mês e clicar no botâo "ok", o formulário chama a página
"recebe_mês.jsp" e envia seus dados para ela. Esta segunda página é um pouco menos
simples que a primeira. Vamos analisar o que ela faz:

- nas primeira linhas utilizamos as tags "page import" para indicar quais classes iremos
utilizar em nossa página:
<%@ page import=java.util.Date %>
<%@ page import=java.lang.String %>

- cinco objetos são criados e inicializados.

- Usamos o método "request.getParameter(´nomedoparametro´)" com a finalidade de


pegar o valor passado para a página através de algum formulário ou passando
diretamente em sua URL. O segundo objeto foi inicializado utilizando esse método para
pegar o valor passado pelo formulário:
String mesString = request.getParameter("mesNasceu");

- O valor passado através de um formulário ou através da URL da página é sempre do


tipo String. Ao inicilizarmos o terceiro objeto, o método
"Integer.parseInt(variavelString)" transformou o valor contido na variável mesString em
Inteiro : int mes = Integer.parseInt(mesString);

- O penúltimo objeto criado é do tipo Date (daí a importância de termos importado a

92
classe java.util.Date na primeira linha de nossa página). Ele é inicializado com a hora
local do servidor. : Date dateNow = new Date();

- Na inicialização do último objeto utilizamos o método "dateNow.getMonth()" que


retorna um inteiro indicando o valor da variável. Somamos 1 ao valor retornado a partir
desse método porque ele retorna 0 para janeiro, 1 para fevereiro e assim por diante : int
monthNow = dateNow.getMonth() + 1;

- Cinco teste são efetuados dentro de um scriptlet (<% e %>). Eles são usados para
definir o valor que a variável "msg" terá, ou seja, a partir dos testes, decidiremos qual
mensagem será exibida na tela.

- Após efetuar os testes, o texto HTML é inserido na página.

- Uma expressão (<%= %>) é usada para exibir o valor da variável "msg": <%= msg
%>

93
Apêndice B

Instalando um container JSP - TOMCAT


Para executarmos nossas páginas JSP na Web precisamos de um container JSP, um
software que seja capaz de interpretar as páginas e executá-las. Abordaremos de forma
bastante pragmática os passos necessários para instalação de um container JSP de
domímio público , o Tomcat, para rodar juntamente com o Apache. O site oficial desta
ferramenta e onde podem ser encontradas todas as informações a seu respeito é o
http://jakarta.apache.org/tomcat/index.html

Os passos para instalação do Tomcat 4.1.18 são :

1. Instalação do java
1.1 – Baixar o pacote SDK 1.4 de http://java.sun.com/j2se/1.4/download.html
1.2 – Descompactar o tar.gz em /usr/local
1.3 – Criar um link simbólico chamado jdk para /usr/local/j2sdk1.4.1_01
1.4 – Editar o /etc/profile acrescentando as seguintes linhas :

JAVA_HOME=/usr/local/jdk
PATH="$PATH:/usr/local/jdk/bin"
Export JAVA_HOME

2. Baixar o pacote jakarta-tomcat-4.1.18.tar.gz de :


http://jakarta.apache.org/builds/jakarta-tomcat-4.0/release/v4.1.18/bin/

3. Descompactá-lo em /usr/local
4. Criar um link simbólico chamado tomcat para /usr/local/jakarta-tomcat-4.1.18/
5. Editar o arquivo /etc/profile acrescentando as seguintes linhas ;

TOMCAT_HOME=/usr/local/tomcat
CATALINA_HOME=/usr/local/tomcat
CLASSPATH=.
export TOMCAT_HOME CATALINA_HOME CLASSPATH

6. Obter o módulo mod_jk-3.3-ap13-noeapi.so de :


http://jakarta.apache.org/builds/jakarta-tomcat/release/v3.3/bin/linux/i386/ e copiá-lo
para dentro de /usr/local/tomcat

6. Renomeá-lo para mod_jk.so


7. Criar o arquivo mod_jk.conf dentro de /usr/local/tomcat com as linhas :

<IfModule !mod_jk.c>
LoadModule jk_module /usr/local/tomcat/mod_jk.so
</IfModule>
JkWorkersFile "/usr/local/tomcat/workers.properties"
JkLogFile "/usr/local/tomcat/mod_jk.log"

JkMount /examples ajp13


JkMount /examples/* ajp13
JkMount /jsp_dev ajp13

94
JkMount /jsp_dev/* ajp13
8. Criar o arquivo workers.properties em /usr/local com o conteúdo :
worker.list=ajp12, ajp13
worker.ajp12.port=8007
worker.ajp12.host=localhost
worker.ajp12.type=ajp12
worker.ajp12.lbfactor=1

worker.ajp13.port=8009
worker.ajp13.host=localhost
worker.ajp13.type=ajp13
worker.ajp13.lbfactor=1

worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=ajp12, ajp13

worker.inprocess.type=jni

worker.inprocess.class_path=$(workers.tomcat_home)$(ps)classes

worker.inprocess.class_path=$(workers.tomcat_home)$(ps)lib$(ps)jaxp.jar
worker.inprocess.class_path=$(workers.tomcat_home)$(ps)lib$(ps)parser.jar
worker.inprocess.class_path=$(workers.tomcat_home)$(ps)lib$(ps)jasper.jar
worker.inprocess.class_path=$(workers.tomcat_home)$(ps)lib$(ps)servlet.jar
worker.inprocess.class_path=$(workers.tomcat_home)$(ps)lib$(ps)webserver.jar

worker.inprocess.class_path=$(workers.java_home)$(ps)lib$(ps)tools.jar

worker.inprocess.cmd_line=-config
worker.inprocess.cmd_line=$(workers.tomcat_home)$(ps)conf$(ps)jni_server.xml
worker.inprocess.cmd_line=-home
worker.inprocess.cmd_line=$(workers.tomcat_home)
worker.inprocess.jvm_lib=$(workers.java_home)$(ps)jre$(ps)bin$(ps)classic$(ps)jvm.dll

worker.inprocess.stdout=$(workers.tomcat_home)$(ps)inprocess.stdout
worker.inprocess.stderr=$(workers.tomcat_home)$(ps)inprocess.stderr
worker.inprocess.sysprops=tomcat.home=$(workers.tomcat_home)

9 – Editar o arquivo /usr/local/tomcat/conf/server.xml e inserir as linhas logo abaixo de


</Context> :

<Context path="/jsp_dev" docBase="/var/www/default/jsp_dev" debug="0"


reloadable="true" crossContext="true">
<Logger className="org.apache.catalina.logger.FileLogger"
prefix="localhost_jsp_dev_log." suffix=".txt"
timestamp="true"/>
</Context>

10 – Criar a seguinte estrutura de diretórios abaixo do “Document Root” do seu servidor


Apache. Neste exemplo é o /var/www/default :

/var/www/default/jsp_dev
/var/www/default/jsp_dev/WEB-INF
/var/www/default/jsp_dev/WEB-INF/classes
/var/www/default/jsp_dev/WEB-INF/lib

11 – Editar o arquivo /etc/httpd/conf/httpd.conf e incluir como última linha deste


arquivo : include /usr/local/tomcat/mod_jk.conf
95
Pronto ! Seu servidor já está apto a processar páginas JSP ,servlets e classes java. Siga
as instruções abaixo para disponibilizar suas aplicações :

• Todas as suas páginas JSP devem ficar em baixo do diretório jsp_dev


• Todas as suas classes, inclusive servlets, devem ficar em baixo de WEB-
INF/classes
• Para que os servlets funcionem, é necessário editar (criar) o arquivo WEB-
INF/web.xml com as configurações do seu servlet. Exemplo :

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

<!-- Define servlets that are included in the jsp_dev application -->
<servlet>
<servlet-name>
login
</servlet-name>
<servlet-class>
login.login
</servlet-class>

</servlet>

<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/servlet/login.login</url-pattern>
</servlet-mapping>
</web-app>

Para inicializar o tomcat fazer : ../tomcat/bin/startup.sh

Para finalizá-lo fazer : ../tomcat/bin/shutdown.sh

96
Apêndice C

HTTP - Hypertext Transfer Protocol

O HTTP é o protocolo mais usado na Web, mas você precisará conhecê-lo em detalhes
apenas se for desenvolver um browser ou um servidor Web. No entanto, um
conhecimento básico é muito útil se você desenvolve programas CGI ou mesmo se
apenas deseja inserir em suas páginas HTML META Tags do tipo Http Equivalent . Ele
é um protocolo do nível de aplicação para sistemas de informação distribuídos,
colaborativos e hipermédia, que tem sido usado na World Wide Web desde 1990. É um
protocolo do tipo requisição/resposta. O programa Cliente (normalmente um navegador
- Internet Explorer ou Netscape Navigator são os mais difundidos) envia ao programa
Servidor uma requisição com o seguinte formato:

• Request Line contendo:


• Request Method
• URI (Uniform Resource Identifier): identificação do recurso ao qual o
Request Method deve ser aplicado
• Versão do protocolo (atualmente HTTP/1.1)
• Mensagem em formato semelhante ao MIME, contendo:
• Cabeçalho da Mensagem ( Header )
• Corpo da Mensagem

O programa Servidor responde com :

• Status Line contendo:


• Versão do protocolo
• Código de erro ou de sucesso
• Texto descritivo do erro ou sucesso
• Mensagem em formato semelhante ao MIME contendo:
• Cabeçalho da Mensagem ( Header )
• Corpo da Mensagem

Exemplo de uma Request Line :


GET http://www.absites.com.br/index.html HTTP/1.1

Relação de Request Methods :

• OPTIONS
• GET
• HEAD
• POST
• PUT
• DELETE
• TRACE
• CONNECT
• Previsão para extensões dos métodos.

97
O Cabeçalho de uma mensagem HTTP pode conter um ou mais campos no formato
nome_do_campo:valor_do_campo .
Os campos do Cabeçalho de uma mensagem de requisição são classificados nos
seguintes grupos:

• General Header (dizem respeito à mensagem sendo transmitida, e não à


entidade sendo transferida).
• Request Header (fornecem informações adicionais sobre a requisição, e a
respeito do próprio cliente, ao servidor).
• Entity Header (definem metainformações a respeito do corpo da mensagem ou
do recurso identificado pela mensagem).

Os campos do Cabeçalho de uma mensagem de resposta são classificados nos seguintes


grupos:

• General Header (dizem respeito à mensagem sendo transmitida, e não à


entidade sendo transferida).
• Response Header (fornecem informações adicionais a respeito da resposta e do
Servidor).
• Entity Header (definem metainformações a respeito do corpo da mensagem ou
do recurso identificado pela mensagem).

Campos de Cabeçalho HTTP classificados como General Header

• Cache-Control
• Connection
• Date
• Pragma
• Trailer
• Transfer-Encoding
• Upgrade
• Via
• Warning

Campos de Cabeçalho HTTP classificados como Request Header

• Accept
• Accept_Charset
• Accept_Encoding
• Accept_Language
• Authorization
• Expect
• From
• Host
• If-Match
• If-Modified-Since
• If-None-Match
• If-Range
• If-Unmodified-Since
• Max-Forwards

98
• Proxy-Authorization
• Range
• Referer - Endereço (URI) da página onde está o link que levou a essa requisição.
• TE
• User-Agent - Identificação do Navegador (Netscape Navigator, Internet
Explorer, etc.) ou robot que originou a requisição.

Campos de Cabeçalho HTTP classificados como Entity Header

• Allow
• Content-Encoding
• Content-Language
• Content-Length
• Content-Location
• Content-MD5
• Content-Range
• Content-Type - Content-Type: text/html; charset=ISO-8859-4
• Expires - Data/hora após a qual a resposta não deve ser obtida de um cache sem
antes verificar no Servidor de origem se esta continua atual.
• Last-Modified
• Previsão para extensões do cabeçalho.

Campos de Cabeçalho HTTP classificados como Response Header

• Accept-Ranges
• Age
• ETag
• Location - Usado para redirecionar o navegador para uma outra URI.
• Proxy_Authenticate
• Retry-After
• Server
• Vary
• WWW-Authenticate

HTTP : Códigos de erro ou sucesso

O primeiro dígito do código define a classe da resposta. Existem 5 valores possíveis


para o primeiro dígito :

• 1XX: Informativo - Requisição recebida, processamento em andamento.


• 2XX: Sucesso - A ação foi recebida com sucesso, entendida e aceita.
• 3XX: Redirecionamento - O Cliente deve executar outras ações para que a
requisição seja completada (por exemplo, requisitar uma outra URI).
• 4XX: Erro do Cliente - A requisição contém erro de sintaxe ou não pode ser
atendida.
• 5XX: Erro do Servidor - O Servidor não conseguiu atender a uma requisição
aparentemente válida.

99

You might also like