SlideShare uma empresa Scribd logo
7
Mais lidos
8
Mais lidos
9
Mais lidos
"Sôci'êdade de Ensino Sunerior da PamffJa



Elogios antecipados para o Use a Cabeça! Servlets & JSpTM
"Este livro, Use a Cabeça! Servlets & JSP, é tão bom quanto o Use a Cabeça! EJB, que me fez rir E
me garantiu 97% de aproveitamento na prova!"
   - Jef Cumps, Consultor de J2EE, Cronos

"Para nossas aulas de Servlet/JSP, nós compramos mais de dez livros, sem encontrar nenhum, de fato,
satisfatório para nossas necessidades de ensino ... Até que encontrarmos esta 'jóia' pedagógica que
você tem agora nas mãos! Os livros da série Use a Cabeça! nos tornaram melhores professores."
    - Philippe Maquet: Instrutor Sênior da Loop Factory, Bruxelas


Elogios para o Use a Cabeça! EJBTM e para o formato da série Use a Cabeça!
"A tecnologia Java está em todos os lugares - em telefones celulares, carros, câmeras, impressoras,
jogos, PDAs, ATMs, smart cards, bombas de gasolina, estádios, equipamentos médicos, webcams,
 servidores, você escolhe. Se você desenvolve software e não conhece Java, definitivamente, está na
hora de você mergulhar de cabeça - Use a Cabeça!."
     - Scott McNealy, Chairman, Presidente e CEO, Sun Microsystems
                                               (Nota do departamento de marketing: isto foi o melhor que
                                               você conseguiu do Scott? Veja se consegue fazer com que ele
                                               acrescente algo do tipo: "Se nós tivéssemos os livros da série
                                               Use a Cabeça! há dois anos, ainda podíamos ter aquela ilusão ...'~).


 "Um livro incrivelmente agradável. Dividido e interconectado como uma rede de conhecimentos.
Como professor da Purdue University, com especialização em desenvolvimento avançado de software
utilizando tecnologias baseadas em Java, estou em constante busca por materiais de apoio que
ofereçam motivação e uma linguagem compreensiva direcionada para o exame, mas que ao mesmo
tempo não desestimulem os alunos. O livro 'Use a Cabeça! EJB' preenche estes requisitos facilmente!
Livros como estes são extremamente raros.
Incluí este livro como um dos textos essenciais para as futuras turmas do curso de graduação avançada
que eu dou de 'Desenvolvimento de Aplicações para Empresas'. Parabéns para os autores; continuem
com o excelente trabalho!"
   -   Professor Dan Gill, Departamento de Tecnologia de
       Computadores, Purdue University.

"Além do estilo envolvente que o levará do nível de leigo ao status de guerreiro aclamado no Java, o
livro Use a Cabeça! Java traz um grande número de questões práticas, que outros títulos tratam como
o temível 'exercício para o leitor ... ' Ele é inteligente, irônico, descolado e prático - existem poucos
livros com estas características e que são capazes de ensinar sobre serialização de objetos e protocolos
de execução em rede ao mesmo tempo."
    - Dr. Dan Russel, Diretor de Pesquisas Experimentais e
        Científicas com Usuários, IBM Almaden Research Center (e
        professor de Inteligência Artificial na Stanford University).

Que maneira maravilhosa de aprender!!! EU NÃO CONSIGO LARGAR ESTE LIVRO!!! Meu
filho de 3 anos acordou à Ih40 da manhã, e eu o colÇ>queide volta na cama segurando o livro e uma
lanterna, e continuei lendo por mais uma hora.
    - Ross Goldberg

"O Use a Cabeça! Java, escrito por Kathy e Bert, dá às suas páginas impressas uma aparência GUI
como você jamais viu. De um jeito diferente e descolado, os autores transformam a aprendizagem em
Java em uma empolgante experiência, do tipo 'qual será a próxima surpresa?'"
   .- Warren Keuffel, Revista Software Development.
Parabéns pelo formato Use a Cabeça!
    "É rápido, irreverente, divertido e envolvente. Cuidado - você pode realmente aprender alguma coisa!"
       -   Ken Arnold, ex-Engenheiro Sênior da Sun Microsystems
           e co-autor (com James Gosling, criador do Java) do livro
           "The J ava Programming Language"

    "Eu passei no exame SCBCD com 94% de aproveitamento. Realmente, o 'P! EJB' é demais! Eu li o
    livro todo em 10 dias ..."
       -   Basavaraj   Devershetty

(   " ... a única maneira de saber o valor de um tutorial é saber se ele realmente ensinará bem. Use a
    Cabeça! Java é excelente para ensinar. Tudo bem, eu pensei que ele fosse bobinho ... mas, me dei conta
    de que estava aprendendo os tópicos totalmente, à medida que avançava pelo livro."
    "O estilo do Use a Cabeça! Java tomou meu aprendizado, digamos, mais fácil."
          - slashdot (análise do site honestpuck)

    "Eu jamais poderia imaginar que alguém pudesse rir enquanto lesse um livro de TI! Usando o material
    do Use a Cabeça! EJB eu consegui uma ótima pontuação (91 %) e estabeleci um recorde mundial
    como o mais jovem SCBCD, com 14 anos de idade."
       - Afsah Shafquat (o mais novo SCBCD do mundo)

    "Esse livro é tão bacana que me deu vontade de CHORAR! Estou chocado."
       - Floyd Jones, Escritor Técnico Sênior/Garoto da piscina, BEA

    "Se você quer aprender Java, não procure mais: bem-vindo ao primeiro livro técnico com
    características GUI! Com seu formato revolucionário e elaborado com perfeição, o livro oferece
    vantagens que outros títulos sobre Java simplesmente não conseguem ... Prepare-se para um passeio
    realmente extraordinário pelo universo Java."
        - Neil R. Bauman, Diretor Executivo e capitão da Geek
            Cruises (www.GeekCruises.com)

    "Se existe alguém no mundo familiarizado com o conceito do 'Use a Cabeça!', este sou eu. Este livro
    é tão bom que eu me casaria com ele na TV!"
        - Rick Rockwell, comediante.
            O noivo original do programa "Quem Quer Se Casar com
            um Milionário?" ("Who Wants to Marry a Millionaire"),
            da FOX Television

    "O Use a Cabeça! Java é como o Monty Python meets the gang offourl ... o texto está tão bem
    dividido entre quebra-cabeças e histórias, questionários e exemplos, que você obtém uma abrangência
    quehenhum livro de informática conseguiu até agora."
        - Douglas Rowe, Comunidade de Usuários de Java, Columbia.

    "'Use a Cabeça! Java' ... dá um novo significado à frase de marketing da O'Reilly: 'Existe um
    O'Reilly para isso'z. Eu o escolhi, pois muitas outras pessoas que eu admiro o classificaram como
    'revolucionário' e eu descrevi uma técnica totalmente diferente para este livro. Eles estavam (estão)
    certos ... Sem fugir do típico formato da O'Reilly, eles conseguiram um formato científico, mas bem
    aceito. O resultado é divertido, irreverente, atuiü, interativo e brilhante ... A sensação de ler este livro é
    a de estar sentado bem próximo aos alto-falantes em uma sala de reunião, aprendendo - e rindo - com
    os colegas ... Se você quer ENTENDER Java, compre logo o seu."
        - Andrew Pollack, www.thenorth.com
Sociedade de Ensino Superbr da Paat1ira

"Lembra quando você estava no jardim de infância? Não? Bem, e quando você aprendeu pela primeira
vez o alfabeto? É dificillembrar? Bem, não faz mal. Lendo o Use a Cabeça! lava, você vai voltar
a se divertir enquanto aprende ... Para aqueles que se interessam por aprender novas linguagens de
programação e não vieram da área de ciência da computação ou da programação, este livro é uma
preciosidade ... Ele torna divertido o aprendizado de uma linguagem dificil de computação. Espero que
existam mais autores interessados em quebrar o velho e corriqueiro modelo 'tradicional' do estilo de
escrever. Aprender linguagens de computação deveria ser prazeroso e não oneroso."
    - Judith Taylor, Comunidade de Usuários da Maeromedia,
        Southeast Ohio.

"Há poucos dias, recebi minha cópia do Use a Cabeça! lava, de Kathy Sierra e Bert Bates. Eu ainda
estou no começo do livro, mas o que me encantou foi que, mesmo estando com sono naquela primeira
noite, me peguei pensando: 'tudo bem, só mais uma página e vou dormir.'"
    - JoeLitton

"FINALMENTE, um livro de lava escrito tal qual eu escreveria se tivesse sido eu.
Falando sério, este livro simplesmente arrasa qualquer outro livro de software que eujá li... É muito
dificil escrever um bom livro ... É preciso muito tempo para explicar os assuntos, em uma seqüência
natural e cujo foco é o leitor. É muito trabalho. Muitos autores, notoriamente, não estão prontos para o
desafio. Parabéns à equipe do Use a Cabeça! EJB por este trabalho primoroso!

P.S. Quando vai sair o projeto Use a Cabeça! l2EE? E o Use a Cabeça! Desenvolvedor de
Componentes para a Web? E como eu faço para que meu videocassete grave umjogo de futebol
enquanto estou trabalhando?"
    - Wally Flint

"Se você é relativamente um iniciante em programação e está interessado em lava, eis o seu livro ...
Abordando tudo - desde objetos para a criação de interfaces gráficas de usuário (GUl),tratamento de
exceções (erros), redes (sockets) e multitarefas, até como agrupar suas pilhas de classes em um único
arquivo de instalação -, este livro é completíssimo ... Se você gostar do estilo, estou certo de que irá adorar o
livro assim como eu. Espero que a série Use a Cabeça! possa ser estendida a vários outros assuntos!"
    - LinuxQuestions.org

"Quando eu li o 'Use a Cabeça! lava', do mesmo autor, eu pensei que é impossível escrever outro
livro (aquele sobre EJB também) de uma forma tão brilhante. Porém, agora eles nos surpreenderam
com este livro ainda mais legal. Os livros da série Use a Cabeca! tornaram-se algo necessário
(QUASE UMA EXIGÊNCIA) em todos os assuntos. Eu queri~ ser uma criança para poder aprender
tudo da maneira como ensina este livro."
    - Anshu Mishra

Eu trabalhei com EJB há cerca de 4 anos e o achei uma bagunça às avessas. Depois de ler as
especificações 2.1 e 2.0, eu descobri que é apenas uma t*** 3 fumegante que ficou maior. Seu livro
respondeu à maioria das incontáveis perguntas que martelavam meu cérebro de amendoim e permitiu-
me passar na prova com uma pontuação de 92% ...
Vencendo facilmente aquele colega de 14 anos de idade por 1 ponto. :-) Muito obrigado.
    - Jim Steiner
"Eu me VICIEI nos contos do livro, nos códigos com anotações, nas entrevistas preparatórias e nos
exercícios para o cérebro."
   - Miehael Yuan, autor, Enterprise J2ME
se a Cabeca Servlets
          ...:>
                                                  & JSPTM
                                              Segunda Edição



                        Não seria fantástico se existisse
                           um livro sobre Servlets que
                         fosse mais interessante do que
                          apagar spam da sua caixa de
                          mensagens? Talvez isso seja
                                   uma ilusão ...




                                                            Bryan Basham
                                                              Kathy Sierra
                                                                Bert Bates




                  Rio de Janeiro.2008
Use a Cabeça Servlets & JSpTM
© Alta Books Editora - Starlin Alta Con Com Ltda 2008

Do original Head First Servlets and JSPTM.
Authorized translation of the English edition of Head First Servlets and JSPTM 2st Edition © 2008 O'Reil/y
                                                                             ,
Media,lnc. ISBN: 978-0596102340 This translation is published and sold by permission ofO'Reil/y
Media, Inc., the owner of ali rights to publish and sell the some.

Todos os direitos reservados e protegidos pela Lei 5988 de 14/12/73. Nenhuma parte deste livro, sem
autorização prévia por escrito da editora, poderá ser reproduzida ou transmitida sejam quais forem os
meios empregados: eletrônico, mecânico, fotográfico, gravação ou quaisquer outros. Todo o esforço
foi feito para fornecer a mais completa e adequada informação, contudo a editora e o(s) autor(es) não
assumem responsabilidade pelos resultados e usos da informação fornecida. Recomendamos aos
leitores testar a informação, bem como tomar todos os cuidados necessários (como o backup), antes da
efetiva utilização. Este livro não contém CD-ROM, disquete ou qualquer outra midia.

Erratas e atualizações: Sempre nos esforçamos para entregar a você, leitor, um livro livre de erros
técnicos ou de conteúdo; porém, nem sempre isso é conseguido, seja por motivo de alteração de
software, interpretação ou mesmo quando alguns deslizes constam na versão original de alguns livros
que traduzimos. Sendo assim, criamos em nosso site, www.altabooks.com.br. a seção Erratas, onde
relataremos, com a devida correção, qualquer erro encontrado em nossos livros.

Avisos e Renúncia de Direitos: Este livro é vendido como está, sem garantia de qualquer tipo, seja
expressa ou implícita.

Marcas Registradas: Todos os termos mencionados e reconhecidos como Marca Registrada e/ou comercial
são de responsabilidade de seus proprietários. A Editora informa não estar associada a nenhum produto e/
ou fornecedor apresentado no livro. No decorrer da obra, imagens, nomes de produtos e fabricantes podem
ter sido utilizados, e desde já a Editora informa que o uso é apenas ilustrativo e/ou educativo, não visando ao
lucro, favorecimento ou desmerecimento do produto/fabricante.

                                Produção Editorial: Editora Alta Books
                           Coordenação Editorial: Roberto Baptista Barroco
                                  Tradução: Eveline Vieira Machado
                                     Revisão: Fernanda Rigamond
                                    Revisão Técnica: Helder Borges
                                     Diagramação:       Equipe Alta Books

Impresso no Brasil

o código de propriedade intelectual de 10 de Julho de 1992 proibe expressamente o uso coletivo sem
autorização dos detentores do direito autoral da obra, bem como a cópia ilegal do original. Esta prática
generalizada nos estabelecimentos de ensino, provoca uma brutal baixa nas vendas dos livros a ponto
de impossibilitar os autores de criarem novas obras.




                                                Editora Alta Books
                                          Rua Viúva Claudio, 291 - Jacaré
                                        Rio de Janeiro - RJ CEP 20551-010
                                       Tel: 21 3278-8069 Fax: 21 3277-1253
                                               www.altabooks.com.br
                                           altabooks@altabooks.com.br
Esse livro é dedicado a todos aqueles que decidiram que EL implicit object
os autores



Os "procurados" da série Use a Cabeça! (e deste livro)
                                                                                       Bryan Basham
Beart Bates




Bert é um antigo desenvolvedor     Kathy gosta de teoria da            Bryan tem mais de vinte
e arquiteto de software, mas       aprendizagem e assuntos             anos de experiência em
um período de 10 anos em           relacionados à mente desde a        desenvolvimento de software,
inteligência artificial o fez      época em que era designer de        incluindo um período com
se interessar por teoria da        jogos (ela escreveu jogos para      software de automação
aprendizagem e treinamento         a Virgin, MGM e Amblin') e          avançada usando técnicas
via computador. Ele passou a       desenvolvedora em I.A2 Grande       de I.A na NASA Ele
primeira década de sua carreira    parte do formato da série Use       também atuou em uma
como desenvolvedor viajando        a Cabeça! foi desenvolvido          consultoria, desenvolvendo
pelo mundo e ajudando clientes     enquanto lecionava Interatividade   aplicações comerciais em 00
como a rádio Nova Zelândia,        Usando Novas Midias, no             personalizadas. Atualmente,
o The Weather Channel e a          programa de extensão de             Bryan é Desenvolvedor de
rede de entretenimentos Arts       Estudos em Entretenimento           Cursos da Sun, com ênfase
and Entertainment Network          da Universidade da Califómia        nos princípios de design em
(A&E) em suas transmissões.        (DCLA). Recentemente, se            Java e em 00. Ele já trabalhou
Atualmente, ele é membro da        tomou instrutora-chefe da           em diversos cursos de Java
equipe da Sun responsável pelo     Sun Microsystems e ensina os        da Sun, incluindo JDBC,
desenvolvimento de diversos        instrutores de Java a divulgarem    J2EE, Servlets e JSP, além de
exames de certificação em Java,    as mais novas tecnologias           Desenvolvimento de Software
incluindo o recente SCWCD.         desta linguagem. Além disso,        utilizando 00. Ele foi também
Bert é um antigo e incorrigível    desenvolve diversos exames          o primeiro designer dos exames
aficionado pelo GOl e vem          para certificações Sun, incluindo   SCWCD, nas versões original
trabalhando há bastante            o SCWCD. Junto com Bert             e atual.
tempo em um programa. O            Bates, ela tem aplicado             Bryan pratica o Zen Budismo,
Java há de se tomar uma            extensivamente os conceitos da      joga Ultimate Frisbee, adora
linguagem expressiva o             série Use a Cabeça! no ensino       som e pratica o ski telemark.
suficiente para que ele finalize   de milhares de desenvolvedores.
seu projeto. Ele é um bom          Ela fundou uma das maiores
guitarrista e, atualmente, está    comunidades em Java no
experimentando o banjo.            mundo virtual, a javaranch.
Sua mais recente aventura          com, premiada em 2003 e 2004
foi a compra de um cavalo          com o Prêmio Produtividade em
islandês, o que deverá trazer      Desenvolvimento de Software.
novos desafios aos seus            Ela adora correr, esquiar, montar
conhecimentos na área de           a cavalo, andar de skate e
treinamento ...                    ciências esotéricas.

VIII
conteúdo




            (Sumát19)
             Introdução                                                            XIX

             Por que usar Servlets & JSPs: uma introdução                               1
             Arquitetura da aplicação web: visão geral de alto nível                37
             Minitutorial do MVC: praticando com o MVC                              67
             Sendo um servlet: request e resposta                                   93
             Sendo uma aplicação web: atributos e listeners                       147
             Estado de conversação: sincronizando o bean/entidade                 223
             Sendo um JSP: escrevendo códigos em JSP                              281
             Páginas sem scripts: escrevendo JSPs sem scripts                     343
             As tags customizadas são poderosas: usando a JSTL                    439
             Quando nem a JSTL é o bastante: desenvolvendo tags customizadas      499
             Distribuindo sua aplicação web: distribuição da aplicação web        601
             Mantenha em segredo, mantenha seguro: segurança da aplicação web 649
             O poder dos filtros: wrappers efiltros                               701
             Padrões de Design Enterprise: padrões e Struts                       737
             Apêndice A: TestePreparatório Final                                  791
             Índice                                                               865




Introdução
Seu cérebro pensando em Servlets. Aqui está você tentando aprender algo, enquanto
seu cérebro lhe presta o favor de certificar-se de que tal aprendizado não será
interrompido. Ele pensa, "é melhor reservar espaço para coisas mais importantes, como
qual animal selvagem evitar e se esquiar sem roupa é ruim mesmo". Então, como você
vai induzi-lo a pensar que sua vida depende do conhecimento em Servlets?

             A quem se destina este livro?                                          XX

             Nós sabemos o que seu cérebro está pensando                           XXI

             Metacognição                                                         XXlll

             Domine seu cérebrp                                                    xxv
             O que você precisa para este livro                                   XXVI

             Passando no exame de certificação                                  XXVlll

             Os revisores técnicos                                                 XXX

             Agradecimentos                                                       XXXI




                                                                                     IX
1
                                                        Por que usar servlets & JSPs?
                                                       As aplicações web estão na moda. Quantas aplicações GUI você conhece que
                                                       são usadas por milhões de usuários em todo o mundo? Como desenvolvedor de
                                                       aplicações web, você não precisará se prender aos problemas de distribuição
                                                       presentes em toda aplicação standalone e irá distribuir sua aplicação a qualquer
                                                       pessoa que possua um browser. Mas você precisará dos servlets e dos JSPs, pois
                                                       as velhas e estáticas páginas HTML são tão, digamos, "1999". Saiba como mudar
                                                       do sUe na web, para a aplicação na web.


                                       Principais elementos do fluxo                       Objetivos do Exame                                                   2
                                       de solicitação:
                                       • O método HTTP (a ação de
                                           se~ executada)
                                       • A~<rinaqueseráacessada
                                                                                           O que os servidores web e os clientes fazem e como conversam
                                       •
                                           (umaURL)
                                              Osp:mi:mctrosdofurmulãrio(curoo
                                                                                           entre si                                                             4
                                              argtIIIlell!oSparamnrnéloOO)


                                                                                           Guia rápido de HTML                                                  7
                          solicitação HTTP
                                                                                           O que é o protocolo HTTP?                                           10
                                                                                           A anatomia das solicitações HTTP GET ePOST e das respostas HTTP 16
                                                                                           Localizando páginas web usando URLs                                 20
    Cliente
                                                                       Servidor
                                                                                           Servidores web, páginas estáticas e    cm                           24

              Principais elementos do fluxo de resposta:
                                                                                           Desmistificando os Servlets: escreva, distribua e rode um servlet   30
              •   Um código      de .umIS (no caso de uma
                  solicitação    bem sucedida)
                  TIpo de conteúdo         (tc."to, i~oem,    HIML,     ctc_)
                                                                                           JSP foi o que aconteceu quando alguém apresentou o Java ao HTML 34
              •   O conteúdo      (o HTML        real, a imagem,    etc_)




                                                        Arquitetura da aplicação web
                                                        Os servlets precisam de ajuda. Quando uma solicitação chega, alguém tem
                                                        que instar o servlet ou, pelo menos, alocar uma thread para tratar a solicitação.



                  2                                     Alguém tem que chamar ou o método doPostO ou o método doGetO do servlet.
                                                        Alguém precisa levar a solicitação e a resposta para o servlet. Alguém precisa
                                                        gerenciar a vida, a morte e os recursos do servlet. Neste capítulo, vamos estudar o
                                                        Container e dar uma primeira olhada no padrão MVC.

                  Serv!et
                                                                                           Objetivos do Exame                                                  38

                                                                                           O que é um Container e o que ele oferece?                           39
         (Controlador '                                                                   Como fica o código (o que toma um servlet um servlet)               44


JSP
       iJSP                                   1                                            Nomeando os servlets e mapeando-os a URLs usando o DD
                                                                                           História: Bob Constrói um Site de Encontros (introdução ao MVC)
                                                                                                                                                               46
                                                                                                                                                               50
                                JCVQ
                                                                                           Visão geral e exemplo de MVC (Model- View-Controller)               54
                          antigo

        View                                    Modelo
                                                                   1,                      Um Deployment Descriptor (DD) "funcionando"                         64
                                                                                Ba",o de
                                                                                 Dad,,,
                                                                                           Como o J2EE cabe nisso tudo                                         65




x
conteúdo


                                                                            Minitutorial do MVC


                       3                                                    Criando e distribuindo uma aplicação MVC. Chegou a hora de colocar a
                                                                            mão na massa e escrever um formulário HTML, um controlador de servlet, um
                                                                            modelo (classe Java simples), um deployrnent descriptor XML e uma view em
                                                                            JSP. É hora de criar, distribuir e testar. Antes, porém, você deverá configurar
                                                                            seu ambiente de desenvolvimento. Em seguida, você terá que configurar o seu
                                                                            ambiente de distribuição, de acordo com as especificações do servlet e do JSP,
                                                                            e as exigências do Tomcat. Concordo, esta é uma aplicação pequena ... Porém,
                                                                            quase NÃO existe aplicação que seja tão pequena e use o MVC.
Especffico      para   o Tomcat

 Este   nome    de diretÓf'io



 root" que o Torncat o •context
 também representa usa quando
 estó resolvendo URLs. Nós
                                                          r::::a
                                                          ~
                                                                   !         Esta parte da estrutura
                                                                             de diretórios é exigido
                                                                                                             Objetivos do Exame                                                   68
 exploraremos detalhes conceno
 em maiores     este     no
 copít1Jloobre Distribuição.
         s
                                                          l;;;J '-; seu diretónoeablllxo estar
                                                          ;~
                                                             I {'
                                                                    pelo Tomcat
                                                                    diretamente
                                                                        j          d~ve do
                                                                                  home.
                                                                                                             Vamos construir uma aplicação MVC: primeiro o design                 69
                                               -~8)~_OOOmedaapricação.                                       Criando os ambientes de desenvolvimento      e distribuição          72
                                                                                                             Criando e testando o HTML para o formulário inicial
dos Servlets                                   j- '-'                       l§l         ,!J.
                                                                                                             Criando o Deployment Descriptor (DD)                                 77
parteda •• pecifj~ção~l
                     ! _
                     1""""                           ~"
                                                     ~                       Este arquivo web.xmJ
                                                                       h~TEMQ~Eestarem
                                       l __
                                          _                     _ z;;        WEB-INF
                                                                                                             Criando, compilando, distribuindo e testando o servlet de controle   81
Específico
Aplicação       da                8,- -: ~
                                      •.                       A estrutura       deste    pacote   é
                                                                                                             Design, criação e teste do componente modelo                         82
                                   - - .' .'                   A   menos que você esteja
                                                                                                             Otimizando o controlador para chamar o modelo
                          ~i _~ ~~(~:~~a~:e~t~i:O
                       ~; __". :~:~~~~u:n=;~o
                       1 _~
                       .. ,'- ,
                                   _
                                  --               _--         maIs    tarde).   você    DEVE colocar    o

                                             Criando                                                                  e distribuindo o componente view; (isto é um JSP)           87
                       g 8    i                    [pacote                  de estrutura de diretórios
                                                               irnediatamente       abaixo de WEB-
                         ~>                _si"",              INF/classes.
                                                                                                             Otimizando o servlet de controle para chamar o JSP                   88


                                                                            Sendo um servlet


                                  4                                         Servlets vivem para servir clientes. A função de um servlet é receber uma
                                                                            solicitação do cliente e devolver uma resposta. A solicitação talvez seja simples:
                                                                            "traga-me a página de Boas-vindas". Ou pode ser complexa: "Finalize o
                                                                            processo do meu carrinho de compras."A solicitação carrega dados cruciais e
                                                                            o código do seu servlet tem que saber como encontrá-Ios e utilizá-Ios. E ele tem
                                                                            que saber como enviar uma resposta. Ou não ...

                                                                                                             Objetivos do Exame                                                   94
                                                                                                             Os Servlets são controlados pelo Container                           95
                                                                                                             Cada solicitação roda em uma thread separada!                        101
                                                                                                             A verdadeira função do servlet no tratamento das solicitações        105
                                                                                                             A história da solicitação não-idempotente                            112
                                                                                                             O que determina se você recebeu uma solicitação GET ou POST?         117
                                                                                                             Enviando e usando parâmetro( s)                                      119
                                                                            o servlet     usa os dados
             NÃO Idempotente                                                do POST para atualizar
                                                                                                             Então, essa foi a Solicitação ... vejamos agora a Resposta           126
~
~
 <_ ....     ~:"::            LJ
                              M
                                                           wz
                                                           ....         -----8
                                                                             ..
                                                                            ObanCOde ..... QdOS.
                                                                                        d
                                                                                        .•..                 Você pode configurar headers de resposta, você pode adicionar
~~
Cliente
                              ~
                                               /servlet
                               ':::~ irO servJet WW'. de volta uma resposta
                                                 envia
                                       com uma página gerada em HTML
                                                                                         D                   headers de resposta                                           133
                                                                                                             Redirecionamento de servlets faz o browser trabalhar          136
                                                                                                             Revisão: HttpServletResponse                                         140


                                                                                                                                                                                   XI
Sendo uma aplicação web


                            5                                Nenhum servlet vive sozinho. Nas aplicações web atuais, vários componentes
                                                             trabalham em conjunto por um objetivo. Temos os modelos, os controladores
                                                             e as views. Temos os parâmetros e os atributos. Temos as classes helper. Mas,
                                                             como juntar os pedaços? Como permitir que os componentes compartilhem
                                                             informações? Como você oculta informações? Como você torna uma informação
                                                             thread-safe? Seu trabalho pode depender destas respostas.


                                                                          Objetivos do Exame                                                     148
                                                                          Os Parâmetros Init dão uma força                                      150
                                                                          Como um JSP consegue obter os parâmetros init do servlet?              155
                                                                          Os parâmetros init do contexto dão uma força                           157
                                                                          Comparando o ServletConfig com o ServletContext                        159
                                                                          Ela quer um ServletContextListener                                     166
9rset                                                                     Tutorial: escreva um ServletContextListener       simples              168
                   ,,,
                                                                          Compile, distribua e teste o seu listener                              176
~set
       Acessível    apennspamoquelescomoc:essoQ_HttpSessionespecifico
                                                                          A história completa, uma análise do ServletContextListener             178
                             Atributos de SOUctTAÇÃO
                                                                          Listeners: eles não servem apenas para os eventos de contextos         180
                                                                          O que é exatamente um atributo?                                        185
                                                                          AAPI Atributo                                                          189
                                                                          O escopo de contexto não é thread-safe!                                192
                                                                          Como tomamos os atributos do contexto thread-safe?                     194
                                                                          Testando a Sincronização                                               195
                                                                          Os atributos de Sessão são thread-safe?                                198
                                                                          Os males do SingleThreadModel                                         201
                                                                          Apenas os atnbutos da Solicitaçãoe as variáveis locais são thread-safe! 204
                                                                          Atributos da Solicitação e request dispatching                         205




XII
conteúdo (sumário)


                                               Estado de conversação


                  6                            Os servidores web não têm memória curta. Assim que eles lhe enviam uma
                                               resposta, eles esquecem quem você é. Na próxima vez que você fizer uma
                                               solicitação, eles não o reconhecerão. Eles não se recordam do que você solicitou
                                               no passado e nem do que eles enviaram como resposta. Nada. Porém, algumas
                                               vezes você precisa manter o estado de conversação com o cliente durante várias
                                               solicitações. Um carrinho de compras não funcionaria se o usuário tivesse que
                                               escolher seus produtos e finalizar a compra de uma única vez.


                                                                         Objetivos do Exame                                             224
                                                                         Esperamos que seja uma conversa (como as sessões
                                                                         funcionam)                                                     226
                                                                         IDs de sessão, cookies e outros fundamentos das sessões        231
                06of.if-f,-",",,-!--r.~""~'-
                                                                         Reescrita de URL: uma alternativa                              237
                         "'~=
                ~"ú'ú ..•.•.
                                                                         Quando as sessões envelhecem; dando adeus às sessões ruins     241
                                                                         Posso usar cookies para outras coisas além das sessões?        250
                                                                         Os principais momentos de um HttpSession                       254
                                                                         Não se esqueça do HttpSessionBindingListener                   256
                                                                         A migração da sessão                                           257
                                                                         Exemplos de listener                                           261


                                               Sendo um JSP
                                               Um JSP torna-se um servlet. Um servlet que você não cria. O Container olha
                                               o seu JSP, o traduz em código-fonte Java e o compila em uma classe servlet de
                                               Java completa. Porém, você tem que saber o que acontece quando o código que
                                               você escreveu em JSP se transforma em código Java. Você pode escrever códigos
                                               Java em JSP, mas será que você deveria? E se não for um código Java, o que
                                               você pode escrever? Como ele jaz a tradução para o código Java? Veremos seis
                                               diferentes tipos de elementos JSP ~ cada um com seu próprio propósito e, sim,
                                               sintaxe única. Você aprenderá como, por que e o que escrever no seu JSP. E você
                                               aprenderá o que não escrever.


                                                                         Objetivos do Exame                                             282

                                                                         Criando um JSP simples usando o "out" e uma
                                                                         diretiva de página                                             283
                                                                         Expressões, variáveis e declarações em JSP                     288

                                                                         Hora de ver. um servlet gerado a partir do JSP                 296
~' .,
 ,.     ._.~.
                                                                         A variável out não é o único objeto implícito                  298

                                                    ">.,.
                                                     MyISP-.J<pSc1vlet
                                                                         O Ciclo de vida e a inicialização de um JSP                    306
                                                                         Já que estamos falandosobre   isso ... as três diretivas       314
                                                                         Scriptlets considerados perigosos? Eis a EL                    317
                                                                         Mas, espere ... ainda não vimos as ações                       323

                                                                                                                                         XIII
Páginas sem scripts


      8   Fuja do scripting. Será que seus webdesigners precisam mesmo saber Java?
          Será que eles pensam que quem programa Java para servidores tomar-se-á,
          digamos, designer gráfico? E mesmo que a equipe seja só você, você quer
          mesmo um monte de bits e pedaços de códigos Java nos seus JSPs? Você sabe
          o que significa "um pesadelo na hora da manutenção"? Escrever páginas sem
          scripts não só é possível, como também é mais fácil e mais flexível com a nova
          especificação JSP 2.0, graças à nova Expression Language (EL). Padronizada
          depois do JavaScript e do XPATH, os webdesigners sentir-se-ão em casa com a
          EL. E você também vai gostar (assim que você se acostumar). Porém, existem
          algumas armadilhas ... a EL se parece com o Java, mas não é. Às vezes, a EL se
          comporta de forma diferente de como comportar-se-ia a mesma sintaxe no Java.
          Portanto, fique atento!


                                                            Objetivos do Exame                                               344
                                                            Quando os atributos são beans                                    345
                                                            Ações-padrão: useBean, getProperty, setProperty                  349
                                                            Você sabe fazer referências polimórficas para beans?             354
                                                              atributo param dá uma ajuda                                    360
                                                            Convertendo propriedades                                         363
                                                            A Expression Language (EL) salva o dia!                          368
                                                            Usando o operador ponto (.) para acessar propriedades
                                                            e mapear valores                                                 370
                                                            O [c:catch] dá a você mais opções (Lists, arrays ...)            372
           .""'<0"""   .•.••••.•••   '''<1''''<:;


           '9"",'~.,,<!~~",-,.~.".                  _~d~.   Mais detalhes dos operadores ponto e [ ]                         376
                                                            Os objetos implícitos da EL                                      385
                                                            Funções EL e tratando o "null"                                   392
                                                            Os pedaços reutilizáveis do template - dois tipos de "include"   402
                                                            A ação-padrão <jsp:forward>                                      416
                                                            Ela não conhece as tags JSTL (uma visão rápida)                  417
                                                            Revisando as ações-padrão e o include                            417




XIV
conteúdo



                                          As tags customizadas são poderosas


               9
                                          Em alguns casos, você precisa de mais do que a EL ou ações-padrão. E se
                                          você quisesse fazer um loop através dos dados de um array, exibindo em seguida
                                          um item por linha em uma tabela HTML? Você sabe que poderia escrever isso em
                                          dois segundos, usando um loop for em um scriptlet. Mas você está tentando evitar
                                          os scripts. Sem problema. Quando a EL e as ações-padrão não forem suficientes,
                                          você pode usar tags customizadas. Elas são tão fáceis de usar em um JSP quanto
                                          as ações-padrão. Melhor ainda, alguém já escreveu boa parte das tags de que você
                                          mais provavelmente precisará, e as juntou na JSTL (JSP Standard Tag Library,
                                          ou Biblioteca de Tags JSP Padrão). Neste capítulo, aprenderemos a usar tags
                                          customizadas, e no capítulo seguinte, aprenderemos a criar as nossas próprias tags.


                                                                                  Objetivos do Exame                                          440
                                                                                  Fazendo loops sem scripts; <c:forEach>                      446
                                                                                  Controle condicional com o <c:i:f> e o <c:choose>           451
                                                                                  Usando as tags <c:set> e <c:remove>                         455
                                                                                  Com a <c:import>, há três maneiras de incluir conteúdo      460
                                                                                  Customizando o que você inclui                              462
                                                                                  Fazendo o mesmo com <c:param>                               463
                                                                                  A <c:url> para todas as suas necessidades de hyperlink      465
                                                                                  Crie suas próprias páginas de erro                          468
                                                                                  A tag <c:catch>. Semelhante a try/catch ... mais ou menos   472
                                                                                  E se você precisar de uma tag que NÃO esteja na JSTL?       475
                                                                                  Preste atenção ao <rtexprvalue>                             480
                                                                                  O que pode existir no corpo de uma tag                      482
                                                                                  O tag handler, o TLD e o JSP                                483
                                                                                  A taglib <uri> é apenas um nome, não um local               484
                                                                                  Quando um JSP usa mais de uma biblioteca de tags            487

                                                             () .H-ritr.rl'c.te   #fler+4.f';tJ
                                                             ,lll.prN.ltLlsi
                                                                          JÇ'
                    <c;forEach
                                                  ,"------
                                    var="1i.stElement"       items="${movi.es}"          >



                                        va.r=-mov.ie" items="${1i;,...tE:J.ezent}"
                                       <td>${llICIVie}</td>            '--                   >
                         </c:f:~~                           lIJoo.{(as fi.:N.js. 5i!"'!~5 5tte
                                                            .j"nll1 (I:!-""jV;,,!DS 'u fI,+"tJ,,,,+a
                    </c:forEach>
                                                             V;jr- J<!l   /"* exhl'~c.




                                                    MatrL,,{Ievoiutions


!«:so,!h"''''f,,''~iro s,'''''J,n---'7'j            KillBilI
                                                    BoondockSaints
                                                    Àmelie
                                                    ReturnoflheKing
                                                    MeanGirls




                                                                                                                                               xv
Quando nem a JSTL é o bastante ...


        10
                         Em alguns casos, a JSTL e as ações-padrão não são suficientes. Quando você
                         precisa de algo customizado, e não quer voltar aos velhos scripts, você pode escrever os
                         seus próprios tag handlers. Dessa maneira, os seus desenvolvedores de páginas poderão
                         usar a sua tag nas suas páginas, enquanto todo o trabalho duro é feito nos bastidores, na
                         sua classe tag handler. Mas há três maneiras diferentes de se criar os seus próprios tag
                         handlers, então, há muito o que aprender. Dessas três, duas foram introduzidas com o
                         JSP 2.0 para tomar a sua vida mais fácil (Simple Tags e Tag Files).

                                                 Objetivos do Exame                                           500
                                                 Tag Files: iguais ao include, só que melhores                502
                                                 Onde o Container procura por Tag Files                       509
                                                 Tag handlers simples                                         513
                                                 Uma tag Simples com um corpo                                 514
                                                 E se o corpo da tag usar uma expressão?                      519
                                                 Você ainda precisa saber sobre os tag
                                                 handlers Clássicos                                           529
                                                 Um tag handler Clássico bem pequeno                          531
                                                 O ciclo de vida Clássico depende dos
                                                 valores retomados                                            536
                                                 A interationTag lhe permite repetir o corpo                  537
                                                 Valores-padrão retomados pela TagSupport                     539
                                                 A interface DynamicAttribute                                 556
                                                  Com BodyTag, você tem dois novos métodos                    563
                                                  E se você tiver tags que funcionam conjuntamente?           567
                                                 Usando a API PageContext para tag handlers                   577


                         Distribuindo sua aplicação web
                         Finalmente, sua aplicação está pronta para o horário nobre. As suas páginas



            11
                         estão finalizadas, seu código está testado e ajustado, e o prazo de entrega era há
                         duas semanas atrás. Mas, para onde vai isso tudo? Tantos diretórios, tantas regras.
                         Que nome você dá aos seus diretórios? Qual nome o cliente pensa que eles têm? O
                         que é que o cliente realmente solicita, e como o Container sabe onde procurar?


                                         Objetivos do Exame                                                   602
Referênciaaumbeanlocal
                                         Principal tarefa da distribuição: onde entra o quê?                  603
                                                                                                              612
                                   ~" Arquivos WAR
                                                                                                              616
                            ~         Como o mapeamento de servlets REALMENTE funciona
                          =~?::::::~;~:::.
                                      Configurando arquivos de boas-vindas no DD                              622
                                         Configurando páginas de erro no DD                                   626
                               ~    ~    Configurando a inicialização de servlets no DD                       628
                          __       -êCriando      um JSP compatível com XML: um Documento JSP                 629

XVI
conteúdo



                                                    Mantenha em segredo, mantenha seguro


     12
                                                    Sua aplicação web está emperigo. O perigo espreita em cada canto da rede. Você não
                                                    quer os Caras Maus xeretando nas transações da sua loja virtual, roubando números
                                                    de cartões de crédito. Também não quer os Caras Maus convencendo o seu servidor
                                                    de que eles na verdade são os Clientes Especiais Que Recebem Grandes Descontos.
                                                    E você não quer ninguém (amigo OU inimigo) olhando dados confidenciais dos
                                                    empregados. Será que o Jim, do departamento de marketing, precisa mesmo saber
                                                    que a Lisa, do departamento de engenharia, ganha três vezes mais do que ele?
  As Dez Melhores Razões para realizar a Sua
  segurança declaratwamente

    'Iil    lJmpaucomais deprátirocomXML            11ÕrJfazmal   a 11inguém.
                                                                                          Objetivos do Exame                                                650
    O :~:U~::te,         as.~eclarações
                                      casamnaturalmente                                   O Top 4 em segurança de servlets                                  653
           deparrame;oSd~~ ':mp~O) já existentesno
                                                                                          Como Autenticar no Mundo HTTP                                     656
   e       Fica multo bem no seu curriculo.

                                                                                          As Dez Melhores Razõespara realizara sua segurançadeclarativamente 659
  o ~~:: ~;~~asmais
      ::j~~:ma                                           flexíveis,
  G Está no exame.                                                                        Quem implementa a segurança em uma aplicação web?                 660
  e       Permite aos dcsenvoh-edores de aplicações IeUtJlizarem
          senlets, mesmo sem acesso ao código-fonte.
                                                                                          Autorização: funções e restrições                                 662
 O É legal, simplesmente.                                                                 Autenticação: quatro sabores                                      677
                                                                                          OS QUATRO tipos de autenticação                                   677
                                                                                          Protegendo a segurança dos dados em trânsito: HTTPS em ação       682
                                                                                          Como implementar confidencialidade     e integridade de dados caso
                                                                                          a caso e declarativamente                                       684


                                                    o poder dos filtros
                                                    Os filtros lhe permitem interceptar a solicitação. E se puder interceptar a
                                                    solicitação, você poderá também controlar a resposta. E, melhor de tudo, o servlet
                                                    nem percebe o que aconteceu. Ele nunca ficará sabendo que alguém intercedeu


     13                                             entre a solicitação do cliente e a invocação do método serviceO do servlet pelo
                                                    Container. O que isso significa para você? Mais férias. Porque o tempo que você
                                                    levaria reescrevendo apenas um dos seus servlets pode ser despendido, em vez
                                                    disso, escrevendo e configurando um filtro com a capacidade de afetar todos os seus
                                                    setvlets. Adicionar tracking das solicitações do usuário a todos os servlets da sua
                                                    aplicação? Sem problema. Manipular o output de cada servlet da sua aplicação? Sem
                                                    problema. E você não precisa nem sequer tocar no código do servlet.




  •.•...
--_
  •
a pilha
               ·181'" ••
                  a pilha
                    9                   e
                                    a pilha
                                                          e
                                                       a pilha              a pilha
                                                                                o
                                                                                          Objetivos do Exame
                                                                                          Construindo um filtro para o monitoramento das solicitações
                                                                                          O ciclo de vida de um filtro
                                                                                          Declarando e ordenando filtros
                                                                                          Comprimindo o output com um filtro no lado da resposta
                                                                                                                                                            702
                                                                                                                                                            707
                                                                                                                                                            708
                                                                                                                                                            710
                                                                                                                                                            713
                              o Conta;tle<"
                             ""'P<Jn"otrlétodo                         ~;::o::-,. Os wrappers são demais                                                    719
                             ~i<eOdo
                             S••••leM I""" o

                              ~~::~~~é                                 êiªª::: O código do verdadeiro filtro de compressão                                  722
                              fircl,m-.e ""tilo,;                      Conta;ner-nMlÜQa
                              ",t;rndodo.pilll<l.

                                                                       respost"-          Código do wrapper de compressão                                   724




                                                                                                                                                           XVII
Padrões de Design Enterprise


    14
            Alguém já fez isso antes. Se estiver começando agora a desenvolver aplicações
            web em Java, você tem sorte. Poderá se beneficiar do saber coletivo das dezenas
            de milhares de desenvolvedores que já trilharam esse caminho e sobreviveram
            para contar. Usando tanto os padrões de design específicos do J2EE quanto
            outros padrões, é possível simplificar o seu código e a sua vida. E o padrão de
            design mais significativo para aplicações web, o MVC, possui até mesmo um
            framework absurdamente popular, o Struts, que ajudará você a criar um servlet
            Front Controller flexível e de fácil manutenção. Você deve a si mesmo tirar
            vantagem do trabalho dos outros para que possa despender mais tempo nas
            coisas mais importantes da vida ...


                          Objetivos do Exame                                               738
                          O poder do hardware e do software por trás dos padrões           739
                          Revisão dos princípios do design de software...                  744
                          Padrões para dar suporte a componentes de modelos remotos        745
                          Visão geral da JNDI e da RMI                                     747
                          O Business Delegate é um "intermediário"                         753
                          Simplifique os seus Business Delegates com o Service Locator 759
                          Hora de usar um Transfer Object?                                 761
                          Nosso primeiro padrão revisitado ... MVC                         762
                          Sim! É o Struts (e o Front Controller), em poucas palavras       767
                          Refatorando a aplicação Beer para o Struts                       770
                          Revisão sobre padrões                                            778




                  fausa pata
                  º caté
            o Teste Preparatório   final. É isso, 69 perguntas. A aparência, os assuntos
            abordados e o nível de dificuldade são praticamente idênticos aos da prova
            oficial. Nós sabemos.


                          Teste preparatório final                                         791
                          Respostas                                                        828

        o
        1   índice                                                                         865




XVIII
1   Introdução



        Como usar este livro?
Use a Cabeça JSP




A quem se destina este livro?
          Se você responder "sim" a todas estas perguntas:


          (1) Você   sabe Java? (não precisa ser um guru)


          ® Você gosta de consertar - você aprende     fazendo, ao invés de apenas ler? Você deseja
               aprender, compreender,    lembrar   dos servlets e dos JSPs e passar no exame SCWD
               for Java EE 1.5?


          ® Você prefere     uma conversa descontraída       em uma festa a palestras   acadêmicas   sem
               graça e tediosas este livro é para você.


          este livro não é para você.




Quem provavelmente deveria manter-se longe deste livro?
          Se você responder "sim" a alguma destas perguntas:



          (!) Você é totalmente  inexperiente em Java? Você não precisa estar em um nível
               avançado, mas, definitivamente, deve ter alguma experiência. Se não tiver, pegue um
               exemplar do Use a Cabeça! Java agora mesmo. Hoje! E só então retome a este livro.



          ® Você é um desenvolvedor     Java "forçado" em busca de um livro de consulta?


          ® Você é um veterano     em J2EE em busca de técnicas ultra-avançadas e "como-fazer"
               específicos para servidores, projetos para empresas e códigos complexos, robustos e
               reais?



          @ Você tem medo      de experimentar coisas diferentes? Você prefere fazer um canal no
               seu dente a misturar listras num tecido xadrez? Você acha que um livro técnico perde a
               credibilidade se os componentes Java tiverem aparência humana?


          este livro não é para você.




xx
introdução




Nós sabemos o que você está pensando.
"Como este livro de programação pode ser sério?"
"Com tantas ilustrações?"
"Eu consigo realmente aprender desta forma?"



E nós sabemos o que seu cérebro está pensando.
Seu cérebro clama por novidades. Está sempre procurando, examinando e
esperando por algo diferente. Ele foi criado assim e o ajuda a se manter vivo.
Atualmente, é pouco provável que você vire o lanchinho de um tigre,
mas seu cérebro continuará em alerta. Nunca se sabe.
Então, como seu cérebro faz para lidar com todas as coisas rotineiras,
comuns e normais com as quais você se depara? Tudo o que ele puder
fazer para impedir que tais coisas interfiram no seu real trabalho:
registrar o que interessa. Não faz mal guardar as coisas fúteis; elas nunca
passarão pelo filtro que retém o que "obviamente não importa".
Como seu cérebro reconhece o que é importante? Suponha que você tire
um dia para fazer uma caminhada e um tigre pule na sua frente. O que
acontece com a sua cabeça e o seu corpo?
Os neurônios disparam. As emoções são ativadas. As reações
químicas explodem.
E é assim que seu cérebro reconhece ...


Isto pode ser importante! Não esqueça!
Mas, imagine que você está em casa, ou em uma
biblioteca. É um local seguro, acolhedor e sem
tigres. Você está estudando. Preparando-se para
um exame. Ou tentando aprender um assunto
técnico e difícil, que seu chefe acredita que
levará uma semana, dez dias no máximo.
Só um problema. Seu cérebro está tentando
lhe fazer um grande favor. Ele está tentando
assegurar-se de que aquele conteúdo, obviamente
irre1evante, não vá confundir os poucos recursos.
Recursos estes que seriam melhores se usados para
armazenarem coisas realmente importantes. Como
tigres. Como o perigo do fogo. Ou como você
nunca mais deveria praticar snowboard de short.
E não existe um jeito simples de dizer ao seu
cérebro, "Ei cérebro, muito obrigado, mas nào
importa se o livro é tedioso, ou o quanto estou
registrando agora na escala Richter emocional,
eu realmente quero que você guarde estas
coisas por aqui."



                                                                                 você está       ~   XXI
Use a Cabeça JSP




   Então, o que é necessário para se aprender algo? Primeiro, você precisa absorver e depois
   se certificar de que não irá esquecer. Não tem nada a ver com enfiar coisas na sua cabeça.
   Baseando-se nas últimas pesquisas em ciência cognitiva, neurobiologia e psicologia
   educacional, o ato de aprender envolve muito mais que textos em uma página. E nós sabemos o
   que faz o seu cérebro funcionar.


   Alguns princípios de aprendizagem da série Use a Cabeça:
                                                      Dê ênfase à parte visual. As imagens são muito mais fáceis
                                                      de serem memorizadas do que palavras soltas e tomam o
                                                      aprendizado muito mais produtivo (aumenta em até 89% a
                                                      memória e o aprendizado usando a técnica da transferência). E
                                                      facilita a compreensão. Ponha as palavras dentro ou próximas
                                                      às respectivas figuras, em vez de no rodapé ou em outra página
                                                      e os leitores serão até duas vezes mais capazes de solucionar os
                                                      problemas relacionados com aquele conteúdo.
                                                                                              precisa   chamar um
                                                                                              método no servidor
    Use um estilo próprio e em forma de conversa. Em estudos
    recentes, o desempenho dos alunos nas provas realizadas após
    aprenderem a matéria, melhorava em 40% se o conteúdo falasse
    diretamente ao leitor usando a primeira pessoa, com um estilo
                                                                                              ~
                                                                                               (                     serviço
                                                                                                                    remoto   RMI




    que simulasse uma conversa em lugar do tom formal. Conte
    histórias em vez de dar palestras. Use a linguagem coloquial. Evite
    ser muito sério. Em que você prestaria mais atenção: em uma
    companhia interessante na festa ou em uma palestra?

                                               Faça o aluno refletir. Em outras palavras, nada acontece na sua cabeça
                                               a menos que você exercite muito os seus neurônios. O leitor precisa estar
                                               motivado, atraído, curioso e inspirado para resolver problemas, tecer
                                               conclusões e gerar um novo conhecimento. E para isso você precisa de
                                               desafios, exercícios e perguntas que estimulem o raciocínio, além de
                                               atividades que envolvam ambos os lados do cérebro e os múltiplos sentidos.

                                             Prenda - e segure - a atenção do leitor. Todos nós já pensamos "eu
                                             realmente gostaria de aprender isto, mas eu não consigo me manter
  abstrac                                    acordado depois da primeira página". Seu cérebro presta atenção a coisas
                                   roam () ; que são extraordinárias, interessantes, estranhas, atraentes e inesperadas.

                                      f,
                                           /    Aprender um assunto novo, difícil e técnico não precisa ser chato. Seu
                                                cérebro aprenderá muito mais rápido se o assunto for interessante.
            c.óM !)WI   pM'l.fb-rV!i!'5Udi,


       Mexa com a emoção do leitor. Agora nós sabemos que sua capacidade de
       recordar algo depende enormemente do seu conteúdo emocional. Aquilo que
       você se preocupa, você se recorda. Você se recorda quando sente algo. Não,
       nós não estamos falando de histórias de sofrimento entre um menino e seu
       cão. Estamos falando de emoções como a surpresa, a curiosidade, a diversão,
       o "caramba!. .." e aquela sensação de "Eu sou o cara!" que vem quando você
       consegue matar uma charada, aprender algo que todos acham difícil ou
       perceber que sabe uma coisa que o "bam-bam-bam" da engenharia não sabe.



XXII
introdução




Metacognição:        pensando sobre pensar
Se você realmente quer aprender - e aprender mais
rápida e definitivamente -, preste atenção em como
você presta atenção. Pense em como você pensa.
Aprenda como você aprende.
A maioria de nós não fez cursos de metacognição ou
teoria do aprendizado enquanto crescia. Esperam que
aprendamos, mas raramente nos ensinam a aprender.
Supomos que se você está segurando este livro, você
quer aprender servlets e, provavelmente, não quer
perder muito tempo. Considerando que você fará
a prova, você terá que lembrar do que leu. Logo,
precisa entender o que foi lido. Para obter o máximo
deste livro - ou de qualquer outro livro ou forma de
aprendizado -, dê responsabilidades ao seu cérebro.
Faça-o ficar atento a este conteúdo.
O truque é fazer com que seu cérebro encare como
Realmente Importante o novo material que você
está aprendendo. Crucial para o seu bem-estar.
Tão importante quanto um tigre. Caso contrário,
você estará constantemente em conflito, com o seu
cérebro dando o melhor de si para não assimilar o
assunto novo.



Então, como você FAZ para que seu cérebro
considere os servlefs          um tigre faminto?


Existem as formas lenta e tediosa e a mais rápida e efetiva. A forma lenta é a pura repetição. É claro
que você sabe que será capaz de aprender e relembrar até mesmo o assunto mais estúpido se o ficar
repetindo. Com uma repetição intensa seu cérebro diz, "isto não parece importante para ele, mas ele
fica olhando para a mesma coisa repetidamente, então eu imagino que deva ser".

A maneira mais rápida é fazer qualquer coisa que aumente sua atividade cerebral, principalmente
atividades de tipos diferentes. O que foi dito na página anterior é uma grande parte da solução e
foi comprovado como forma de ajudar seu cérebro a trabalhar em seu favor. Por exemplo, estudos
demonstram que colocando as palavras dentro das figuras que elas representam (em vez de soltas na
página, como uma explicação ou dentro do texto) faz com que seu cérebro entenda como as figuras e
as palavras se relacionam, ativando mais neurônios. Mais neurônios ativados significa mais chances
do cérebro entender que determinado assunto merece atenção e, possivelmente, deve ser registrado.

O estilo interativo também ajuda, pois as pessoas tendem a prestar mais atenção quando percebem que
estão em uma conversa, já que se espera que ela;s acompanhem até o final. O interessante é que seu
cérebro não se importa necessariamente que a "conversa" seja entre você e um livro! Por outro lado,
se o estilo de escrever for seco e formal, seu cérebro entenderá isso do mesmo modo que você o faria
se estivesse em uma palestra numa sala repleta de participantes indiferentes.

Porém, as figuras e o estilo que simula uma conversa são só o começo.



                                                                                 você está       ~ XXIII
Use   a   Cabeça JSP




Eis       O   que NÓS fizemos:
                                                                                  Ro<:hd'~ttltf


Nós usamos figuras, pois seu cérebro está adaptado ao que é visual,
não texto. Para ele, uma imagem vale 1.024 palavras. E quando figuras
e textos trabalham juntos, nós inserimos o texto na imagem, pois seu
cérebro funciona melhor quando o texto está dentro daquilo a que se refere,   I
diferente de estar numa observação ou escondido em algum lugar no texto.
Nós usamos a repetição. Dizemos a mesma coisa de formas distintas e
através de meios diferentes - e múltiplos sentidos -, para aumentar as
chances de o assunto ser registrado em mais de uma área cerebral.                 W<wd<;::ligners~
                                                                                  Quthere ..•


Nós usamos os conceitos e as figuras de maneira inesperada, pois seu
cérebro é ativado quando encontra uma novidade. E usamos figuras e
idéias com pelo menos algum conteúdo emocional, pois seu cérebro está
predisposto a dar mais atenção à bioquímica das emoções. Aquilo que
te faz sentir algo tende a ser mais facilmente lembrado, ainda que esta
sensação não passe de um pouco de humor, surpresa ou interesse.
Nós usamos um estilo próprio que simula uma conversa, porque seu
cérebro tende a prestar maior atenção quando acredita que você está
participando d~ uma conversa e não assistindo passivamente a uma
apresentação. E assim que funciona mesmo quando você está lendo.
Nós incluímos mais de 40 atividades, pois seu cérebro está habituado a
aprender e a relembrar mais quando você faz alguma coisa do que quando
você lê a respeito. E colocamos exercícios dificeis, porém possíveis de
serem feitos, pois é como a maioria das pessoas prefere.
Nós usamos métodos diferentes de aprendizado, pois você poderia
preferir os procedimentos passo a passo, enquanto outra pessoa
poderia preferir entender primeiro as figuras grandes, enquanto outras,
simplesmente ver os exemplos de códigos. Mas, independentemente da
sua própria preferência de aprendizado, todos se beneficiam vendo o
mesmo conteúdo representado sob múltiplas formas.
Nós colocamos assuntos para serem usados por ambos os lados do seu
cérebro, pois quanto mais você usar do seu cérebro, mais chances terá de
aprender e lembrar, além de mais tempo de concentração. Já que colocando
para funcionar um lado do cérebro significa geralmente a oportunidade do
outro lado descansar, você poderá produzir mais por mais tempo.
E nós incluímos estudos de caso e exercícios que apresentam mais
de um ponto de vista, pois seu cérebro está adaptado a aprender mais
intensamente, quando forçado a fazer avaliações e julgamentos.
Nós inserimos desafios com exercícios eperguntas que nem sempre têm
respostas diretas, pois seu cérebro está mais propenso a aprender e lembrar
quando tem que se esforçar por algo. Pense nisso - você não consegue manter
seu corpo em forma apenas observando as pessoas na academia. Porem, nós
fizemos o melhor possível para garantir que, quando você estiver trabalhando
duro, será pelas coisas certas. E que você não estará desperdiçando nenhum
dendrito a mais, tentando entender um exemplo complicado ou analisando
um texto dificil, repleto de jargões, ou então, extremamente resumido.
Nós usamos pessoas nas histórias, nos exemplos, nas figuras, etc. Afinal,
você é uma pessoa e seu cérebro dá maior atenção a pessoas do que a coisas.
Nós usamos a técnica do 80/20. Entendemos que se você pretende ser um
PhD em JSP, este não deve ser seu único livro. Logo, não falamos sobre
tudo. Apenas da matéria que você realmente precisará.



XXIV
introdução




                                    Eis O que VOCÊ pode fazer para
                                    dominar seu cérebro
                                   Então, fizemos a nossa parte. O resto é com você. As dicas a seguir são o
                                   ponto de partida. Preste atenção no seu cérebro e descubra o que serve e o
              Jef!cá/'h          , que não serve para você. Experimente novidades.
             d          ! " f: C<J!Y4{1P -           ;
              ~" ,J1?1tJ;«elf'tI.   ().  "i!I   Pó/'r",


(1) Vá   devagar. Quanto mais você entender,
    menos terá que memorizar.
                                                           ® Fale. Em voz alta.
                                                                Falando, você ativa uma parte diferente do
    Não leia apenas. Pare e pense. Quando o                     cérebro. Se você estiver tentando entender
    livro perguntar algo, não pule para a resposta.             algo ou aumentar sua chance de recordar
    Imagine que alguém esteja realmente lhe                     mais tarde, leia em voz alta. Melhor ainda,
    fazendo a pergunta. Quanto mais você forçar o               tente explicar isto para outra pessoa em voz
    seu cérebro a pensar, melhores serão as chaTIces            alta. Você aprenderá mais rápido e talvez
    de aprender e recordar.                                     observe idéias que você não havia percebido
                                                                que estavam ali enquanto lia.
® Faça os exerCÍcios. Faça
   anotações.
                                        suas próprias
                                                           Q) Ouça    seu cérebro.
    Nós os colocamos no livro, mas se nós                       Observe se o seu cérebro não está ficando
    resolvermos, vai parecer que alguém está                    sobrecarregado. Se você se pegar passando
    fazendo a ginástica para você. E não basta                  a mão na superficie do livro ou esquecendo
    olhar os exercícios. Use um lápis. Está                     o que acabara de ler, é hora de uma
    provado que a atividade fisica, enquanto se                 pausa. Uma vez que você ultrapasse um
    estuda, pode melhorar o aprendizado.                        determinado ponto, você não aprenderá mais
                                                                rápido se tentar "enfiar" mais informação
@) Leia   a seção "Perguntar não ofende".                       na cabeça e poderá até comprometer o
    Ou seja, todas elas. Elas não são barras                    processo.
    laterais opcionais. Elas s ão parte do
    conteúdo principal! Não as pule.                       ® Sinta    algo!
                                                                Seu cérebro precisa saber que isto é
@ Antes     de ir dormir, faça desta a sua última               importante. Envolva-se com as histórias.
                                                                Crie suas próprias legendas para as fotos.
    leitura. Ou pelo menos a última que lhe
    exija racioCÍnio.                                           Dar um sorriso amarelo quando uma piada
                                                                não tem graça ainda é melhor do que não
    Parte do aprendizado (especialmente a
                                                                esboçar reação.
    transferência para a memória de longa
    duração) acontece depois que você fecha o
    livro. Seu cérebro necessita do seu próprio
    tempo para maior processamento. Se você
                                                           ® de acabar o livro.
                                                             Faça o Teste Preparatório     Final só DEPOIS

    puser uma informação nova durante este                      Se você fizer o teste muito cedo, você não
    tempo de processamento, o que você acabou                   terá uma idéia clara da sua preparação para
    de aprender será perdido.                                   o exame. Espere até sentir que você está
                                                                quase pronto e então faça o teste em, no
@ Beba    água. Muita água.                                     máximo, 135 minutos - o tempo verdadeiro
    Seu cérebro funcionará melhor se receber
                                                                doSCWCD.
    um belo banho. A desidratação (que pode .
    acontecer bem antes de você sentir sede)
    reduz a função cognitiva. A cerveja, ou algo
    mais forte, será bem-vinda quando você
    passar no exame.



                                                                                      você está       •• XXV
Use a Cabeça JSP




o que você         precisa para este livro:
Além do seu cérebro e um lápis, você precisa do Java, do Tomcat 5 e de
um computador.
Você não precisa de nenhuma outra ferramenta de desenvolvimento como o
Integrated Development Environment (IDE). Definitivamente, recomendamos
que você não use nada além de um editor simples até terminar o livro. Um
IDE que reconhece servlet e JSP poderá privá-l o de algum detalhe realmente
importante (e que cairá na prova). Por isso, é melhor você evitar desenvolver
todo o bean manualmente. Uma vez que você realmente entenda o que está
acontecendo, poderá utilizar uma ferramenta que automatize alguns dos
passos para a criação e distribuição do servlet/JSP. Se você já sabe como usar
o Ant, poderá usá-lo após o capítulo 3 para ajudar na distribuição. Porém, não
recomendamos usar o Ant até que você tenha memorizado completamente a
estrutura de distribuição da aplicação web.

               OBTENDO      O TOMCAT --------,

       Caso ainda não possua o Java SE v1.5 ou superior, você vai
       precisar (de preferência 1.4).
       Se você não tem ainda o Tomcat 5, obtenha-o em:
        http://tomcat.apache.org/
       Selecione "Tomcat v5.5" no menu Downloads no lado esquerdo
       da home page.
    • Pagine até a seção "Binary Distributions" (Distribuições Binárias)
       e faça o download da versão escolhida. Se não souber, então,
       selecione a distribuição "Core" (Básico); é tudo que você precisa.

       Salve o arquivo de instalação em uma pasta temporária.
       Instale o Tomcat.
       Para Windows, dê um duplo-clique no arquivo install.exe e siga
       as instruções do assistente de instalação.
       Para os outros sistemas, descompacte o arquivo de instalação
       no diretório onde você quer que o Tomcat resida.
       Para facilitar as instruções do livro, renomeie para "tomcat" o
       diretório home do Tomcat (ou configure um cognome "tomcat"
       que aponte para o home verdadeiro do Tomcat).

       Configure as variáveis de ambiente para JAVA_HOME e                      Java 2 Standard Edition 1.5
       TOMCAT HOME, da mesma forma como você normalmente                        Tomcat 5
       faz em sua máquina.                                                      O exame abrange as
       Você deve ter uma cópia das especificações, embora não                   seguintes especificações:
       precise delas para passar no exame. Até o lançamento deste
       livro, as especificações eram:
                                                                                • Servlets 2.4
       Servlet 2.4 (JSR #154) http://jcp.org/eng/jsr/detail?id=154
       JSP 2.0 (JSR #152)          http://jcp.org/eng/jsr/detail?id=152         ·JSP 2.0
       JSTL 1.1 (JSR #52)          http://jcp.org/eng/jsr/detail?id=52
       Vá até a página JSR e clique em Download Page para o                     • JSTL 1.1
       lançamento mais recente.

       Teste o Tomcat rodando o script tomcat/bin/startup (startup.
       sh para os sistemas Linux/Unix/OSX). Digite na barra de
       endereços do seu browser:
       http://localhost:8080/   e você verá a página inicial do Tomcat.

XXVI

                                                                 .~       ...
introdução



Coisas de última hora que você precisa saber:
Isto é uma experiência de aprendizado e não um livro de
referência. Nós retiramos deliberadamente tudo que pudesse
atrapalhar o caminho do aprendizado, independentemente do
que estejamos trabalhando no livro. E, desde o primeiro instante,
comece do começo, pois o livro faz considerações quanto àquilo
que já foi visto e aprendido.
                                                                       fJS{Ufl6S VI?,   fJMI-.
Nós usamos diagramas simples e parecidos com UML.                                      f!
                                                                       m~Ji/tllt:M.,lt~ h!4,(~
Embora exista uma grande chance de você já saber UML, isto não
é cobrado no exame e não é um pré-requisito para o livro. Então,
você não terá que se preocupar em aprender servlets, JSP, JSTL e
                                                                                          Diretor
UML ao mesmo tempo.
                                                                              getMovies

Nós não cobrimos todos os detalhes minuciosos da especificação.               getOscars          ()

O exame é muito detalhado, mas, nós também somos. Porém, se                   getKevin

existe um detalhe na especificação que não é cobrado no exame, só             BaconDegrees()
o citaremos se for importante para a maioria dos desenvolvedores de
componentes. O que você precisa saber para começar a desenvolver
componentes web (servlets e JSPs), e o que precisa para passar no
exame, cobre cerca de 85%. Nós incluímos algumas coisas que não
caem na prova, mas sinalizamos para que você não se preocupe em
memorizá-Ias. Nós criamos o verdadeiro exame, portanto, sabemos
onde você deverá concentrar sua energia! Se houver a possibilidade
de um mínimo detalhe figurar em uma questão da prova, mas se o
esforço para aprendê-Io realmente não valha a pena, provavelmente
ou o omitiremos, ou o abordaremos sucintamente, ou o colocaremos
em uma questão do teste preparatório.

As atividades NÃO são opcionais.
Os exercícios e as atividades não são meros adicionais; eles são
parte do conteúdo principal do livro. Alguns estão lá para ajudar na
memorização, outros para ajudar na compreensão, enquanto outros
o ajudarão a aplicar o que você aprendeu. Não pule nada.

A redundância é intencional e importante.
Uma coisa que é claramente diferente em um livro da série Use a
Cabeça! é que nós queremos muito, muito, muíto que você entenda.
E gostaríamos que você terminasse o livro lembrando o que
aprendeu. A maioria das informações e dos livros de referências não
tem, necessariamente, a retenção e a lembrança como objetivos, mas
aqui você verá alguns conceitos aparecerem mais de uma vez.

Os códigos-exemplos são os mais resumidos possíveis.
Nossos leitores têm relatado o quanto é frustrante ler
minuciosamente 200 linhas de códigos procurando por aquelas
duas linhas que eles precisam. A maioria dos exemplos deste livro
é exibida dentro dos menores contextos possíveis, para que a parte
que você precisa fique clara e simples. Não espere que o código
seja robusto ou completo. Esta é sua tarefa para quando terminar o
livro. Os exemplos aqui são escritos especialmente para aprender e
nem sempre são totalmente funcionais. Alguns exemplos de código
para o livro estão disponíveis em www.altabooks.com.br


                                                                                 você está aqui ~ XXVII
fazendo a prova




Sobre o exame SCWCD               (para Java EE      1.5)

o   exame SCWCD atualizado é chamado de "Sun Certified Web Component Developer
for Java Platform, Enterprise Edition 5" (CX-310-083), mas não fique confuso com o
título. O exame atualizado ainda é designado para o Java EE vIA, para o servlet v2A e
as especificações JSP v2.0.

Primeiro tenho que passar no SCJP?
Sim. O exame Web Component Developer, exame Business Component Developer,
exame Mobile Application Developer, exame Web Services Developer e exame
Developer requerem que você seja um Sun Certified Java Programmer.

Quantas questões?
Você terá 69 questões quando fizer o exame. Ninguém têem as mesmas 69 questões; existem
muitas versões diferentes do exame. Mas todas têm o mesmo grau de dificuldade e o mesmo
equilíbrio de tópicos. No exame real, espere ver pelo menos uma questão do objetivo de
cada exame e existem alguns objetivos nos quais você terá mais de uma questão.

Quanto tempo tenho para completar o exame?
Você tem três horas (180 minutos). A maioria das pessoas não acha que isso é um problema,
pois essas questões não são longas, complicadas, complexas. A maioria das questões é
muito curta, tem múltipla escolha e você sabe a resposta ou não.

Como são as questões7
Elas são quase exatamente como as nossas perguntas simuladas do exame, com uma
grande diferença - o exame real informa-o quantas respostas estão corretas, nós não.
Contudo, você verá algumas perguntas do tipo arrastar e soltar que não podemos fazer
aqui. Mas as questões com arrastar e soltar são apenas o modo interativo de coincidir
uma coisa com outra.

Quantas tenho que responder corretamente?
Você deve ter 49 questões corretas (70%) para passar no exame. Quando terminar
de responder a todas as questões, mantenha o cursor do mouse sobre o botão Done
(Terminado) até que tenha coragem de clicá-Io. Em cerca de seis nanossegundos, você
saberá se passou (claro, você passará).

Por que os exames simulados no livro não informam quantas opções escolher para a
resposta correta?
Queremos que nossos exames sejam apenas um pouco mais difíceis que o exame real,
para lhe dar uma idéia mais verdadeira para saber se você está pronto para fazer o
exame. As pessoas tendem a ter notas mais altas nos exames simulados do livro porque
refazem o mesmo teste mais de uma vez e não queremos que você tenha uma falsa
sensação de sua aptidão para o exame. Os leitores têm informado que a pontuação
consegui da no exame real é muito próxima da pontuação que eles têm no exame
simulado final neste livro.


XXVIII   introdução
o que acontece   depois de fazer o exame?
Antes de deixar o centro de teste, obtenha o relatório de seu exame. Ele mostra um
resumo de sua pontuação em cada área maior e se passou ou falhou. Guarde-o! É sua
prova inicial de que você foi certificado. Em poucas semanas depois do teste, você
receberá um pequeno pacote da Sun Educational Services que inclui seu certificado
impresso real, uma carta de felicitação da Sun e um adorável alfinete de lapela
informando Sun Certified Web Component Developer em uma fonte tão pequena que
você poderia declarar ser certificado em qualquer coisa que quisesse e ninguém poderia
ler para saber a diferença. Não inclui a bebida alcoólica que você estará querendo depois
de passar no exame.

Quanto custa e como me registro?
O exame custa US$200. E é por isso que você precisa deste livro ... para assegurar
que passará na primeira vez. Você registra-se através do Sun Educational Services,
fornecendo o número de seu cartão de crédito. Em troca, receberá um número de
voucher, que usará para agendar um encontro em um Prometric Testing Center mais
próximo de você.
Para obter detalhes on-line e comprar um voucher do exame, comece em:bttp://www.sun.
com/training/certificationi. Se estiver nos Estados Unidos, estará marcado. Se não, poderá
selecionar um país na barra de menus   à direita.
Como é o software do exame?

É bem simples de usar - você tem uma questão e responde-a. Se não quiser responder,
poderá pulá-Ia e voltar para ela mais tarde. Se a responder, mas não estiver certo e
quiser voltar para ela se tiver mais tempo, poderá "marcar" uma questão. Assim que
tiver terminado, verá uma tela que mostra todas as questões que você não respondeu ou
marcou, para que possa voltar para elas.
Bem no início do exame, você obterá um pequeno tutorial sobre como usar o software,
onde conseguir um pequeno teste prático (não sobre Servlets). O tempo gasto no tutorial
não conta como o tempo gasto no exame SCWCD. O relógio não iniciará até que você
tenha terminado o tutorial do software de exame e estiver pronto para começar.

Onde posso encontrarum grupo de estudo e quanto tempo levará para me preparar?
O melhor grupo de análise on-line para este exame é aquele que os autores
presidem! (Deus, quais são as probabilidades?) Pare em j avaranch. com e vá para Big
Moose Saloon (é onde estão todos os fóruns de discussão). Você não pode perder.
Sempre haverá alguém para responder suas perguntas, inclusive nós. JavaRanch é
a comunidade Java mais amistosa na Internet, portanto, você será bem-vindo não
importando o nível em que estiver no Java. Se você ainda precisar ter o SCJP, iremos
ajudá-Io com ele também.
Quanto tempo leva para ficar pronto para o exame depende muito de quantos servlets
e experiência JSP você tem. Se você for novo. nos servlets e no JSP, poderá precisar de
6 a 12 semanas, dependendo de quanto tempo pode dedicar a cada dia. Aqueles com
muitos servlets recentes e experiência JPS geralmente poderão estar prontos em até
três semanas.




                                                                                 você está   ~ XXIX
a equipe de revisores



Beta testers & Revisores Técnicos




                                                                        lA"fi.iS   d"'$      u
                                                                                          f •.• de
                                                                        ~a,beld$!JT'rt.b'Jc'(';s   f>4!JJ'"


                                                                        Céwsa      desh      Itvrcó,




IV';" 1"+(;5f'~f~d",
("'4S +õ'ó
''''Pórhwl-e     &1/4",1-"
"$ "'1I+r"s)                                                -I


/1-",1'+   L"",dhe                  de: J""'5   ---.----/
                                                                 A"drew    1Lf.""k/,{Jtlse




                                                   fl.ee,l-ish
                                                                     (~
                                                                  lA.adafta



XXX         introdução
introdução

                                   J.tU' ct'~J.t.f<}

Outras pessoas a quem ~:

Na O'Reilly:
Nossos maiores agradecimentos a Mike Loukides na O'Reilly,
por iniciar tudo e ajudar a dar forma ao conceito Use a Cabeça em
uma série. Adoramos ter um editor que é um Verdadeiro Java. E um
grande agradecimento à força motriz por trás do Use a Cabeça, Tim
O'Reilly. Felizmente para nós, ele sempre está pensando no futuro
e gosta de ser uma influência destruidora. Obrigado a Kyle Hard "a
mamãe da série" Use a Cabeça inteligente por descobrir como o Use
a Cabeça encaixa-se no resto dos livros de computador.

Nossos revisores intrépidos:
Tudo bem, então, o livro levou um pouco mais de tempo do que
tínhamos planejado. Mas sem o gerente de revisão JavaRanch
Johannes deJong, ele teria ficado assustadoramente atrasado. Você
é nosso herói, Johannes. E nossos agradecimentos especiais a Joe
Konior cujo feedback em cada capítulo foi quase do mesmo tamanho
do capítulo. Estamos profundamente agradecidos pelo esforço
inexorável e experiência (e alegria) de Philippe Macquet. Todos
os três autores adoram-no tanto que queremos casar com ele ... mas
isso seria estranho. E estamos muito gratos a Andrew Monkhouse
pelo feedback técnico e ajuda nas traduções sutis do inglês para a
língua australiana. Jef Cumps, sua interpretação MP3 da canção
"setHeader" foi impressionante (exceto talvez por ser um pouco emo)
e seus comentários técnicos foram realmente úteis.

Dave Wood trabalhou com afinco em tudo e foi carinhoso ao apontar
para as primeiras páginas e dizer: "Isso não é o estilo Use a Cabeça".
Também tivemos um feedback excelente dos moderadores JavaRanch
Jason Menard, Dirk "cara de peixe" Shreckmann, Rob Ross,
Ernest Freidman-Hill e Thomas Paul. E como sempre, agradeço
especialmente ao chefe javaranch.com,    Paul Wheaton.
Agradecimentos especiais aos seguintes revisores técnicos pela
segunda edição: Bear Bibeault, Theodore Casser, UlfDittmer,
Preetish Madalia, Sergio Ramirez, Oliver RoeU, Neeraj Singhal e
Collins Tchoumba.

Perguntas do examine simulado
Se você se encontrar balançando a cabeça em uma questão simulada
JSP particularmente capciosa, não nos culpe - culpe Marc Peabody!
Obrigado Marc por ajudar a manter todos os candidatos SCWCD
em alerta. Marc passa uma quantidade enorme de seu tempo livre
moderando no JavaRanch, onde é conhecido por estimular os
usuários Ranch a construir misturas horríveis de suas tecnologias Java
EE inocentes.




                                                                         você está       ~ XXXI
mais reconhecimentos




Tem mais gente ainda*

Por Bryan Basham

Eu poderia começar agradecendo à minha mãe, mas isso já foi feito antes ... Meu conhecimento em
desenvolvimento web com Java tem como base algumas aplicações de média escala que escrevi, mas
esta base foi melhorada e refinada por anos de debate em Java como instrutor da Sun, usando um e-mail
com um nome fictício. Em particular, gostaria de agradecer a Steve Stelting, Victor Peters, Lisa Morris,
Jean Tordella, Michael Judd, Evan Troyka e Keith Ratliff. Muitas pessoas ajudaram a lapidar meu
conhecimento, mas estes seis foram as facas que melhor me esculpiram.

Como em todos os projetos de livro, os últimos três meses foram muito dificeis. Gostaria de agradecer à minha
noiva, Kathy Collina, por ter sido paciente comigo. Eu quero agradecer a Karma e Kiwi (nossos gatos) pelas
sessões de lambidas tarde da noite e as pancadas no teclado.

Por último, e mais importante, tenho que agradecer à Kathy e ao Bert por sugerirem que levássemos
adiante o projeto. Kathy Sierra é mesmo única no mundo. Seu conhecimento em metacognição e design
educacional só se comparam à sua essência criativa que transborda nos livros desta série. Eu tenho
trabalhado com educação há cinco anos e praticamente tudo o que aprendi foi com a Kathy ... Oh, não
se preocupe com minha mãe; ela receberá uma grande dedicatória em meu próximo Use a Cabeça!. Eu
te amo, mãe!


Por Kathy e Bert

Isso foi tão sentimental, Bryan, ohhhh ... (Não que a Kathy não goste de rasgar uma seda). Mas, concordamos
quando fala sobre sua noiva. Mas não por ela ter sentindo saudades suas, enquanto jogava Ultimate o verão todo
e nós trabalhávamos feito cachorro em nossos Powerbooks 1. Mas você realmente fez disso uma experiência
recompensadora, Bryan, e hoje é o melhor(NA) co-autor que já tivemos! Chega quase a assustar o quanto
você é calmo e feliz o tempo todo.

Todos nós adoramos a equipe que trabalha duro nos exames de certificação da Sun, em especial a Gerente
de Certificação em Java, Evelyn Cartagena. Queremos agradecer também a todos os colegas que ajudaram a
desenvolver as especificações dos JSRs para Servlet e JSP.




    o
* grande número de agradecimentos é porque estamos testando uma teoria
de que todos os mencionados na seção de agradecimentos do livro comprarão
pelo menos uma cópia, talvez mais, contando os parentes e tudo. Se você
quiser estar na seção de agradecimentos  do nosso próximo livro, e se tiver
uma família grande, escreva-nos.

1Ponto de esclarecimento: O Bryan foi o único co-autor que nós tivemos,
mas isto não diminui em nada a nossa intenção.


XXXII
Por que usar Servlets & JSPs?




As aplicações web estão na moda. Claro, as aplicações GUI podem
usar aquelas coisas exóticas do Swing, mas quantas aplicações GUI você
conhece que são usadas por milhões de usuários em todo o mundo? Como
desenvolvedor   de aplicações web, você não precisará se prender aos
problemas de distribuição presentes em toda aplicação standalone e irá
distribuir sua aplicação a qualquer pessoa que possua um browser. Porém,
para construir uma aplicação web poderosa mesmo, você precisa do Java.
Dos servlets. Dos JSPs. Pois as velhas e estáticas páginas HTML são tão,
digamos, "1999". Hoje, os usuários esperam por sites dinâmicos, interativos
e customizáveis. Aqui, você aprenderá como mudar do site na web, para a
aplicação na web.



                                                            este   é um   novo ca~)ítuio
objetivos do exame oficial da Sun




Visão geral dos Servlets & JSP                   Notas sobre a Abrangência:
1.1 Para cada um dos Métodos HTTP (como          Os objetivos deste capítulo são abordados
    GET, POST, HEAD e assim por diante):         completamente em outro capítulo, então,
                                                 considere este capítulo como uma base,
       Descrever os beneficios do Método
                                                 em primeira mão, para o que virá adiante.
       HTTP
                                                 Em outras palavras, não se preocupe
       Descrever as funcionalidades do Método    em terminar este capítulo sabendo (e
       HTTP                                      lembrando) de itens especificos destes
       Listar os triggers que podem levar um     objetivos; apenas use isto como uma base.
       Cliente (geralmente um browser) a usar    Se você já domina estes assuntos, poderá
       o método                                  simplesmente dar uma olhada rápida e
                                                 passar para o capítulo 2.
Também jaz parte do Objetivo 1.1, mas não será
                                                 Você não encontrará nenhuma pergunta no
abordado neste capítulo:
                                                 teste prático sobre estes assuntos até que
        Identificar o método HttpServlet que     você chegue ao capítulo mais especifico,
        corresponda ao Método HTTP               onde eles serão abordados.




    2 capitulo 1
introdução        e arquitetura


rodos queretM UtM website
Você tem uma idéia fantástica para um website. Para aniquilar
com os concorrentes, você precisa de uma arquitetura flexível e
escalonável. Você precisa de servlets e JSPs.
Antes de começarmos a construção, vamos dar uma olhada na rede
mundial de computadores, a uma distância de aproximadamente
40k pés. O que mais nos importa neste capítulo é como os clientes
e servidores web se comunicam entre si.

Provavelmente, as muitas das páginas a seguir serão uma revisão
para você, principalmente se você já é um desenvolvedor.
Contudo, teremos a chance de definir algumas das terminologias
que usaremos no decorrer do livro.




                                                   A- we!I c4"Sls-!--f:          f!1t   ;l!t.;;es     de clte".f-es
                                                   (,/sa"dlJ      brlJWSfJ'SCtl""lJ             lJ   llA.o;llla   {}V 6

                                                   Sa.lard       fi!   serllt;/{}rff!S     (;'6;/0.";/6 apUctlj;;es
                                                   C61ttl6 A-ptlct.e);          ClJ"ec.f-a;/lJS tl+NJ.V;S ;/e
                                                   redes       ClJltIltl e wtreless.                1JI)SS6 "''de+tv6
                                                   ; ClJ"s.f-I'Vll' Vlttl tlpllca{ã6 ave lJS clle,,-I-es
                                                   44 red41' ;/6 ItV,,;/lJ p6S S8..." tlces sal'. í "ôS
                                                   +6N78.1''''''S es.f-vpt;/lJ..."e,,-I-e rlcf/'JS.




                     Cliente
                                         a terra




                                                                                           você está aquí          I;     3
servidor Web




o que      o seu servidor web faz?
Um servidor web recebe uma solicitação e devolve algo para o cliente.

Um browser permite ao usuário solicitar um recurso. O servidor
pega a solicitação, encontra o recurso e retoma com algo para o
usuário. Algumas vezes este recurso é uma página HTML. Outras,
umafigura. Ou um arquivo de som. Ou até mesmo um documento
PDF. Não importa - o cliente solicita uma coisa (recurso) e o
servidor a envia de volta.

A menos que o recurso não esteja lá. Ou pelo menos, não está onde
o servidor esperava encontrá-Io. Certamente, você já está bem
familiarizado com o erro "404 Not Found" - a resposta que você recebe
quando o servidor não pode encontrar o que ele acha que você solicitou.
Quando dizemos "servidor", estamos querendo dizer ou a máquina
física (hardware), ou a aplicação do servidor web (software). Ao
longo do livro, se a diferença entre o hardware e o software do
servidor importar, nós diremos explicitamente a qual dos dois
(hardware ou software) nos referimos.




/} sali'cl.fa{i6    JÍ6 clle~         C611#1VI ()
l1ólVle e el1Jel"eS6 (li. (J}t.f-); JIJ.3l1t1fJ
alie fJ cltewh!    es.f:   fl"6ClIl"lJ.l1Ja.
                                  ~
                                      C3"
                                      ~                                                          bel"fi./lVlel1h;  6 sel'vti/tJl"
                              ~                                                                  hlVl IVIlIt-.f6 C6#1htdtJ
                                                                                                 fbJe   seI' 1Vlfi.I1JÍIí.Jb
                                                                                                                           ffi.NJ.   tJ

                                                                                                      /
                                                                                                 lISVfJ.l't'"b.tsh         1__.1
                                                                                                                     (;tJ#1-rrtllJfJ

                                                                                                 f6Je ser f~''''fJ.S; JPíbs
                             ~
                                                                                                  e <':Jv.fl"<':Js
                                                                                                                 l'eCVI'SfJs.



                                                        ~
                                                                
                                            /} l"espas.ffJ.   Ja    sel"lI,i/t'J1" C6#1#1VI a

                                            J.oclIlVlel1.fa vel"JaJell'tJ     !ve   tJ   dtewh
                                            stJlicr.f6l1 (6V VIVI C:iiil51) de el"l"õ se I)
                                         feJti/6     1146fvJel'sel"         fl"l)cessad6).




    4                1
introdução   e arquitetura


o que UtM cliettte web          faz?
Um cliente web permite ao usuário fazer solicitações ao
servidor, exibindo para ele o resultado do pedido.


Quando falamos em clientes, no entanto, geralmente queremos
dizer ao mesmo tempo o usuário e o browser (ou um dos dois) .
O browser é o software (como o Netscape ou o Mozilla) que sabe
se comunicar com o servidor. A outra grande tarefa do browser é
interpretar o código HTML e exibir a página ao usuário.
Então, a partir de agora, quando usarmos o termo cliente,
geralmente não nos preocuparemos se estamos falando do usuário
ou do browser. Em outras palavras, o cliente é o browser jazendo
aquilo que o usuário solicitou.




        o usuário   clica em um
                                               o browser     formato   a
                                                                                    o servidor   encontra
        link no browser.                                                            a página solicitada.
                                               solicitação   e a envia para
       ~
                                               o servidor.
                                                                       G1J
     •. 'P:    ~
                                                 ------=7
 I
   I .
   I
 ;"1'"
 Usuário                       Browser                                       Servidor




                    o browser consegue o
                    HTML e o traduz em              o servidor   formato     a

                    formato    visual para o        resposta e a envia para o
                    usuário.                        cliente (browser).




                                                -~I~I                        Servidor




                                                                                  você está aqui ~            5
HTMLeHTTP



Os clietttes e os servidores conhecelt HfML e HffF


 HTML
  Quando um servidor responde a
  uma solicitação, ele geralmente
  envia algum tipo de conteúdo
  para o browser, para que este
  possa exibi-Io. Os servidores
  geralmente enviam instruções
  para o browser escritas em
  HTML (HyperText Markup
  Language). O HTML diz ao
  browser como apresentar o
  conteúdo ao usuário.

   Todos os browsers sabem o que
   fazer com o HTML, embora
   algumas vezes um browser
   mais antigo possa não entender
   partes de uma página que tenha
   sido escrita usando as versões
                                             o B1ML        Int9tma a9
   mais recentes do HTML.                    bt9"'vTset 9m9 e)Úblt 9
                                                       C
                                                    ;d       ;c
                                              c9nteU 9 a9 Usuatl9.
  HTTP
   A maioria das conversas que
   ocorre na web entre clientes e
   servidores é mantida através do
                                           o BTTP     é 9 pt9t9c919 'Lue 95
   protocolo HTTP, que possibilita         clIentes e 9S set""Id9tes usam
   conversas de request e resposta
   simples. O cliente envia uma            patq se C9munkatem.
   solicitação HTTP e o servidor
   retoma uma resposta HTTP.
   Conclusão: se você é um
   servidor web, você fala HTTR
                                             o set""ld9t USq9 BTTP pata
   Quando um servidor envia uma
   página HTML ao cliente, o faz
                                             en""'i!U' B1ML íW clIente.
                                                     9
   usando o HTTP. (Você verá
   os detalhes de como tudo isto
   funciona nas próximas páginas.)
   (Para Sua Informação:
   HTTP significa Protocolo de
   Transferência de Hipertexto.)




    6 capitulo 1
introdução e arquitetura



G-uia rápido de    HfML
Quando você desenvolve uma página, você usa o HTML para
descrever que aparência a página deve ter e como deve se comportar.
o HTML tem dúzias de tags e centenas de atributos de tag. O
objetivo do HTML é, a partir de um documento texto, adicionar
tags que dirão ao browser como formatá-Io. Abaixo estão as tags
que usaremos nos diversos capítulos a seguir. Se você precisar de
um conhecimento completo em HTML, recomendamos o livro
HTML & XHTML The Definitive Guide.



Tag                  Descrição

<!-      ~>          onde você põe seus comentários

<a>                  âncora - geralmente para colocar um hyperlink




                                                                      )
<align>              alinha os comentários à esquerda, à direita,

                      centralizado ou justificado

<body>                define os limites do corpo do documento

<br>                                                                      (1'éc/IliCQ.llle/ll+ej         Q.S
                     pular linha
                                                                          <.ce/ll+el'")        e <.aIi5/1l") Cf).II'f).1IIt
<center>              centraliza o conteúdo
                                               '"                          elll   fÀesustJ       ctJll'I a
<form>                define um formulário    (que geralmente   oferece    'i.0)          lIItas eS+Q.lllttJs
                                                                            uSQ./IlfÀtJ-as elllt
                     um campo para a entrada de dados)
                                                                            /IltJS StJS eXt!.l!'fi(JS;
<hl>                  o cabeçalho de primeiro nível                          sel'elllt     1t'141"$    sil!'fles    fÀt.
                                                                                              •                     StJ4S
<head>                define os limites do header do documento               st.l'elt'l     llilfJ.S

                                                                              l'espec+tv4S
<html>                define os limites do documento HTML                           /
                                                                              a.fé p61'ZUe
<input     type>      define um tipo de entrada em um formulário               es-ra asvl•
                                                                                   Il
<p>                   um novo parágrafo
                                                                                  IfrM~,)
<title>               o título do documento HTML




                                                                                          você está                           7
escrevendo HTML



o que você      escreve ...
(o HfMU
Imagine que você está criando uma página de login. O HTML
simples poderia se parecer com isto:


      <html>

      <!- Um HTML        exemplo       - >   4::--   {J1f   Ce.lf!ifl1+:1'/4 /frML
      <head>

        <title>A        Login       Page</title>                                     tt +~<.I~> es+:             fJ.11/"I1t.adfJ.
                                                                                                                              del1+l't:.

      </head>                                                                        de viria   +~<.a.lijl1> de tfJ.I':51'fJ.1t:.;
                                                                                     4 11Ít de cõ/e.C41' ti 1Ít~elf!i IrItu's õV
      <body>
                                                                                     If!ifl14S lJl1de 3vel'flrlõ.s'.      (Lelrlbl'e-      se;
®     <hl align="center">Skyler's                  Login       Page</hl>
                                                                                       +~<'Q.1I511> fJJvflrl JfSVS(J;

©
      <p align="right">

         <img    src~"SKYLER2.jpg"            width="130"
                                                                        r
                                                                      height="150"/>
                                                                                     fJ.


                                                                                     seI' !Ma)
                                                                                                 tC
                                                                                     JeciÇ/ihl.lJS vSQ-la tlJl'        ser   sl~/es
                                                                                                                                    lf!iitS
                                                                                                                                               Je




@
      </p>



      <form     action="date2">

                Name:    <input
                                    r     () sel"vld




                                      type~"text"
                                                             pal'a.   ó 3Va./
                                          el1i1I&lI'f!1rI6Sa. s()llct+fJ.f'li4.


                                                         name~"paraml"/><br/>
                                                                                                     A's +~S

                                                                                            ~tfJ.f'fI.     tV/lU'
                                                                                                                             sel'velrl

                                                                                                                       h"l1t.as.


         Password:       <input       type="text·         'ame="param2"         I><br I><br I><br I>

                                                   "--         ()ptJl"+Vl1alrlel1+eJ
                                                                         I                    1a./aN;lrIlJs ""(/,1"$
         <center>
                                                               IÓI"IrIVIQI'14S; irias pal'a I'esvlrlir;                ó 1JI'IJIf;Isel'
             <input     type="SUBMIT"I>                        cgp+VI'fJ.1'     éI   l"I1pV+ JIJ VSV:1"14 e l"e+IJI"I1:-I",              Qtl

®        </center>                                             sel'vtJIJI'.

      </form>


      </body>
      </html>
                                ......•••.•.....•.••••.....••........•.•..............••.........••........•.•
                                :             o                                                                                                     :
                                :                        Você só vai precisar dos conhecimentos                     mais básicos                    :
                                ·
                                :
                                ·
                                ·
                                                         emHTML.                                                                                    .
                                                                                                                                                    :
                                                                                                                                                    .
                                                                                                                                                    .
                                ·
                                ·                                                                                                                   .
                                                                                                                                                    .
                                :                    0. HTML "pipoca" durante todo o exame. Mas você não                                            :
                                :    está sendo testado em HTML. No entanto, você vai se deparar com o                                              :
                                :    HTML no contexto de várias perguntas. Portanto, você precisará ao menos                                        :
                                ·
                                :
                                ·    de uma idéia do que está acontecendo quando vir um HTML simples.
                                ..............................................................................
                                                                                                                                                    .
                                                                                                                                                    .
                                                                                                                                                    :



    8 capítulo 1
introdução   e arquitetura


o que o browser     cria ...
o browserlê todo o código HTML, cria a página e a transforma
em imagem para o usuário.




                                               I
®




@ ----.:'Iame:
           Password:




                                             ®




                                                                você está                   9
o protocolo   HTTP



o que é o protocolo        HffP?
o HTTP roda no topo do TCP/IP. Se você
não está familiarizado com estes protocolos
de rede, temos aqui um curso rápido: O TCP
é responsável por garantir que um arquivo
enviado de um nó da rede para outro chegue
íntegro ao seu destino, ainda que o arquivo
                                                         Principais eleme
esteja dividido em blocos no momento do
                                                         solicitação:     ntos do fluxo de
envio. O IP é o protocolo de sustentação
que transfere/roteia os blocos (pacotes) de              ~    O método RTTP      _
um host para o outro no seu caminho até o                     executada)    (a açao de ser
destino. Ou seja, o HTTP é outro protocolo
de rede que tem características específicas             ~     A página qu          '
para web, mas ele depende do TCP/IP para                                 e sera acessada (
obter a solicitação e a resposta completas de           ~    Os parâmetros do [o'      , . uma URL)
um lugar para o outro. A estrutura de uma                    argumentos para     nn?lano (como
                                                                              ummetodo)
conversa HTTP é uma seqüência simples de
Solicitação/Resposta;    um browser solicita e
um servidor responde.
                                                    solicitação HTTP
                                                   ~




                                                             resposta
                                                             HTTP                      Servidor

                                        Principais elementos do fluxo de
                                        resposta:
                                         ~    Um código de status (~o caso de uma
                                              solicitação bem suced1da)
                                       i~      Tipo de conteúdo (texto, imagem, HTML,

                                        ~     O conteúdo (o HTML real, a imagem, etc.)
                                               etc.)




                          ..........................................................................
                                                                                                       ·
                                                                                                       ·
                           Você não precisa memorizar a especijicação do HTTP.                         ·
                                                                                                       ·
                           Se você quer mesmo saber (felizmente, o exame não espera que                ·
                                                                                                       ·
                                                                                                       ·
                           você queira), o protocolo HTTP segue o padrão IETF, RFC 2616.
                           O Apache é um exemplo de servidor Web que processa solicitações
               HTTP. O Mozilla é um exemplo de browser que dá ao usuário o mecanismo para
                                                                                                       ·
                                                                                                       ·
                                                                                                       ·
               realizar solicitações HTTP e visualizar os documentos retomados pelo servidor.          ·
                                                                                                       ·
                                                                                                       ·
              ......................................................................................
    10
introdução   e arquitetura


o HfML é parte             da resposta HffF
Uma resposta HTTP pode conter o HTML. O HTTP acrescenta a
informação do headerno topo de qualquer que seja o conteúdo da
resposta (em outras palavras, aquilo que retoma do servidor). Um
browser HTML usa aquela informação de header para ajudar no
processamento da página HTML. Considere o conteúdo do HTML
como um dado que foi colado dentro de uma resposta HTTP.




                                                      solicitação HTTP




                                                          resposta HTTP

                                                                1                Servidor


 ~Va.l7d4 6 bl"ówsel" el'Jumfl"a a +f4j
 <"+11'I1> abel"-!-v"4; ele el7+l"a.ell'l lI'Iód6
         de
 de pI"4CeSSall'le~4        d6 I/rK.4.L     e ex'-!!e a      </head.>
   /               /
 p~lP;a ." t/SVfJ.I"it>.                                    <bOdy>
                                                            <img src== ...   >
         ~val'Jdó ó bl"ówsel" el'Jcól'J-!-I"Qll'la
                                            v               </bOdy>
                                                            </htm.l>
         -!-~
            de         Iw..~e..., ele jel"a óV+l"a
         sóllct-!-a{ióltrrp          pal"14,,. bvscal"
         6 l"ecvl"sóespecllteadlJ.
                                       / AJes-h
         ca.SIJ; 6 bl"ówsel" !al"a. Vll'la.SejVl'Jda
         sóllcl+a.{ió I/rrp         pal"a ób-h"      a
         1w..4jell'l   descl"i+.   l'Jaf~    <1"""5>.




                                                                                  você está               11
Métodos HTTP



Se esta               é a resposta,        o que consta na solicita cão               ?
A primeira coisa que você encontrará é o nome do método HTTP. Estes não são
métodos Java, mas a idéia é semelhante. O nome do método informa ao servidor
o tipo de solicitação que está sendo feita e como o resto da mensagem será
formatada. O protocolo HTTP possui diversos métodos, mas os que você usará
com mais freqüência são o GET e o POSTo




                o usuário  dica em
                um Iink para uma
                                               o browser envia um HTiP GET ao
                nova página.                   servidor, pedindo ao servidor que
                                               CONSIGA a página.
                  ~




    J


 Usuário                             Browser




 POST
               O usuário digita em um          O browser envia um HTiP POST ao
    11I formulário e dica no                   servidor passando para o servidor o
    ·i!':1lt   botão enviar.
                                               que o usuário digitou no formulário.
                  ~




    I
Usuário                              Browser




   12 capítulo 1
introdução     e arquitetura


o &Ef é uma      simples    solicita~o, o POSf       pode enviar dados do usuário
o GET é o método mais simples do HTTP e seu principal
trabalho na vida é pedir ao servidor que consiga um
recurso e enviá-Io de volta. Tal recurso pode ser uma
página HTML, um JPEG, um PDF, etc. Não importa. O
objetivo do GET é conseguir alguma coisa do servidor.
O POST é uma solicitação mais poderosa. É como se
fosse um GET ++. Com o POST, você pode solicitar
algo e, ao mesmo tempo, enviar os dados de um
formulário para o servidor (mais adiante neste capítulo,
veremos o que o servidor pode fazer com esses dados).




           Nã9 ex1stem
  retguntas         idl9téls
r:  E com relação aos outros métodos HTTP
além do GET e do POST?


1:   Estes são os dois métodos mais usados por
todo mundo. Mas, existem alguns raramente usados
(e os Servlets podem tratá-Ios), tais como HEAD,                            Espere um momento ...
                                                                          Eu poderia jurar que vi
TRACE, PUT, DELETE, OPTIONS e CONNECT.                               solicitações   GET que enviavam
                                                                    alguns dados por parâmetros ao
Você realmente não precisa saber muito sobre estes                                servidor.
outros para o exame, embora você possa encontrá-
los em alguma pergunta. O capítulo A Vida e a Morte
de um Servlet aborda o resto dos detalhes dos
métodos HTTP que você poderá precisar.




                                                                         você está                     13
HTTPGET



É   verdade ... você pode enviar algutls dados           COI11    o HffF G-Ef
Mas você pode não querer. As razões para usarmos o POST no lugar do GET incluem:


    G) O total de caracteres no GET é realmente limitado (dependendo do
        servidor). Se o usuário digitar, digamos, um trecho extenso em uma
        caixa de entrada do tipo "Procurar", o GET pode não funcionar.
    @) Os dados que você envia através do GET são anexados à URL,
        lá em cima, na barra de endereços do browser; portanto, seja
        o que for, ficará exposto. Melhor não colocar a senha ou outra
        informação sensível como parte de um GET!
    ® Devido     ao item 2 acima, o usuário não pode adicionar aos seus
        favoritos a página que envia um formulário, se você usar o POST
        em lugar do GET. Dependendo de sua aplicação, você pode querer
        ou não que os usuários sejam capazes de armazenar a página
        resultante do envio de um formulário.

                                                                  U7"
                                                             A-    .     sepQ,('Q,c cQ,/fI!,I;.,I.e {JS
                                                                                                  d
                                                            pal"~e+('cs         Ccs dadtls         ex+rQ,s).      ()

                                                             +tl+1).1 de dadlJs ôlle vtlcê pede             (;"'1/1"41"

                                                             a+l"Q,vés dlJ tf:ré        IIÍf'l+ad6 e explis+6

                                                             f4alll e/fl!,clÍf'a 11(J!Jr(Jwser;     para      +"dlJ
                                                             /fI!,v'Id(J ver, JfI'I+(JS;    f(J('/fI!,o./fI!, s+rl~j
                                                                                                           (J,
                   A- (J}t.l- (JI"ij'~Q,1 f4",l-es dcs
                                                             da (JJel- ófle é el1vi'4da Ctl/fl!,a st:.lici+a{i.ó.
                  pQ,('~dl"cs       ex·f.ras.




     14 capítulo 1
introdução     e arquitetura


At1atotMia      de utMa solicitação        HffF G-Ef
o caminho até o recurso e quaisquer parâmetros adicionados à URL estão incluídos na "linha de solicitação".




                                 () calVlií'l!." paJ"a "
                                 NtcVJ"S/i '10 sf!f'vldcJ".          ~    bl"cwseJ" es-f:Pf'tJ-flJcõ/t,
                                                                           A- veJ"são do      SfJ!iél..fa'ldlJ.   õ
                            ~~
                    GET /seiect! seiectbeer'l'aste. J sp·?co.tor=aarK!itaste=mal ty HTTP/ 1.1
                                                                                                  )..
                    Host: www.wickedlysmart.com
                    User-Agent:   Mozilla/5.0    (Macintosh; U; PPC Mac OS X Mach-O; en-US;
                    rv:l.4) Gecko/20030624     Netscape/7.1
                    Accept: text/xml,application/xml,application/xhtml+xml,text/
Os l.eo.df!J"sdO.
                    html;q~0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/
S("tcl-h'yã",       gif;q=0.2,*/*;q~0.1
                    Accept-Language:    en-us,en;q~0.5
                    Accept-Encoding:    gzip,defiate
                    Accept-Charset:    ISO-8859-1,utf-8;q=0.7,*;q=0.7
                    Keep-Alive:   300
                    Connection:   keep-alive




       Ei servidor ... PEGUE aí para mim
        a página que se encontra em /
        select/selectBeerTaste.jsp    e,
       ah sim, aqui estão os parâmetros
       para você: color = dark & toste =
                malty. E depressa.



                                             solicitação HTTP


                                                       U---~
                                                                          Servidor




                                                                                    você está                     15
HTTPPOST



At1atotftia de utfta solicitação HffP POSf
As solicitações HTTP POST são designadas para serem usadas pelo
browser em solicitações complexas para o servidor. Por exemplo, se o
usuário acabou de preencher um longo formulário, a aplicação poderá
querer que todos os dados do formulário sejam adicionados a um banco
de dados. Os dados a serem enviados de volta ao servidor são conhecidos
como "corpo da mensagem" ou "payload" e podem ser bem extensos.


                                                                                                      ti-   VE'l'sâ'" dIJ

                                                                                                     fl',,-I-ót;óIIJ ôllE' ti
                                                                                                      bI"6WSE'1' es-I-~
                                                                                                      stlfiCl-l-a,uló.

                              Rost:   www.wickedlysmart.com
                              User-Agent:     Mozilla/5.0      (Macintosh;         U; PPC Mac          OS X Mach-O;             en-
                              US;   rv:l.4)   Gecko/20030624      Netscape/7.1
    Os t.eg,del"s     da      Accept:   text/xml,application/xml,application/xhtml+xml,text/
                              html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/
    StJltcr-l-Il.Sâ',,·
                              jpeg,image/gif;q=0.2,*/*;q~0.1
                              Accept-Language:       en-us,en;q=0.5
                              Accept-Encoding:       gzip,defiate
                              Accept-Charset:       ISO-8859-1,utf-8;q=0.7,*;q=0.7
                              Keep-Alive:     300
                              Connection:     keep-alive

                                                            !Jes.f.1J.lIej tlS flJ.l'v,.e.f.l'tJs        E's.f."itl 4~1I1~

 O Cor'fD da                                          ~     'lI) 11;'0.1   d" ctll'ftJ   eJ ftJl'.f.fJ.".j.I))   '1â'IJ   Ilc41/1i

 lI1e'lS~f~    aljlll/lifJ.s Çcolor=dark&taste=malty        1i'lI1l-l-4des dQ. l/Iial1E'/rQ.311eItcIJ.I'I"b.l/Iil1l1al1d"
 ul              u
 ve~es cl.all1fJ.dtJde (                                    se usa 1Ii111  bf.:'; e fl'E'ci'sal/li seI' c(Jl<)cadlJs 114
                                                                                      N
 _.f'Dj'<)lJ.d   •                                          /I;,t.a de SlJ/tct+-aflJ.c.


         Ei servidor ... por favor COLOQUE                                           Claro, eu vou procurar este
            isto no recurso localizado em:
                                                                                  recurso (na verdade, uma pequena
              / advisor / selectBeer Taste.                                         aplicação) e quando eu achar,
           do. Não se esqueça de olhar na                                           entregarei OS dados enviados
          parte interna do corpo os dados                                          no corpo da solicitação que você
          importantes que estou enviando.                                                       enviou.




                                                solicitação HTTP


                                                           u----::.;

                                                                                    Servidor
    16                    1
introdução       e arquitetura


A.,atolMia de ulMaresposta HffF e que .,egócio é esse de "MIME typeN1
Agora que já vimos as solicitações do browser para o servidor, vamos dar uma olhada no que
o servidor envia de volta como resposta. Uma resposta HTTP é composta de header e corpo. A
informação do header informa ao browser o protocolo que está sendo usado, se a solicitação obteve
êxito e que tipo de conteúdo está incluído no corpo. O corpo possui o conteúdo (por exemplo, o
HTML) que o browser exibirá.




    A vel"s~"      d4Pl"4.f.4C"/4             f) C:'dijÓ de S.f.a..f.ClS
    ~Cle., Sf!l"vtiJ.,1"we6 es+:              Hr-rp     pal"ti. a

    ClSa'ld4.                                Jeesf6s+a..                   a
                                                                      iJ ••••versã., hx.f.(J ti., C:'dijtJ
                                   .1-
                                   HTTP/1.1
                                                 :.t ~tie
                                                200 OK
                                                                           s.f.a+Cls.
                                   Set~Cookie:        JSESSIONID=OAAB6C8DE415E2E5F307CF334BFCAOC1;
                                   Path~/testEL
   i.etJ.deI"Sde
                              _~                                                      f) va/tJl" d6 t.eadel"
   Jeesp4sh        Hrrp'
                                   Content-Length: 397                                 "'          I
                                                                                      ;;te N!Sp6SrfJ. pa.I"a 6
                                   Date: Wed, 19 Nov 2003           03:25:40    GMT                         /


                                   Server: .Apache-Coyote/1.1                         C4~'1-1--I;fe      e ctJl'lt.ecl'J"
                                   Connectlon:   close                                .:6•••• If4zJ4,f. +jpe. ()
                                                                                           4
                                                                                      !fA.ZIf4f. -Iype 1'I'J/41"1J'lfJ.
                                                                                      fJ.4bl"tJwsel" 3t1e -hj>o tie
                                                                                      dfJ.titJô bl"(Jwsel" es+:

                                                                                      p41"4 I"ecebel"J1'41"43C1e'
                                                                                      es+e f"ssa sdel" CõlJ'l"
                                                                                                 /
                                                                                      pl"óces sa-/(J.

                                                                                      /t.efal"e 3C1e' valtJl"para
                                                                                                   6
                                                                                      (JIf4I!fA.f. +jfe' I"III:/el"e-
                                                                                      se QfJS1Ia./"I"es11'$+4"6S
                                                                                      '16 "eadel" ACCfp+ da
                                                                                      sôltd-h.{i.(J Hrrp'
                                                                                      (Observe (J !.eadel"

                                                                                      l1a s6Iict+a{i.., PO.:s-rJIt.
                                                                                      ":;I'I'Ja al1+el"161")
                                                         o
                                                         a
                           resposta HTTP




  Cliente                                               Servidor

                                                                                                     está               17
solicitação       e resposta




                                                                                                        (
                                                                                                                o !H'óWSft'         cria v~a
                                                                                                          
                                                                                                          ,
                                                                                                          



                                                                                                          i     SfJltct-fo.{i6     Itrrp iG,!'(
                                                                                                        '-V


                                                                                                 GET /test1/Beer1.html HTTP/1.1
                                                                                                 Host: www.wickedlysmart.com
                                                                                                 User-Agent: Mozilla/5.0 (Macintosh ...




                                                                                                                                    Beerl.html
                                                                                            <html><body>
                                                                                            <hl align~eenter>Beer Login Page</hl>
                                                                                            <form>
                                                                                              Seleet a beer type or buy beer
~5era    lI~a
                                                                                              making supplies?<p>
resf>t:Js+a                                                                                   <input type~radio name~seleet
Itrrp'                                  o   ~erVitl<J1' e"JC6"J+r~                              value~Seleet> Seleet a beer<br>
                                        4 f>~/"'Q •••                                         <input type~radio name~select
                                                                                                value=Buy> Buy supplies<br><br>
                                                                                              <center>
                                                                                                <input type~SUBMIT>
                                                                                              </eenter>
                                                                                            </form>
                                                                                            </body></html>
    HTIP/1.1 200 OK
    Set-Cookie:     ...


    <html><body>
    <hl align~eenter>Beer Login Page</hl>
    <forro>
       Seleet a beer type or buy beer . . .



              lJr   f"f!Sf><JS.f.l1.   Itrrp é eJ1vtatila         46

         1    /;l'fJwser.

                                                                                                              lJr c/tel7+-e

                                                                                                              ~v4rtila
                                                                                                              fJ.I7Si;'S14~el7+-e

                                                                                                              jVf! SVo.
                                                                                                              -frtJ.I7S14í4Ó s~a
                                                                 Beer Login Page                              reallj14tila C.:l~
                                               Sclcrt a beer type o. huy beer making supplics?                sue,!SS.:l.
                                               o Select a bcer
                                               O BllY supplies




    18                     1
introdução   e arquitetura




                                GETou POST?
                     Para cada descrição, circule POST ou GET,
                     dependendo de que método HTTP você usaria
                     para implementar isso funcionalmente. Se você
                     achar que pode ser ambos, circule os dois, mas
                     esteja preparado para defender suas respostas ...


       POST   GET   Um usuário digitando um login e uma senha.
POST                Um usuário solicitando uma nova página via hyperlink.
                    Um usuário em uma sala de bate-papo enviando uma resposta.
                    Um usuário dica no botão "next" para ver a próxima página.
                    Um usuário dica no botão de "logout" num site seguro de um banco.
                    Um usuário dica em "Voltar" no browser.

                    Um usuário envia um formulário com nome e endereço para o servidor.
                    Um usuário faz uma escolha em um botão de seleção.




                                                                         você está               19
Anatomia da URL



      URL. O que quer que você faça, t1ãO prot1ut1cie "Ean".
      Quando você procura a letra U no dicionário de acrônimos ocorre um
      congestionamento ... URI, URL, URN, onde isso termina? Por enquanto, vamos
      focar nas URLs, ou Uniform Resource Locators (Localizadores Uniformes de
      Recursos), que você conhece e ama. Todo recurso na web tem seu endereço
      único próprio, no padrão URL.
                                                                                                                       Jeec(Jl',u,;        t:J   17"""e d"
                                                                                                                       C617-H!~d" Sel7dlJ s6Ilcl+lJ.dlJ.

                                                                                                                       ~de         seI' (J*11J.
                                                                                                                                             ?~/;'IJ.
                                                      ~1'+4:
                                                       I               íS+4 I'
                                                                           ?41'-H!         da fiJt.L.
                                                                                                                        Hr14.L.;          V""    Sf!I''11le+" v""a
                                                      e "PCI6'10.I, fiíf'l tl17IC(J
                                                                                  Sel'vitÍ61'
                                                                                                                        i'íf'ltJ.jf!") P!JF; íf'I~Si'ca; v!Je(J
                                                      stI?"I'+a          v:I'i'1J.Sf61'+o.s,
                                                                           IV      I        I,                          6(1 3(1IJ.I1;Vf!1'
                                                                                                                                        tW+1'1J.C6iSIJ.
      Pr.o+tJctJl,,: Il7ltu'íf'l11.                   U""4 ~/ico.f46              e tde'l-r'fI,co.Jo.
                                                                                                                        3ve       6 sel'lIitÍlJl'      S(lelrfJ.
                                                      1'61' tlíf'lo.1'01'+0., Se vtlcê 'lã"
      f4.:l   sel'vií/cl'         (pai                                                                                  dl's?"17tbtli'fJ.I'.          Se es+a
                                                      especilical'              tlíf'lo.p61'+4 f!íf'I
      ?I'Õ+CC(J16 de                                                                                                   Pf4I'-H! "pcl6l7allól'        t!Jíf'll-h«a;
      cOíf'ltll7lctJ.5';" (l7es-H!
                                                      SVo. uJt.L.J        IJ.   fÓI'+4    80 seI':      tl
                                                                                                                       IJ. ""o.i6I'i'8. d6S sel'lIitÍÓl'es
                                                                                                                             I'
                                                      f4til'';6   I'
                                                                       eJ CÓI;,ettie'l-H!l/1Iel7+e J
      CIJ.S{JJ Hrrp'>
            I{                       atle                                                                               Iro. fl'lJC(lN.1'           PCI' I;'dex,t.+"",
      sel'lJ. tlS4dtJ,                                eS+4 e fJ. "I'+fJ.-?f4Jl'ãó
                                                               ?                                 f41'fJ. ÓS
                                                      sel'vitÍól't!,S           wd,
                    j                                                                                                  fCI' ?f4dl'';C,                ,

          http://www.wickedlysmart.com:8~/beeradvice/select/beerl.html


      Sel'vlt1iJl':         t:J            t
                                            I    '
                                  17t>íf'lf!lmc" ti" sel'lIlt1t'J1'
                                                                                                               
                                                                                                        Ca""I"'II<";   t:J   ca"",;,t.6plJ.l"a         a ItJcalt;,ã6;
        I                      ~     11
      IISICtJ pelt'J 3vo.I vtJce es-ra fl'tJCtll'fJ.I7J.D,                                              '16 sel''Ilt1"I'; J(J I'f!C(lI"StJ ô(Je es+a
                                                                                                        sel7d" st:Jltct+aJlJ. 1"" vlr.fvJe       de a
      1S-H! 1761/11e
                  8.f6'1-f-1J.
                             f41'fJ.              Víf'I ~l7i'c6

      el7tiel'f!j6 IP. t:Js e'lJel'ej.Ds                    IP
                                                                                                        íf'Iaiól'iit dos sel"!/l«lJl'es              wd     I/1I(M$
             I                                                     "sã"                                 '16!/t:JS I't!dal" fi 171)( IJ. Sl;,-f-alcf! thl1l)(
      l7t1íf'1el'i'u~s e as stlíf'le"" fJ.                             xxx.
                             u           .••                                                                     f               J
                                                                                                        41;,Ja e (JsadIA. al"a descl"evel" as
                                                                                                                            f
      jj}';;;'IJ.fJ.1Il           , ~ce p6de f!specl/l'c1A1' (líf'I
      f!"'Itiel'(j6 fIP 8.f.(li"eíf'l V('tJ tie tll/1I'16íf'1f! íf'IlJ.S                                t,tel'aI"3(Ji'tJ.s Je Jlre+:l"ibs.
                           Q            I                    J
      (Jíf'I170l/1le beíf'l íf'Ia.ts IlJ.crl de le*1bNJ.t',
                    e




;             20 capítulo 1
~~c
introdução      e arquitetura




                                                                                          ,
                                                                                 Os '7VIlflt!1"4S lIfI~i"$

                                                                                 c(mt.eeM"s          Je p61"+as

                                                                                 rcpparI),       tJ.Sapli"ctii;;t!s
Uma porta TCP é apenas um número                                                 IIfIfJ.I"$ llIIfIV'7S 3"e N,,:i8.11f1
                                                                                          C                         ellfl
                                                                                 St!I"VM4I"fS
Um número de 16 bits que identifica um
programa específico             no hardware do
                                                                             Telnet
servidor.

o software do seu servidor de intemet (HTTP) roda na
porta 80. Isto é padrão. Se você possui um servidor de                                                             Time
Telnet, ele rodará na porta 23. FTP? 21. Servidor de
e-mail POP3? 1l0. SMTP? 25. O Time server fica na 37.
Considere as portas como identificadores únicos. Uma .
porta representa uma conexão lógica para um determinado
                                                                                            110
software rodando no hardware do servidor. Só isso. Você
não pode virar o seu gabinete e encontrar uma porta TCP.
Por um motivo, você tem 65536 delas em um servidor
                                                                           HTTPS              POP3
(O a 65535). Além disso, não conectamos dispositivos
físicos nelas. Elas são apenas números representando uma
aplicação para servidor.                                          (J SfJ.'7Jtl   V"'IJ. apltefJ.S';(J
                                                                                                    1'41" p41"+a., li'"

Sem os números das portas, o servidor não teria meios de          S(!l"Vti/(Jf' ptlJe fff'           11.-#   'S-S-3(.
saber a qual aplicação o cliente gostaria de se conectar. E já    apli'ca{;;es      Jtfel"fl1ffs I       NultJ.I1JtJ
que cada aplicação deve ter seu próprio protocolo, imagine
                                                                  (e"'!?tlf'1J. S!jl), ptJS sl'lIel f'If:lJIJ.f'
o problema que você teria sem estes identificadores. E se
o seu browser, por exemplo, fosse parar no servidor POP3          11<4/"$ VII<4apltCf<f';6 111),
                                                                        Je                      II<es",~
em vez do servidor HTTP? O servidor de e-mail não sabe           P6f'+fJ. se elas VSIJ.N!1IfI
                                                                                           PI"(J+(Jc6ItJS
analisar uma solicitação HTTP! E mesmo que soubesse,              JI"$-h"'+tJS) •
o servidor POP3 não sabe nada sobre disponibilidade de
páginas HTML.
Se você está escrevendo serviços (programas de servidores)
para rodar na rede de uma empresa, você deve checar com o
administrador de sistemas quais portas já estão sendo usadas.
Seu administrador poderá dizer, por exemplo, que você não
                                                                 Os númet9s das p91tas
pode usar nenhuma porta inferior a, digamos, 3000.               de O a 10Z3 sã9
                                                                               o;    1  0d
                                                                 pata ser" lÇ95ja C9hneCl 9S
                                                                                    TO



                                                                 (Inclu'iud9 a -PrIncIpalpélta
                                                                 h9S - a p9tta 80)$ Nã9 use
                                                                 estflS p9ttas                         9S sen ti
                                                                 pt9h"tamas pattlculates!
                                                                                          você está                     21
diretório web site



A estrutura de diretórios para um site Apache simples
Nós falaremos mais sobre o Apache e o Tomcat mais adiante, mas por enquanto
vamos admitir que nosso site simples esteja usando o Apache (um servidor web
bastante popular, de código aberto e que provavelmente você já está usando).
Como parecer-se-ia a estrutura de diretórios para um site chamado www.
wickedlysmart.com, hospedando duas aplicações, uma dando conselhos sobre
esquiar e a outra, sobre assuntos relacionados à cerveja? Imagine que o Apache
esteja rodando na porta 80.
Marcamos cada uma das páginas .html com uma letra (A, B, C, D) para o
exercício na próxima página.




            I       I
ípuiex.t.-r1ti1 e 4 f>~/"'4-
                             I
      '"              I
p4dl'IJ.C 3ue Sel'4                            (J""   Sf!I'Vtd61' 1Jrf>b.ct.eIJ.ss{J""tl':      <)    J.+dlJcs (;<)1'1I6
l'e-/-':JN1IJ.d4 4<) USU:I"iJ
                                               d   d'I"e+;l'liJ-1'4l;f>fJ.NJ.     +6tÂas 4S aplí'c4í';es               tÂd
3ue díjt+6U         WliI/liI/.
                                          /    sel'vtiJ{<)I'.
wtcked'jsIf!41'+.C6""/
I1IJ   seu PNlliI/Sel'.                                                  lJr f4S+a-l'li.t;pfl.l'fJ.       fi.   apliClJ.ji!l
                                                                         !Jeel'lJrdvtce.
                                         ~                                   v:




                •       <~bd>
                        Index.html




       22 capitulo 1
                                                                        ~"
introdução    e arquitetura




Apontando as URLs para o conteúdo
Observe a estrutura de diretórios da página ao lado e escreva a URL que levaria você a cada uma
das quatro páginas .html marcadas com as letras A, B, C e D. Nós fizemos a primeira (A) para você,
porque é assim que nós somos. Para o exercício, considere que o Apache esteja rodando na porta 80.
(As respostas estão no rodapé da próxima página.)




                 Fará com que o servidor retome para você a página index.html no ponto    ®




                 Fará com que o servidor retome para você a página index.html no ponto    ®




                 Fará com que o servidor retome para você a página index.htrnl no ponto   ©




                 Fará com que o servidor retome para você a página selectBeer.html no ponto   ®

                                                                            você está                23
páginas estáticas



Servidores Web aiMaiMservir páginas
Web estáticas

                                                               lT pflbma esf:atma
                                                                Jma .1 o    ."                   (J




                                                               apenas tep9usa lá dentt9
                                                               d9 d1tet9t19. O setv''id9t a
                                                               enc9ntta e a dev'9Ive pata 9
                                                               clIente C9m9 está. '19d9 ()
                                                               clIente        'Vê   a mesma

                                                ís.f-as f>~/"I1t1.SV';fJ di,;'e.f-(J f>tU'Q.(J
               4f1i'clJ.g';fJ                   dle'1ff) eXfA..f-a.htt'1ff     C"ht(J
               alie f"ddo. 1M                   elas f6f"alit c"/(JctAdas '1() sel''r/liA.rJf''.
               S,!f"IIi"JtJf"

    servidor


                     Mas e se eu quiser, digamos,
                     que a hora atual apareça na
                     minha página? E se eu quiser
                       uma página com conteúdo
                    dinâmico? Eu não poderia ter
                    algo como uma variável dentro
                           do meu HTML?



                                                                     f. se   3l1lSel'htóS
                                                                                              ,
                                                                                            f!'1cD.i'xo.f"

                                                                     o.'5l1hta CiHSo. V4f"1fJ.llel




                                                                               [
                                                                     da f>~I"l1a    HrKA.L?
                                      <html>
                                      <body>
                                      The current     time    i8   [insertTimeOnServer].
                                      </body>
                                      </html>




                                c- MMM'M,C~GqJÀ8lligr~'cOllipGGr~qA,CG
                                D- MMM'M,C~GqJÀ8lligr~'cOllipGGr~qA,CG8GJGC~8GJGC~BGGr'p~llirl
                                B- MMM·M'C~GqJÀ8lligr~·cOlli8~"uàVqA'CG                                    J

  24
introdução   e arquitetura


Mas algutHas vezes você precisa de tHais do
que só o servidor




                                                         Mas como isso vai ajudar? Meus
                                                            clientes são todos clientes
                                                          web. O browser só conhece o
                                                        servidor ... ou seja, ele não vai ser
                                                          capaz de chamar aquela outra
                                                                      aplicação.

                                                                   o
                                                                   ó


servidor        outra aplicação do servidor




                Isto não é problema. Eu cuidarei de
                  entregar a solicitação à aplicação
               helper correta. Aí, eu pego a resposta
                 da aplicação e entrego de volta ao
               cliente. Na realidade, o cliente nunca
                   precisa saber que outra pessoa
                        participou do trabalho.




                      outra aplicação
                      do servidor



                                                                        você está               25
quando um servidor não      é o bastante


Vuas coisas que o servidor não faz sozinho
                                                                   As Páh1nclSInstantâneélB
Se você precisa de páginas instantâneas (páginas criadas
dinamicamente e que não existiam antes da solicitação) e           nã9 eXIstem antes de
da capacidade para escrever/salvar dados no servidor (que                                     l'
significa escrever em um arquivo ou banco de dados), você          ser te'lta a s91'lc'ltaç-ã9.E
não pode contar apenas com o servidor.
                                                                   C9m9 tqz.er uma pâblna
1 Conteúdo dinâmico                                                B11t[., de tepente.
A aplicação que roda no servidor disponibiliza somente
páginas estáticas, porém uma outra aplicação "assistente",         A s91'lc'ltayã9cbet;a. q
com a qual o servidor pode se comunicar, pode construir
páginas dinâmicas instantaneamente. Uma página dinâmica            apllcaç-ã9 beIpet ~~escteve"
poderia ser qualquer coisa, desde um catálogo até um               9 BINIL, e 9 setVld9t
weblog, ou até mesmo uma página que escolha imagens
aleatoriamente para exibi-Ias.                                     tet9tna a9 clIente.

 Quando em vez disto:                       Você quer isto:


      <html>                             <html>
      <body>                             <body>
      The curent    time   is            The curent    time   is
      always 4:20 PM                       [insertTimeOnServer]
      on the server                        on the server
      </body>                            always    4:20 PM
      </html>                            on the    server
                                         </body>
                                         </html>




2 Salvando os dados no servidor
Quando o usuário envia os dados em um formulário, o servidor
analisa os dados e pensa: "E aí? Eu devo me preocupar?".
Para processar esses dados, salvá-Ios em um arquivo ou
banco de dados, ou até mesmo para usá-Ios na criação da
página de resposta, você precisa de outra aplicação. Quando o
servidor recebe uma solicitação para uma aplicação helper, ele
considera que aqueles parâmetros são destinados ao assistente.
Assim, o servidor passa os parâmetros, fornecendo à aplicação
uma forma de gerar uma resposta ao cliente.




   26 capítulo 1
introdução   e arquitetura


o fernto     t1ão-Java para uttta aplicação helper
que roda     tiO   servidor é o "C&I~~

A maioria dos programas CGI é escrita como scripts em Perl,
mas várias outras linguagens podem servir, incluindo o C, o
Python e o PHP. (CGI significa Common Gateway Interface
- Interface de Passagem Comum -, e não nos importamos por
que ele é chamado assim.)
Usando o CGI, veja abaixo como funciona uma página
dinâmica que possui a data atual do servidor.

o                                                      servidor
                                                                                   o usuário dica em um


~-,
                                                                                  link que tem uma URL,
                                                                                  que chama um CGI em
                                      aplicação                                   vez de uma página
                                     do servidor                                  estática.
  Cliente




 ..Cliente
             )          aplicação
                       do servidor
                                           servidor



                                          parâmetros
                                                        aplicação
                                                         helper
                                                                     A aplicação do servidor "vê" que a
                                                                     solicitação é para o programa
                                                                     assistente, então o servidor abre
                                                                     e roda o programa. A aplicação do
                                                                     servidor envia junto os parâmet-
                                                                     ros do GET ou POST.




                                           servidor
                                                                    A aplicação helper constrói a nova
                                                                    página (que tem a data atual inserido)
                                                                    e devolve o HTML ao servidor.
 ~)Cliente
                                                        aplicação
                                                         helper
                                                                    Para o servidor, o HTML da aplicação
                                                                    helper é uma página estática.




                                                       servidor
                                                                                  A aplicação helper é

                                       [J
                                      aplicação
                                     do servidor
                                                                                  fechada e o cliente
                                                                                  recebe de volta uma
                                                                                  página HTML contendo
                                                                                  a data atual, agora
                                                                                  estática, como parte




                                                                               você está aqui ~           27
dois lados, CGI   e Ser,;iets


Os Servlets    e o   CG-I   aruaIM COlMOuIMa aplicação
helper no servidor
                                                    Preste atenção na conversa dos nossos dois faixas-
                                                    pretas sobre os prós e os contras do CGI e dos Servlets.



    CGI                                                                                    Servlets


o CGI é melhor  que os Servlets. Nós criamos os        Com todo o respeito, mestre, existem muitas
scripts CGI em Perl na nossa empresa, pois todo        vantagens em se usar o Java, em vez do Perl, para
mundo sabe PerI.                                       essas coisas que você quer fazer com o CGI.


Eu acho que é legal usar Java, se você souber.         Desempenho, por exemplo. Com o Perl, o
Mas certamente, não valerá a pena para nós             servidor tem que rodar um processo superpesado
mudar para Java. Não há nenhuma vantagem.              para todas as solicitações que sejam para este
                                                       recurso!

Você está me desafiando? Em quais assuntos?
                                                       Ah, sim, mas os Servlets ficam carregados e
                                                       as solicitações dos clientes para um recurso do
Isto não é diferente do Java ... O que você chama      Servlet são tratadas como threads de um único
de JVM? Cada ocorrência da JVM não é um                Servlet em execução. Não existe overhead ao
processo superpesado?                                  carregar a NM, as classes e tudo mais ...


Eu vejo que você esqueceu muita coisa.                 Eu não esqueci, mestre. Mas não são todos os
Atualmente, os servidores web são capazes              servidores que podem fazer isso. Você está se
de manter um único programa Perl rodando               referindo a um caso isolado que não se aplica
entre as solicitações dos clientes. Por isso, seu      a todos os programas CGI em PerI. Porém, os
argumento de que ele é mais pesado não vale            Servlets serão sempre mais eficientes quando isso
de nada.                                               ocorrer. E não vamos esquecer que um Servlet
                                                       pode ser um cliente J2EE e um programa CGI em
                                                       Perl não.
Do que você está falando? Qualquer coisa
compatível com o CORBA pode ser um
cliente J2EE.                                          Eu não quero dizer um cliente para um      programa
                                                       J2EE, e sim um cliente que é um J2EE.      Um
                                                       Servlet rodando em um container J2EE       pode
Chega, estou atrasado para minha aula de Pilates.      participar da segurança e das transações    com
Mas não pense que acabou. Vamos terminar isso          enterprise beans e existem ...
mais tarde.
                                                                                                 continua ...


Eu duvido que todos saibam PerI. Eu gosto do
Perl, mas todos somos programadores Java aqui
na empresa; então, preferimos Java.



   28 capítulo 1
introdução           e arquitetura




                                         o I/Sil~l'íé. J.iji.f(J,
                                                 t/W(J,   u~l-.
Solicitação                                          ~
Resposta
                                                                                      11
                                                                                                   HTTP/U
Complete as caixas                                                          GET /test1lBeer1.htm
                                                                                 .      WicKedysmart.com
escrevendo o que acontece                                                   Host. www·        '1 /5 o (Macintosh ...
                                                                            user-Agent: Mozl a .
durante cada passo no
processo. Esta é uma cópia
da página 18. Ou seja,
                                                                                     <htrnl><body>
ao terminar, volte lá para                                                           <hl align=center>Beer              Login Page</hl>
comparar suas respostas.                                                             <forro>
                                                                                        Seleet a beer type ar buy beer
                                                                                        making supplies?<p>
                                                                                        <input type=radio name=select
                                                                                          value=Select> Select a beer<br>
                                                                                       <input type=radio name=select
                                                                                         value=Buy> Buy supplies<br><br>
                                                                                       <center>
                                                                                         <input type~SUBMIT>
                                                                                       </center>


                      S·d~i
                       ervl or
                                                                                     </form>
                                                                                     </body></html>




                                 1
                             HTIP/1.1 2000K
                             Set-Cookie: ...


                             <html><body>
                             <hl aIign=center>Beer          Login Page</hl>
                             <Íorrn>

                                SeIeet   a beer type or buy beer            ...




                                                                                           A- c!ie#i-fe fJ.5t/tJ.1'ç(fi.
                                                                                           a#iSl(jSfA~e#i-fe ~tlf
                                                                                           st/a .ff'fI.#isa{i(J

                                                Beer Login Page                            S~(J, f'f4'l-;l'J.tifl. c.o~
                                                                                           St/Cf!S SlJ.
                              Select a beer type or buy beer making .supplies?

                              O Selccr a beer
                              C Buy $upplíes




                                                                                                        você está                         29
uma rápida olhada nos servlets



Servlets Desmistificados
(criar, distribuir, executar)
Pois é, os novatos em servlets já podem parar de prender a
respiração; aqui está um guia rápido para criar, distribuir e executar
um servlet. Este guia pode gerar mais perguntas que respostas -
não se assuste! Você não precisajazê-Io neste exato momento. É




  O
apenas uma rápida demonstração para tutorial mais não conseguem /
esperar. O próximo capítulo inclui um aqueles que detalhado/
       Construa esta árvore de diretórios (em qualquer lugar,
        exeeto sob o tomcat).                                                 Ch1Servletjava
                                                                                                                               weh.xml




  8    Crie um servlet chamado ChlServlet.java e o coloque no diretório sre (para
       simplificar este exemplo, não colocaremos o servlet em um pacote; mas após
       este, todos os outros exemplos com servlet neste livro estarão em pacotes).
    import    javax.servlet.*;
    import    javax.servlet.http.*;
    import    java.io.*;



       public     void   doGet(HttpServletRequest              request,
                              HttpServletResponse             response)
    public    class   ChlServlet
                             throwsextends HttpServlet
                                     IOException  {                    { ~

             PrintWriter     out ~ response.getWriter();


             ou t .pr in tln ("<h tml>       " +                                                           rrrJl4.L         IPJSf;l"it/.t)
                           "<body>"      +                                                                        vw, PI"t)51"fJ.""'(J.
                                                                                                           Java. '" J
                                                                                                                 ";.
                                                                                                           e"",

                                                                                                                                J
                                                                                               'l"
                        "<hl align~center>HF' s Chapterl Servlet</hl>"                           +                        ;1"1J!t)
                        + "<br>" + today + "</body>" + "</html>");                                           IV!
             java.util.Date  today ~ new java.util.Date();                                                 "46 ti! w,es""'(J?


  8    Crie um deployment descriptor (DD) chamado web.xml e
       ponha-o no diretório ete.
                                                                                        c.<J"Jsi'tI.eN4;es
                                                                                               l-a'J.f-e S:
                                                                                       1Ry>4/'••

                                                                                        - (J :b!J pfJ.l"tI.c!J.t/.fJ.
                                                                                            "'"
    <?xml    version="l.O"      encoding-"ISO=8851-1"             ?>
    <web-app     xmlns=''http://java.sun             .com/xml/ns/j     2ee"             apliClJ.yfltJ         web.
             xmlns: xSi= ••ttp://www.w3.org/200l/XMLSchema-instance
                          h                                                           -(JltlJ!Jpt)t/.eJ.ecllU.1J.1..
                                                                                     ••
           xsi:schemaLocation~''http://java.sun.com/xml/ns/j2ee/                             !.
                                                                                        V8.1"14Ssel'v              Ie.,-s.
                                                                                                                      I
           http://java.sun.com/xml/ns/j2ee/web-app       2 4.xsd"
        version="2.4/>                                                                  - (JIt <:'sel'lIle-!-'JIJ.w,e>
        <servlet>
                                                                                                     4
                                                                                        1J.""'41'1'1J. e/e"",e",-!-a
             <servlet-name>Chapterl                Servlet</servlet-
             name>                                                                      <:.sel'lIle-!->           4tJ    ele""'e,,-!-a
             <servlet-class>ChlServlet</servlet-class>
                                                                                        <:.sel'v1e-!-lttJ.pp'-"5              >.
        </servlet>
                                                                                        - (J1t<:'sel'lIle-!-clfJ.ss>                      é
        </servlet-mapping>                                                              IJ. clfJ.Sse J4VIJ..
             <servlet-name>Chapterl                Servlet</servlet-
             name>                                                                      -      11"",   <:'fll"l-pfJ.fflM>              é
             <url-pattern>/Servl</url-pattern>
                                                                                        (J   ",,,,,,,,e afie"           dle,,-h       flSfJ.
        </servlet-mapping>
    </web-app>
                                                                                       1'41'4          a s4IiCi-!-tJ.{i6.

    30 capítulo 1
introdução     e arquitetura


 o    Construa esta árvore de diretórios abaixo do diretório tomcat
      existente ...


 o    Do diretório projectl,    compile o servlet...
                                                                                       o nome        da
                                                                                       aplicação
                                                                                       web
   servlet-api.jar       -d classes      src/ChlServlet.java

  (IS+6     +V1I16é VII'I ~"l'c6 Ct)II'IIU'I1I14)                                 ~
[%javac     -classpath      /your   path/torncat/common/lib/


   (o arquivo Chl Servlet.class vai terminar em projectl/classes)



 o    Copie o arquivo ChlServlet.class para WEB-INF/classes,
      arquivo web.xml para o diretório WEB-INF.
                                                                    eo



 fi   Rode o Tomcat a partir do diretório tomcat ...
      %bin/startup.sh                                                                 Ch1Servlet.class




 o    Abra seu browser e digite:
      http://localhost:8080/chl/Servl
      deve aparecer:




          HF's Chapterl Servlet

          Tue Feb 10 15:01:24 MST 2004




 @) Por   enquanto, toda vez que você atualizar ou uma classe de
      servlet, ou o deployment descriptor, dê um shutdown no
      Tomcat:


       %bin/shutdown.sh




                                                                          você está aqui •.               31
HTML em um println() não rola



                                                          I                      •••                 I
                Sem ofensas, mas existe                   f. 4SSI"" IJ
                                                                    'l.(le lI.:lce CI'I"!A        t:>(J,f;1i14
                                                                                          (11104 r "



                                                          dli1M-.tc(J,e~ (I~ sel'lIle.f-.                +ello 3ye
               alguma coisa SERIAMENTE
              errada com esta figura sobre                                                        I~cê
               servlets ... tentando enfiar o             ex"!!ll'   .f-yJ() pal'fJ. y~fJ. salda ex+eI''JfJ. ('JfJ.
             HTML dentro de um printlnO??
             Isso não pode estar correto..
                                                                .A   J.        '         L   .A              J
                                                          V!!I'91"'14l1e) I$S4 e plJ.l''TT:."1(;, I'espas-r(;,
                                                                                                                  JlrrO
                                                                                                                 rr    r
                                                                               ••• j'


        &'                                 /I"r                ...Iev_ ,..
                                                                 .   ....~('.".I.).
                   out.println(~<html> ~ +
                                 ~<body>" +
                                 ~<hl>Skyler's Login Page</hl>"
                                       +
                                       ~<br>" + today +
                                       ~</body>" +
                                       ~</html>");


                                           Na verdade, tehtar fort1atar o HfM.
                                           dehtro de Ut1out.prihtlhO hO servlet é pior
                                           aihda.
                                           Esta é uma das piores partes (não, a pior parte) dos servlets.
                                           Enfiar tags HTML, devidamente formatadas, dentro do
                                           printlnO, só para que você possa inserir variáveis e métodos
                                           de chamadas é simplesmente uma crueldade. Nem pense
                                           em inventar coisas, ainda que pouco sofisticadas.




                                           r:   Não pode ser tão ruim assim ... Por que eu não
                                           posso simplesmente copiar uma página HTML
                                           inteira do meu editor, como o Dreamweaver, e
                                           colar dentro do printlnO? Não é só para eu ser
                                           capaz de ler o código lá dentro?


                                           1: Obviamente,    você ainda não tentou fazer isso.
                                           Que bom. Sim. Eu faço minha página em um editor
                                           decente (ou até mesmo um simples arquivo de texto
                                           seria mais fácil que no meu código Java) e, então,
                                           faço um copiar/colar rapidinho no printlnO e pronto!
                                           Pena que você vai receber 1.378 erros de compilação.
                                           Lembre-se de que você não pode ter um carriage return
                                           (retorno de carro) de verdade dentro de uma String
                                           literal. E já que estamos falando de Strings ... o que dizer
                                           do seu HTML com todas aquelas aspas duplas?




  32 capítiulo 1
introdução        e arquitetura




        Oh, se pelo menos existisse
         uma maneira de colocar o
        Java dentro de uma página
        HTML, em vez de colocar o
        HTML dentro de uma classe
                   Java.




                    Ela ttão cottheee o JSP


    <html>
    <body>                                                 DptJ.!Is+;;; se p4.t'ece        CIJIM

    <hl>Skyler's   Login   Page</hl>
    <br>
                                                           VIM pf.'1pe.l1tJ          "fIM l1ó
    <%= new java.util.Date()     %>
                                                           1Mf./~   Je   VIM   H-rA4.L?!
    </body>
    </html>




                    sky/erlogin.jsp

Uma página JSP é bem parecida com uma página HTML,
com a diferença de que você pode inserir Java (e coisas
relacionadas ao Java) dentro da página. Portanto, é
realmente semelhante a inserir uma variável no seu HTML.




                                                                você está aqui ~              33
o Java encontra o HTML = JSP



JSP foi Oque acottteceu quatldo alguéttt apresetltou o Java ao HfML
Itlserir o Java tiO HfML é a solução para dois probletttas:

1 Nem todos os designersque fazem
   páginas em HTML conhecem Java

Os desenvolvedores de aplicação sabem Java. Já os
designers de páginas sabem HTML. Com o JSP, os
desenvolvedores Java fazem a parte Java, enquanto
que os desenvolvedores HTML fazem as páginas.



2 Formatar    o HTML dentro de uma
   String literal é REALMENTEterrível
Inserir um HTML, mesmo que levemente complexo, dentro de
um argumento em um printlnO é esperar que ocorra um erro de
compilação. Pode ser que você tenha que fazer um trabalho
enorme para formatar o HTML, de forma que ele funcione no
browser do cliente, mas satisfaça as regras do Java para aquilo
que ele for designado a fazer na String. Você não pode ter, por
exemplo, carriage returns, embora a maioria dos HTMLs que
você baixa e edita terá carriage returns de verdade na fonte.
As aspas podem significar um problema também - muitas
tags HTML usam aspas antes e depois dos valores para
atributos, por exemplo. E você sabe o que acontece quando
um compilador dá de cara com as aspas duplas ... ele pensa
"este deve ser o final da String literal". Naturalmente, você pode
voltar e substituir suas aspas duplas pelos escape codes ... mas
isso tudo aumenta demais a chance de erros.


r:   Espere ... ainda tem algo de errado aqui! A vantagem número 1
diz que "nem todos os designers de páginas sabem Java ...", mas
quem cria páginas em HTML ainda tem que escrever o Java dentro
da página J5P! O J5P alivia o programador Java de escrever o HTML,
mas ele não ajuda, de fato, o designer que cria o HTML. Poderia ser
mais fácil escrever o HTML em um J5P, em vez de num printlnO, mas
o profissional que escreve o HTML ainda terá que saber Java.


I: Parece que sim, não parece?   Mas com a nova especificação para
o JSP - e seguindo alguns conselhos -, o desenvolvedor da página
incluirá, de Java mesmo, muito pouco (ou nenhum) no JSP. Eles terão
que aprender alguma coisa ... mas algo como colocar labels que de
fato chamem os métodos Java, em vez de escrever o código Java real
na página mesmo. E terão que aprender a sintaxe JSP, mas não a
linguagem Java.

   34   capítulo 1
introdução    e arquitetura




HTTP significa HyperText Transfer Protocol (Protocolo para Transferência de
Hipertexto), e é o protocolo de rede usado na Web. Ele roda no topo do TCP/IP.

O HTTP usa um modelo solicitação/resposta - o cliente faz uma solicitação HTTP e o
servidor web devolve uma resposta HTTP, que o browser então calcula como tratá-Ia
(dependendo do tipo de conteúdo da resposta).

Se a resposta vinda do servidor for uma página HTML, o HTML é adicionado à
resposta HTTP.

Uma solicitação HTTP inclui a solicitação URL (o recurso que o cliente está tentando
acessar), o método HTTP (GET, POST, etc.) e (opcionalmente) os dados de parâmetros
do formulário (também chamado de "query string").

Uma resposta HTTP inclui um código de status, o tipo de conteúdo (também conhecido
por MIME type) e o conteúdo real da resposta (HTML, imagem, etc.).

Uma solicitação GET anexa dados do formulário no final da URL.

Uma solicitação POST inclui dados do formulário no corpo da solicitação.

Um MIME type informa ao browser que tipo de dados ele deverá receber, para que o
browser saiba como tratá-Ios (processar o HTML, mostrar o gráfico, tocar a música,
etc.).

URL significa Uniform Resource Locator (Localizador Uniforme de Recursos). Todo
recurso na web tem seu próprio e único endereço neste padrão. Ele começa com o
protocolo, seguido pelo nome do servidor, um número de porta opcional e geralmente
um caminho específico acompanhado do nome do recurso. Opcionalmente, ele também
pode incluir uma query string, se a URL for para uma solicitação GET.

Os servidores web são bons em disponibilizar páginas HTML estáticas, mas se você
precisa de dados gerados dinamicamente na página (como a hora atual, por exemplo),
você precisará de algum tipo de helper que possa trabalhar com o servidor. O termo
não-lava para estas aplicações assistentes (freqüentemente escritas em Perl) é CGI (que
significa Common Gateway Interface - Interface de Passagem Comum).

Colocar o HTML dentro de uma declaração println( ) é terrível e suscetível a erros, mas
os lSPs solucionam este problema ao permitir colocar lava em uma página HTML, em
vez de colocar o HTML dentro de um código lava.




                                                                      você está              35
A arquitetura da aplicação web




Os servlets precisam de ajuda. Quando uma solicitação chega,
alguém tem que instanciar o servlet ou, pelo menos, criar uma
nova thread para tratar a solicitação. Alguém tem que chamar ou
o método do PostO ou o método doGetO do servlet. E, claro, esses
métodos possuem um argumento crucial - os objetos request e
response HTTP. Alguém precisa levar a request e a response para
o servlet. Alguém precisa gerenciar a vida, a morte e os recursos
do servlet. Esse alguém é o Container. Neste capítulo, vamos ver
como sua aplicação roda no Container e daremos uma primeira
olhada na estrutura de uma aplicação usando o padrão de projeto
Model View Controller (MVC).




                                                           este   é um   novo capítulo   ll>   37
objetivos do exame oficial da Sun




                                      06jetivgs
                                   IS!!hS.i ....- - -




A Arquitetura das Aplicações de Alto Nível


                                                        Notas sobre a Abrangência:

1.1 Para cada Método HTTP(como GET, POST,
     HEAD e assim por diante), descrever o              Todos os objetivos nesta seção serão abordados
     seu propósito e as características técnicas        completamente em outros capítulos. Portanto,
                                                        considere este capítulo como uma base para o que
     do protocolo do Método HTTP, listar
                                                        virá depois. Em outras palavras, não se preocupe
     os triggers que podem levar o cliente
                                                        em terminar este capítulo sabendo (e recordando)
     (geralmente um browser) a usar o Método
                                                        assuntos especificos destes objetivos.
     e identificar o método HttpServlet que
     corresponde ao Método HTTP.                        Não existirá nenhuma pergunta sobre estes
                                                        assuntos nos testes práticos, até que você chegue ao
                                                        capítulo especifico em que eles serão abordados.
1.4 Descrever o propósito e a seqüência de eventos      Aproveite este material legal, simples e que
     do ciclo de vida do servlet: (l) carregar a        servirá de base enquanto você pode!
     classe do servlet, (2) instanciar o servlet, (3)
                                                        PORÉM .. você precisa conhecer estes assuntos
     chamar o método init, (4) chamar o método          para prosseguir. Se você já tem alguma
     service, e (5) chamar o método destroy.            experiência com servlet, poderá simplesmente
                                                        pular as páginas, olhar as figuras, jazer os
                                                        exercícios e avançar para o capítulo 3.
2.1 Construir a estrutura de arquivo e diretórios
     de uma aplicação que contenha (a) conteúdo
     estático, (b) páginas JSP, (c) classes do
     servlet, (d) o deployment descriptor, (e)
     bibliotecas de tags, (f) arquivos JAR, e (g)
     arquivos de classe Java; e descrever como
     proteger os arquivos de recurso do acesso
     HTTP.



 2.2 Descrever o propósito e a semântica
     para cada um dos seguintes elementos
     do deployment descriptor: instância do
     servlet, nome do servlet, classe do servlet,
     parâmetros de inicialização do servlet e a
     URL que aponta para o respectivo servlet.




 38 capíitulo2
arquitetura de alto nív~1




o   que    é   um Container?
Os servlets não possuem um método mainO. Eles estão sob o
controle de outra aplicação Java chamada Container.

o Tomcat    é um exemplo de Container. Quando sua aplicação web
(como o Apache) recebe uma solicitação para um servlet (ao contrário
de, digamos, uma antiga e estática página HTML), o servidor entrega a
solicitação não ao servlet em si, mas para o Container no qual o servlet é
distribuído. É o Container que entrega ao servlet a request e a response
HTTP, e chama os métodos do servlet (como o doPostO ou o doGetO).




                                                                                     servidor


                                                                                      código
                                                                                 Y     Java

                                                   aplicação
                                                 do Container
                                                      web




                                                                                  servidor




                                                                             você está aqui     11>   39
ti vida sem servlets



E se você tivesse o Java e não tivesse nelt servlets,
net1 Oontaineres?


E se você tivesse que escrever um programa em Java para tratar
as solicitações dinâmicas que chegam na aplicação do servidor
(como o Apache), mas sem um Containet como o Torncat? Em
outras palavras, imagine que não exista nada como os servlets
e tudo que você tem são as bibliotecas principais do J2SE? (É                    D
                                                                                O
claro que você pode admitir que tem a possibilidade de
configurar a aplicação do servidor para que ela possa
chamar a sua aplicação Java). Tudo bem, você ainda
não sabe bem o que o Container faz. Apenas imagine
que você precise de um suporte ao lado do servidor
para uma aplicação e tudo o que você tem é um Java
antigo e comum.


Liste algumas das funções que você teria que
implementar numa aplicação J2SE Se não
existisse o Container:




            "'U!J9UI~m ~p Olu~UIu~:)ml~ll'iud~ "'dSf ~llodns 'sllol OUIO:) US~O;)
                                                                         S     lUlllY
IUl~nb 'u6U1un1l~slUlu~m~ldm~ 'spu~.nn ~p lOPU~;)U~l~ll lU!J;) :s~~AJssodSUlsods~lI
                                                       mn
40 capitulo 2
arq'uít,'Jtwra de alto nível




o que o Cotttait1er oferece?
Nós sabemos que é o Container que gerencia
                                                                 Gta'i.cts a9 C9nt:Unet,
                                                                 VOCÊ p9de se C9noonttélt
e roda o servlet, mas por quê? Vale a pena o
overhead extra?                                                  mais na 1.1"
                                                                    "        9hICa d9 seu
                                     ..                          pt9ptl9 neh9c19, em ve;z de
o container  oferece uma maneira simples para seus
                                                                 se pte9cupat em esctey'et
servlets se comunicarem com seu servidor. Você não               c9dIh9s pata thteads,
precisa construir um ServerSocket, escutar uma porta,            sehutétn,?a e tede.
criar tráfego, etc. O Container conhece o protocolo
entre o servidor e ele mesmo, para que seu servlet não
tenha que se preocupar com uma API entre, digamos,
                                                                 VOCÊ tem 'Lue.- étnallz.éu'
                                                                                   c
o servidor Apache e o código da sua própria aplicação.           t9da a sua enetgIa na
Tudo o que você tem que se preocupar é com a lógica              Ctla,?ã9 de uma 19ja y'Iltual
do seu próprio negócio, que está contida em seu Servlet          tabu19sa pata embalélhens
(como aceitar um pedido na sua loja virtual).                    de p1â5tlc9-b91ha e deIxat
                     . ..         . .-                           9S sety'I,?9S de SUP91te,
O Container controla a vida e a morte dos seus servlets.         C9m9 a sehutétn,?a e 9
Ele cuida de carregar as classes, instanciar e inicializar       Pt900SSament9 JSf, pélta 9
                                                                       "
os servlets, chamar os métodos do servlet e tornar               C9ntUnet.
as instâncias do servlet aptas a coletar o lixo. Com o
Container no controle, você não precisa se preocupar
tanto com o gerenciamento dos recursos.
                                         O Container cria              Agora, tudo o que eu tenho que
automaticamente uma nova thread em Java para cada                     me preocupar é como vender me
                                                                       suado plástico-bolha,   em vez de
request do servlet recebida. Quando o servlet conclui a
                                                                       escrever todos aqueles códigos
execução do método de serviço HTTP para a solicitação                para as coisas que o Container fará
daquele cliente, a thread termina (isto é, morre). Isto não                       para mim ...

significa que você está liberado da segurança do thread -
você ainda pode ter problemas de sincronização. Porém,
contar com o servidor para criar e gerenciar as threads para
                                                                                      o O
as várias solicitações ainda nos poupa de muito trabalho.

Certeza de segurança                   Com um Container,
você pode usar um deployment descriptor XML para
configurar (e modificar) a segurança, sem ter que escrever
direto no código da classe do seu servlet (ou qualquer outro).
Pense nisso! Você pode gerenciar e alterar sua segurança
sem tocar, ou recompilar, seus arquivos-fonte em Java.

Suporte ao .,ISP           Você já sabe como os
JSPs são legais. Bem, quem você pensa que se
encarrega de traduzir aquele código JSP em Java
de verdade? É claro. O Container.




                                                                                      está                 41
o Container

Co~o o Comaitter trata u~a solieita~o

Vamos economizar alguns dos cartuchos para mais tarde, mas aqui está
um breve esquema:



o
                                                                       o usuário  dica em um
                                                                       link que contém uma
                                                                       URL para um servlet,
                               container                               em vez de uma página
                                                                       estática.




 -,
  Cliente


                                                  •
                                                                       o  container "vê" que
                                                                       a request é para um
                                                                       servlet e então ele cria
                                                                       dois objetos:
                                                                       1) HttpServletResponse
                                                                       2) HttpServletRequest

                                              response




 -.
  Cliente
                                                                       o container  encontra
                                                                       o servlet correto
                                                                       baseado na URL da
                                                                       request, cria ou aloca
                                                                       uma thread para essa
                                                                       request, e passa os
                                                                       objetos request e
                                                                       response para a thread
                                                                       do servlet.




42 capítulo 2
arquitetura de alto nível       ,
                                                                                          I

                                                                                        I
                                                                                         j
                                                                                          i
                                                                                        ~
                                                               O container chama o
                                                               método serviceO do
                                                                                        I
                                                                                        !
           C1J                         •
          containe~~er~let                                      servlet. de request,
                                                                do tipo Dependendo]       "




                                                                                        1,1,:
                                __      <--::::.J
                                                                o método serviceO
                                                                chama ou o método
                  request •      '"/         1                  doGetO, ou o método
                    response.          serviceO                 doPostO·
                                                                Para este exemplo,
                                                                consideraremos que a
                                                                request foi um HTTP
                                                                GET.




-.
Cliente
           o
          container
               response
                                       servlet
                                        I
                                        O
                                              I




                                         serviceO
                                                    ,J.
                                                    doGetO
                                                                O método doGet gera
                                                                uma página dinâmica
                                                                e a insere no objeto
                                                                response. Lembre-
                                                                se, o container ainda
                                                                tem uma referência
                                                                do objeto response!




                                                                O thread termina, o
                                                                container converte
                                                                o objeto response
          container                                             em uma response
                                                                HTTP, envia de volta
                                                                ao cliente e apaga
                                                                os objetos request e
                                                                response.
                res~
               re~




                                                             você está aqui ~     43
o código   do servtei



Cotto fica   O   código (o que toma utt servlet UttservletJ




       PrintWriter   out ~ response.getWriter();
       java.util.Date   today = new java.util.Date();
       out.println(ft<html>   ft +
                   "<body>" +
                   ft<hl style="text-align:center>"   +          .•.
                   ftHF's Chapter2 Servlet</hl>"   +     4ce pl:Jtle c6J?se5uir       u~
                   "<br>U + today +
                   ft</body>" +                           PrlPi-PNl't-t-e1'      dó ótJe+ó
                   ft</html>");
                                                          ~ue      6 seu sel'vle+     I'ecebe    d6
                                                          C6111+tJ.fPiel'.
                                                                        ti+lit"3e l:JPrlJ?.fWl'l-t-e1'
                                                          pt1.Nl escl'evel'       -t-eX+6    #rJlA.L
                                                          J?()  tltJe+6 l'esptJlIIse.    Me;
                                                                                         p<Jde
                                                          "'I""f:1'   I          ""      r     r
                                                           1._ (j(l-rI't1.S 6pf6es de sQlda ale~

                                                          tltJ Prll1-PNl'lhl')      pal'(J, escl'evel'.)


                                                          hx+" ffrJlA.L)
                                                          dija~6sll
                                                                  u~1.l f~(lf'aJ            e~ vej    de u~
       Nã9 exIst~m
f eth'untél5          Idl9téls

r: Você foi muito superficial ao explicar
como o container encontrou o servlet
                                                r:
                                                e
                                                     Eu me lembro de ter visto o doGetO
                                                  o doPostO, mas na página anterior você
correto ... ou seja, como uma URL se            mostrou o método serviceO? De onde ele
relaciona com um servlet? O usuário tem         surgiu?
que digitar o caminho exato e o nome do
arquivo de classe do servlet?
                                                I:   Seu servlet herdou isso do HttpServlet,
                                                que herdou isso do GenericServlet, que
I: Não. Mas esta é uma boa pergunta.           herdou isso do ... ahhh, nós veremos muita
Mas ela nos leva a um Assunto Bem Grande        hierarquia de classes no capítulo Sendo um
(mapeamento de servlet e padrões de URL).       Servlet; portanto, aguarde só um pouquinho.
Portanto, daremos apenas uma rápida
olhada nas próximas páginas, mas veremos
muito mais detalhes adiante (no capítulo
sobre Distribuição).

44                2
arq'uitE,1fW"a   de alto nível



Você está se perguntat1do          COlMO   o Contait1er
et1cotttrou o Servlet ...


De alguma forma, a URL que chega como parte da solicitação do
cliente é mapeada para um servlet específico no servidor. Este
mapeamento de URLs para servlets pode ser tratado de várias
formas e é um dos assuntos fundamentais que você irá lidar como
desenvolvedor de aplicação. A solicitação do usuário deve mapear
para um servlet específico e cabe a você entender e (geralmente)
configurar este mapeamento. O que você acha?




            EXERCITE

            Como o Container deveria mapear os servlets para as URLs?
            o usuário  faz alguma coisa no browser (clica num link, clica no botão "Enviar", digita
            uma URL, etc.) e espera-se que esta ação envie a solicitação para um servlet especifico
            (ou outra aplicação como o JSP) que você construiu. Como isso pôde acontecer?


            Para cada um dos seguintes procedimentos, considere os prós e os contras.


       o    Escrever o mapeamento direto no código da sua página HTML. Em outras palavras, o
             cliente está usando o caminho exato e nome do arquivo (de classe) do servlet.

                           PRÓS:

                           CONTRAS:



       •    Usar as ferramentas   do fabricante do seu Container para criar o mapeamento:

                           PRÓS:

                           CONTRAS:



        •   Usar algo como uma tabela de propriedades para armazenar os mapeamentos:

                           PRÓS:

                           CONTRAS:




                                                                             você está                  45
o mapeamento      URLS para senl/ets



Uttt servlet pode ter fRÊS notttes
Um servlet tem um nome do caminho para o arquivo, obviamente,
como classes/registrationlSignUpServlet.class     (um caminho para um
arquivo de classe real). O legítimo desenvolvedor da classe do servlet
escolhe o nome da classe (e o nome do pacote que define parte da
estrutura de diretórios), e o local no servidor define o nome completo
do caminho. Mas qualquer pessoa que distribua o servlet também
pode atribuir a ele um nome de distribuição especial. Um nome de
distribuição é simplesmente um nome interno secreto, que não precisa
ser igual ao nome da classe ou do arquivo. Ele pode ser igual ao nome
da classe (registration.SignUpServlet)    ou o caminho relativo para
o arquivo da classe (classes/registrationlSignUpServlet.class),  mas
também pode ser algo completamente diferente (como EnrollServlet).
Pra terminar, o servlet tem um nome público de URL - O nome
que o cliente conhece. Ou seja, o nome codificado no HTML de
modo que, quando o usuário clicar em um link, que se supõe que vá
àquele servlet, este nome público de URL é enviado ao servidor na
solicitação HTTP.




                                                 ()
                                                  o




Nome da URL                         Nome interno secreto                 Nome do arquivo
conhecido pelo cliente              conhecido pelo                       verdadeiro
                                    distribuidor
O cliente vê uma URL que liga                                            A classe do servlet do
a um servlet (no HTML), mas         O distribuidor pode criar            desenvolvedor tem um nome
não sabe realmente como esse        um nome que somente seja             completamente qualificado,
nome de servlet mapeia para         conhecido apenas por ele e           que inclui os nomes da classe e
verdadeiros arquivos e diretórios   pelos outros que participam da       do pacote. O arquivo de classe
de volta ao servidor. O nome        área operacional de verdade.         do servlet possui um nome
público de URL é um nome            Este também é um nome                de arquivo e caminho real,
falso, criado para os clientes.     falso, criado somente para a         dependendo de onde o pacote
                                    distribuição do servlet. Ele não     com a estrutura de diretórios
                                    precisa coincidir nem com a          resida no servidor.
                                    URL pública usada pelo cliente,
                                    NEM com o nome do arquivo
                                    verdadeiro ou o caminho da
                                    classe do servlet.

46 capítulo 2
arquitetura de alto nível




Nossa, é interessante como todo mundo
   quer expressar Sua criatividade e
aparecer com seus próprios nomes para
 se referir à mesma coisa. Mas por que
  será?! Realmente? Por que nós todos
não usamos o único, real e inconfundível
            nome do arquivo?


              D
              o



                              Mapear O nome dos
                              servlets aumenta a
                              flexibilidade e a segurança
                              da sua aplicação.
                              Pense nisso.

                              Então, você escreveu direto no código o caminho
                              verdadeiro e o nome do arquivo em todos os JSPs e
                              nas outras páginas HTML que usam aquele servlet?
                              Ótimo. Agora, o que acontecerá quando você
                              precisar reorganizar sua aplicação e, possivelmente,
                              mover coisas para diferentes estruturas de
                              diretórios? Você realmente quer forçar todos
                              que usam aquele servlet a conhecer (e seguir
                              eternamente) esta mesma estrutura de diretórios?
                              Mapear o nome, em vez de codificar o verdadeiro
                              caminho e nome do arquivo, garante-lhe
                              flexibilidade ao mover as coisas. E evita aquele
                              pesadelo na hora de acompanhar e mudar o
                              código do cliente que aponta para a antiga
                              localização dos arquivos dos servlets.
                              E quanto à segurança? Você realmente quer que
                              o cliente saiba exatamente como é a estrutura
                              no seu servidor? Você quer que eles, digamos,
                              tentem navegar diretamente para o servlet, sem
                              passar pelas páginas e formulários corretos?
                              Pois, se o usuário final puder ver o caminho
                              verdadeiro, ele pode digitá-lo em seu browser e
                              tentar acessá-lo diretamente.




                                                               você está             47
o mapeamento       do servlet no DO



Usando o VeploytMettt Vescriptor para tMapear as URLs aos servlets
Quando você for distribuir seu servlet em seu Container, você criará um documento XML,
razoavelmente simples, chamado Deployment Descriptor (DD), para informar ao Container como
executar seus servlets e JSPs. Embora você use o DD para outras tarefas além de simples mapeamento
de nomes, você usará dois elementos XML para mapear as URLs aos servlets - um para mapear o
nome público de URL conhecido pelo cliente para o seu próprio nome interno, e o outro para mapear
seu próprio nome interno para um nome de classe completamente qualificado.



Os dois elementos do DD para mapeamento de URL:
        <servlet>
        mapeia o nome interno para o nome da classe completamente qualificado



         <servlet-mapping>
        mapeia o nome interno para o nome público de URL
                                                                                                                       ,
                                                                                                            () elelJe'l-f.(j
                                                                                                            'IalJe:> e IIsad"
                                                                                                            IIIJ efew,fl'1+1J

                                                                                                            li! 1Iw,




               "I''''"S''
        dtll$ sel'vle-f.s.     p.n"r
                                  '            (
                                                ~
                                      <web-app            ...>
               <sfl'vle+:>
          4(jC{;j'l+4/~el'l'        fi <servlet>
                                         <servlet-name>Internal                                name    l</servlet-name>                 I~sel'e

                   de                   </servlet>               ~{;ji'J{;jw,(!
                                       <servlet>
                                          <servlet-class>foo.Servletl</servlet-class>
                   flJ                   <servlet-name>Internal       name 2</servlet-name>
                                          <servlet-class>foo.Servlet2</servlet-class>
                                        </servlet>


                          •            • ••••••••••...........••....••••••••..•••••••••                                          'Ii!

                                             <servlet-name>Internal    name l</servlet-name>                                      c~ss
                                             <url-pa~tern>/Publicl</url-pattern>
                   tl            </servlet-mapplng>
             ti e1ew,e'l+/<serVlet-maPPlng>             ~
             lisa 'ItI,
                                                 IS+tlftl                                         Ó



                      I.IIP~
                          '~                            li!: ti I'jt:;w,f! t
                     ftl,I'4           <servlet-mapping>
                                          <servlet-name>Internal                               name    2</servlet-name>
                                          <url-pattern>/Public2</url-pattern>
                                       </servlet-mapping>
                                                             ;              I
                                      </web-app>             Z.                      I.IS«I' WtlJcllil'JS   1'10


48             2
arquitE1tW"a   de alto nível



Mas espere!       retlt tltais coisa que você       pode fazer COtlt
                                                                   o         UU

Além de mapear URLs aos servlets verdadeiros, você pode
usar o DD para personalizar outros aspectos da sua aplicação,
incluindo atribuições de segurança, páginas de erro, bibliotecas
de tags, informações sobre a configuração inicial e, se for um
servidor J2EE completo, você pode inclusive declarar que           o de,p19fment    de,SCtlpt9l"
estará acessando enterprise javabeans específicos.                 (DD) 9te,l"e,ce,um
Não se preocupe ainda com os detalhes. O ponto crucial,
por enquanto, é que o DD oferece uma manéira de
                                                                   me,céUllsm9 ~·doolfltad9"
modificar declaradamente a sua aplicação, sem alterar o
código- fonte!                                                     pata a cust9m1zayã9 das
Pense nisso ... significa que mesmo aqueles que não são            suas apl'lcély9e,s, se,m t9Cm'
programadores Java podem personalizar sua aplicação Java,
sem precisar arrancá-Io das suas férias ao sol.                    n9 c9dlg9--t9nte,!

        Nã9   ex'íSbiom

pethuntélS         Idl9téls
r:   Estou confuso. Olhando para o DO,
você ainda não tem nada que indique o
                                                                    Os Benefícios      do DO

                                                                     Reduz a necessidade de alteração
verdadeiro nome do caminho do servlet!
                                                                     do código-fonte que já foi testado.
Apenas diz o nome da classe. Isto ainda
não responde à pergunta de como o                                    Permite que você ajuste os recursos
Container usa aquele nome de classe para                             da sua aplicação, mesmo que você
encontrar um arquivo de classe de um                                 não possua o código-fonte.
servlet específico. Existe ainda UM OUTRO
                                                                     Permite que você adapte sua
mapeamento em algum lugar que diga que                               aplicação de acordo com diferentes
tal nome da classe, mapeia para tal arquivo
                                                                     recursos (como bancos de dados),
em tal lugar?
                                                                     sem ter que recompilar e testar
                                                                     nenhum código.
1: Você   prestou atenção. Você está certo,                         Facilita a manutenção das
pois colocamos apenas o nome da classe                               informações dinâmicas sobre
(totalmente qualificada para incluir o nome do                       segurança, tais como listas de controle
pacote) no elemento <servlet-class> . Isso é                         de acessos e funções de segurança.
porque o Container tem um lugar específico
                                                                     Permite que aqueles que não
em que procurará por todos os servlets para os
                                                                     sejam programadores modifiquem
quais você especificou um mapeamento no DO.
                                                                     e distribuam suas aplicações,
Aliás, o Container usa um sofisticado esquema
                                                                     enquanto você dá mais atenção
de regras para encontrar um par entre a URL                          às tarefas mais interessantes. Por
que chega da solicitação do cliente, e uma
                                                                     exemplo, se o seu guarda-roupas
classe Java real localizada em algum lugar do                        está apropriado para uma viagem
servidor. Mas entraremos neste assunto em                            ao Havaí.
um capítulo mais adiante (em Distribuição). Por
enquanto, o mais importante que você deve
lembrar é que você pode fazer isto mapeando.



                                                                                                      ••       49
Bob   se corresponde   no site



História: Job Cot1strói Uit Site de Et1cotrtros
Marcar um encontro está dificil hoje em dia. Quem tem
tempo, quando tem sempre um outro disco para ser
desfragmentado? Bob, que quer uma fatia desse mercado
virtual (o que sobrou, pelo menos), acredita que criar um
site de encontros específico para nerds é o seu passaporte
para deixar o emprego Dilbertiano1 que ele tem agora.
O problema é que Bob já é um gerente de software há
tanto tempo, que ele está, digamos, por fora das práticas
atuais de engenharia de software. Mas ele conhece
alguns conceitos básicos, um pouco de Java e já leu um
pouco sobre servlets. Ele então faz um projeto rápido e
começa a escrever o código ...




                                                             Input your state
                                                             Handle ~I             ~

                              GeekDates                      Age
                                                             OS ~I
                                                                   ~!

                                                                                   ~
                                                                                       _




                                                             Attributes   ~!           _


                                                             Exceptionsl~          _




                           Refactor                                     DQLQuery
                           Modify your profile:

                            [profile hereJ


                                                                        I===~-===
                                                                            __




50 caplitulo 2
arquitetura de alto nível



Ele cotMeça a construir utMa porção de servlets ... UtM

para cada página
Ele pensava em ter um único servlet, cheio de testes if, mas
decidiu que servlets separados seriam mais 00 - cada servlet
deveria ter uma responsabilidade, como a página de questionário,
a página de cadastro, a página com os resultados da busca, etc.
Cada servlet terá toda a lógica de negócio que precisa para
modificar ou ler o banco de dados e exibir o HTML de volta com
os dados da resposta do cliente.


   II    declarações                            de import

   public           class                DatingServlet              extends           Http$ervlet                    {

        public             void            doGet(HttpServletRequest      request,
                                             HttpServletResponse     response)
                                             throws IOException     {

           II
           a lógica de negócio entra aqui,
   dependendo
           II
           do que este servlet deve fazer
           II
            (escrever para o banco de dados,                                                       fazer            a query,   etc.)

           PrintWriter                           out = response.getWriter();

           II
           escreve a página HTML dinâmica
        out.println( ~something really ugly                                                        goes
   here") ;




                 101HI1
                 IonOI
                 1010100001.0
                 lQHllOO
                 010101
                                                                                    101101
                                                                                    lOllOl
                                                                                    1010100001.0
                                                                                                                                f) servle-l-fa~ 4 ?l.le
                                                                                    10111100
                 lClOlOl
                 lClOlOlO
                                                                                    (110101.
                                                                                    101C101
                                                                                                                                ele precise parí3.prtlCe:ssal" a
                 1001010101
                                                                                    10101010

           InputDQLServlet
                                                                                    1001010101
                                                                                                                                S4IiCl·h{i4 (C4"M4/;,seri'r (J~
                                                                                  SignupServlet        101101
                                                                                                       101101
                                        DoDQLQueryServlet                                                                       Jat/4 4(J prtIC(Jrlu' #tt!

        [J
                                                                                                       WIOIOOOOIO
                                                                                                       1010100
                                                                                                       010101
                                                                                                       101(1101                 Je: t/aJ4s) e:

                                                                                                                                    ,                    ,
                                                                                                       1.0101010
                                                                                                       1001010101
           web
                                                                                                   Accept 19nup ervlet          1/1714 #tarespt!#tse
                                                                                                                                  ,
    server/container


                          10110l                                                                                                1ãJa a 145,éo.Je
                          101101
                          10101000010
                                                                                                                                pa51;,a Je respal1se

                                                                                                                                  ,
                          1010100
                          010101
                          1010101
                          10101010
                          1001010201
                                                                       AcceptProfiJeChangesServlet                              J~ clte#t+e
                   MainPageServ            et     InputProfileChangesServJet
                                                                                                                                c~Jij~ t/a




                                                                                                                                        você está aqui ~       51
80b adiciona JSPs



Mas fica horrível e ele acrescetrta os JSPs
Aquelas declarações printlnO irritantes para saída
de resposta se tomam realmente terríveis muito
rapidamente. Ele lê sobre os JSPs e decide fazer                                                                       o design deste  JSP está muito
com que cada servlet faça qualquer que seja a                                                                            tranqüilo. Agora. o código do
                                                                                                                        servlet está mais claro... cada
lógica de negócios de que ele precise (query no                                                                         servlet roda sua própria lógica
                                                                                                                       e chama um JSP específico para
banco de dados, inserir ou atualizar um novo                                                                          tratar o HTML que será usado na
registro, etc.) e encaminhe a solicitação para                                                                         resposta, separando a lógica de
                                                                                                                          negócio da apresentação.
um JSP, que fará o HTML para a resposta.
Ele também separa a lógica de negócio da
apresentação ... e já que ele andou lendo sobre
desi~n, ele sabe que separar as preocupações é
um Otimo Negócio.
    II     declarações           de import

   public           class    DatingServlet           extends             HttpServlet                            {

         public void doGet(HttpServletRequest                                     request,
               HttpServletResponse   response)
                        throws IOException   {

               II   a lógica de negócio entra aqui,
               II   dependendo  do que este servlet deve fazer
               II    (escrever para o banco de dados, fazer a query,                                                   etc.)
               II   envia a solicitação   a uma página JSP específica
               II   em vez de tentar exibir o HTML
               II   junto     com os dados         de saída
           }




                                                                                          «._'.•
                                                                                          .-
                                                                                                1.··'.,'·····




                                                                       AcceptPrOfileChanlj.~~.sSe~lel
         InpulSignupJSP     AcceplSignupJSP   InputProfileChangesJSP            AcceplProfileChangesJSP             MainPageJSP     InpulDQLJSP      DoDQLQueJYJSP




                                                                                                                                     DoDQLQueryJSP




                                                          /       lJib ib                                                 "'''J)        "
          O cllf!l';.f.efl"eel';ct.e ó lilI"IYoVI!J.I"I4J '4t1e~7 e c/tcl). 11t!J
                                                       !I'4L                   bI:J.f:aõ õ I~ • ís.f.e
          el';vià tlIYo4 slJliél+ali" Hrrp       POSrfal"4 a D"J)$L$vel"].        O sel"vtJ,,1" ",ell ct.alYofJ.

          f!I1CalYol;"t.aJ4 J-sP o.fN'prltJ.JlJ, O ,)-sp CtIJl1s+rfJta N:sffJl1se Hrl..-tLõliCt+fJ.j'iõ é
          fJ serv1e+; ó servle+ execv+a a y,tlerí 1';" btJ.l1ctIJ JfJ.Jós e f!11+'iõfJ.
                          aõ                                     ~e                      s e t.l Jev()/ve.

52 capitulo 2
arquitetura de a/to nível



Mas etrtão o seu aiMigo diz: "Você ESr Á
usando MVC, certo?»
Kim quer saber se o serviço de encontro pode ser acessado
a partir de uma aplicação GUI Swing. Bob diz: "Não,
eu não pensei nisso." Então, Kim fala: "Bem, isso não é
problema porque eu estou certo de que você usou MVC,
então nós podemos preparar num instante um cliente GUI
Swing, que possa acessar as classes lógicas de negócio."
Bob: "Glup."
Kim: "Não me diga ... você não usou MVC?"

Bob: "Bem, eu separei a apresentação da lógica de
negócio ..."
Kim: "Já é um começo ... ma~-níe         adivinhar ... a lógica
do seu negócio está toda dentro de servlets?!"
Bob percebe, rapidamente, porque ele se tomou gerente.
Porém, ele está determinado a fazer isto corretamente. Então,
ele pede a Kim uma explicação bem rápida sobre MVC.



Com o MVC a lógica de negócio
não fica apenas separada da
apresentação ... ela sequer sabe que
EXISTE uma apresentação.

A essência do MVC é que você pode separar a lógica de
negócio da apresentação, mas ponha algo entre elas para que a
lógica de negócio possa agir sozinha como uma classe Java
reutilizável, sem precisar saber nada sobre a view.
Bob estava quase lá, separando a lógica de negócio da
apresentação, mas sua lógica ainda tem uma forte ligação
com a view. Ou seja, ele misturou a lógica de negócio no
servlet, o que significa que ele não poderá reutilizar sua
lógica em outros tipos de view (como um GUI Swing ou
até mesmo uma aplicação wireless). Sua lógica está presa
em um servlet, quando deveria estar em uma classe Java
stàndalone que ele pudesse reutilizar!




                                                                  você está              53
o padrão de design MVC


    o Padrão de Projeto Model~View~ComrollerMVc) cot1serta isto
                                           (

    Se Bob tivesse entendido o padrão de design
    MVC, ele saberia que a lógica de negócio não
    deveria estar inserida em um servlet. Ele teria
    percebido que com a lógica de negócio embutida        o M9del*VleW*C9ntt91let
    no servlet, ele ficaria "em maus lençóis" caso
    algum dia tivesse que acessar o serviço de encontro   (MVC) tet1tél él 1991célde neg9c19
    de uma maneira diferente. Como na aplicação           t9tél d9 set"let e él 09190élem
    GUI Swing. Nós falaremos mais sobre o MVC (e
    outros padrões) mais adiante, mas você precisa de     um ~~M9de19" - umél éllrt'lgél
    um rápido entendimento agora, pois o tutorial que
    construímos no final deste capítulo usa o MVC.        délSseJél"él, plqnél e teutJ'l1zá"e1.
    Se você já está familiarizado com ele, então você     O lVl9de19 é él 09mblnélyã9 d9S
~      sabe que o MVC não é específico para servlets
    e JSPs - a clara separação da lógica de negócio da    déld9S de neg9c19 (09m9 9 e5téld9
    apresentação é igualmente válida para qualquer
    outro tipo de aplicação. Porém, com aplicações
                                                          de um 0éltt1nb9 de 09mptéls) e
    web é realmente importante, porque você nunca         95 mét9d95 (tegtél5) 'Lue 9tetélm
     deveria considerar que sua lógica será acessada
     apenas da web! Estamos certos de que você            nesses déld9S.
     trabalha neste negócio há tempo suficiente para
     saber que a única garantia em desenvolvimento
     de software é: a especijicação sempre muda.


     o MVC no mundo Servlet                               & JSP
                                                              CONTROLADOR
                                                              Retira da solicitação do usuário OS
                                                              dados de entrada e interpreta o que
                                                              eles significam para o modelo.
                                                              Obriga o modelo a se atualizar e
                                                              disponibiliza o estado do novo modelo
                                                              para a view (o JSP).

     VIEW                                                              MODELO

     Responsável pela                                                  e o estadoverdadeira lógica
                                                                       Abriga a do modelo. Em
     apresentação. Ela                                                 outras palavras, ele conhece
     recebe o estado
     do modelo do                                                      as regras para obtenção e
                                                                       atualização do estado.
     Controlador (embora                                               O conteúdo de um Carrinho de
     não diretamente; o                                                Coml?ras (e as regras sobre o
     Controlador põe os                                                que fazer com isso) seria parte
     dados do modelo em um         Vlew                                qo Modelo no MVC.
     lugar onde a View possa                                           E a única parte do sistema
     encontrá-Io). Também                                              que se comunica com o
     é a parte que recebe                                              banco de dados (embora ele
     os dados de entrada                                               provavelmente use outro
     do usuário que volta ao                                           objeto para a verdadeira
     Controlador.                                                      comunicação com o DB, mas
                                                                       guardaremos este padrão
                                                                       para mais tarde ...).

     54 capítulo 2
arquitetura de alto nível



Aplicando o padrão MVC na aplicação de encontros
Pois bem, Bob sabe o que precisa fazer. Separar a lógica de
negócio dos servlets e criar urna classe Java normal para
cada um ... para representar o Modelo.
Com isso, o servlet legítimo será o Controlador, a nova
classe para a lógica de negócio será o Modelo e o JSP será
a View.




             1111101                lGllCl
                                    lGUOJ. -0/
             10101MClllll           111101001l0>-0
                                    '-''I1G100
             010>-01                01010 1
             1"101<1l




                        i
          In~~;~::pModcl     (~~Modm




                                                                         AcceplProfileChangesServlet                                       DoDQIQueryServlel




 '-""~f1~
       '"-~
      InpulSignupJSP        AcceplSignupJSP          InputProfileChangesJSP
                                                                                          ~
                                                                                  AcceplProfileChangesJSP   MainPageJSP
                                                                                                                            :.
                                                                                                                            <'"_>_<ll>




                                                                                                                              .
                                                                                                                            """"'"
                                                                                                                            </10»1,




                                                                                                                           InpulDQLJSP
                                                                                                                                       -"-.-:'-.
                                                                                                                            <'rI_,,",,"-
                                                                                                                            _.....

                                                                                                                           Ej,.
                                                                                                                                                     ~=
                                                                                                                                                     ••..._b";>
                                                                                                                                                     ~
                                                                                                                                                     Ej~'
                                                                                                                                                     'J>ooo'
                                                                                                                                                      (},,,,,,




                                                                                                                                                   DoDQLQueryJSP
                                                                                                                                                                 -.::."?"




                                                                                                                                                     "li"'''''''''''
                                                                                                                                                           •...

                                                                                                                                                                 ;.1




                                                                                                                          você está                                         55
sim, mas isso é um bom             ?


Neste tMotMemo, seu atMigo KitM dá utMa olhada
Kim aparece e diz que embora esse SEJA um projeto
MVC, ele é ruim. Claro, a lógica de negócio foi colocada
em um Modelo, e os servlets atuam como Controladores
trabalhando entre os Modelos e as Views, para que o
Modelo possa be brain-dead about the Views2• Isso tudo é
muito bom. Mas olhe para todos aqueles pequenos servlets.     Que projeto mais fraco! Observe
O que elesfazem mesmo? Agora que a lógica de negócio           todos estes códigos duplicados
                                                               em cada servlet. Você tem que
está "guardada" com segurança no Modelo, o Controlador
                                                               adicionar o mesmo código geral
do servlet não está fazendo nada além de alguns trabalhos     de aplicação, como segurança, na
comuns para esta aplicação e, ah sim, ele atualiza o Modelo          maioria dos servlets.
e coloca a View para funcionar.
Mas o pior é que toda aquela simples lógica de aplicação                       o
                                                                               o
é repetida em cada um daqueles malditos servlets! Se
algo requerer alteração, terá que ser alterado em todos os
lugares. A manutenção de um trem destroçado está por vir.
"Sim, eu não gostei muito deste código duplicado", diz
Bob. "Mas o que mais eu posso fazer? Naturalmente,
você não quer que eu ponha tudo em um simples servlet
novamente? Como isso funcionaria?"




56
de a/to nível




Existe utMa resposta?


              Será que o Bob dev ria volta
               para apenas um Controlador
              de servlet para evitar código
             duplicado? Isso seria um modelo
             00 ruim, pois os servlets estão
                realmente fazendo coisas
               diferentes? O Keanu Reeves
                    luta mesmo Kung Fu?

                                   D
                                   o




          EXERCITE SUA MENTE

          Deixe isto para você meditar. É o que nós vamos fazer.
          O que você acha? Você sabe a resposta? EXISTE
          uma resposta? Você concordaria com Bob e
          deixaria os servlets como eles são, ou colocaria
          o código dentro de um único Controlador de
          servlet? E se você usar mesmo apenas um
          Controlador para tudo, como ele saberá qual
          Modelo e View chamar?

          A resposta para esta pergunta não virá antes
          do final deste livro, então pense nisso por
          alguns momentos e depois coloque numa
          thread em background na sua mente ...




                                                                   você está aqui...    57
capítulo 2 - reflexão




•   Usando o MVC no mundo servlet & JSP, cada
    um destes três componentes (JSP, classe Java e
    Servlet) desempenha um papel MVC. Circule
    "M", "V" ou "C", dependendo de qual parte do
    MVC o componente executa. Circule apenas uma
    letra por componente.


                                       M              O Container oferece à sua aplicação web
                                       V              suporte em comunicações, gerenciamento
                                                      do ciclo de vida, suporte a multithread,
                                       C              segurança declarada e suporte para JSPs,
                                                      para que você possa se concentrar em sua
            J'SP                                      própria lógica de negócio.

                                                      O Container cria um objeto request
                                       M              e response que os servlets (e outras

                                       V              partes da aplicação) podem usar para
                                                      conseguir informações sobre a request e
                                       C              enviar dados ao cliente.

         non-servlet                                  Um servlet típico é uma classe que
         J'ava c1ass                                  estende o HttpServlet e sobrepõe
                                                      um ou mais métodos de serviço que
                                                      correspondem aos métodos HTTP
                                       M              ativados pelo browser (doGetO,
                                       V              doPostO, etc.).

                                       C              O distribuidor pode mapear uma classe de
            servlet                                   servlet para uma URL, que o cliente pode
                                                      usar para solicitar tal servlet. O nome
                                                      pode ser completamente diferente do
                                                      verdadeiro nome do arquivo da classe.




8    O que as letras MVC representam
     design MVC?
                                       no padrão de


    M significa                                          _
    V significa                                          _
    C significa                                          _




58 capítulo 2
arquitetura de alto nível




         Ap9nte seu lápis
                                  Quem é o responsável?
                                 Preencha a tabela abaixo, indicando se é o servidor, o container ou um
                                 servlet o mais responsável pela tarefa listada. Em alguns casos, mais
                                 de uma opção pode ser verdadeira para a tarefa especificada. Para
                                 justificar, acrescente um breve comentário descrevendo o processo.




Tarefa                                      Servidor            Container           Servlet

dinâmicos HTTP
response objetos request e no DD
elemento <servlet-class> response
solicitações
 Cria os
Converte HTTP no de vida
Gerencia umciclos DD conteúdos uma
Encontra URLs  objeto response em
Conhece onova tbread
Tem uma os preparo para o com
Iniciaum nome que coincide objeto oas
Coordena referência de para tratar
        uma
Acrescenta objetos serviceOe response
Apaga os método requestobjeto response
Chama o o HTML ao




                                                                             você está aqui    li>   59
servlet   e exercício   DD




                                          Ímãs         de G-ela-del'téL
                                          Um servlet funcionando e o seu DD são misturados em
                                          uma frigideira. Você é capaz de unir os pedaços de código
                                          recortados à direita com a listagem incompleta à esquerda,
                                          a fim de criar um servlet e um DD que funcionem e cuja
                                          URL termine com /Dice? É possível que alguns códigos à
                                          direita não sejam usados!


- Servlet

   public     class                   extends        HttpServlet                 {


     public     void doGet(




                        throws   IOException    {




          String dI      Integer.toString((int)  ((Math.random()*6)+I»;
          String d2      Integer.toString( (int) ((Math.random() *6) +1»;

          out.println("<html>   <body>" +
             "<hl align=center>HF's   Chap 2 Dice Rol1er</hl>"                               +
             "<p>" + dI + " and " + d2 + " were rolled" +
             "</body> </html>");




-DD
                                                      teS+-4 #'/';6     é 4 +-~de         det'+-vt'fI.
   <web-app                                     ()   f!;cf!iIP<pic   c<!IlJY>le+-ô ftI1Cc#'/+-Nr     se #,/c flplfJ.1
                                                            IS+(j      #'/';tJ   fJ.fe+a (; e;cet'c:C/~).




 </web-app>




60   capítulo 2
arquitetura de alto nível




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



                             public    void service(
    </url-pattern>




                      <servlet-name>
                                                  ServletRequest      requeSt'



PrintWriter   out
                     response.getWriter();
                                                       HttpServletResponse         response)




                           <servlet-mapping>


                                                       ServletResponse    response,



                              <servlet-name>                    </servlet-class>



                                             HttpServletRequest     request,




                                             PrintWriter   out     request.getWriter() ;



                              </servlet-name>
                                                        <url-pattern>


                                </servlet>
     <servlet-c1                                         </servlet-mapping>




                                                                       você está aqui ~        61
Responsabilidade     - solução do exercícío




       Tarefa                                       Servidor web    Container             Servlet
                           classe uma               encaminhar ao   thread antesservlet
                                                                    Logo parachama
                                                                    o partir quem
                                                                    responsedos
                                                                    a
                                                                    Inicia que ao
                                                                    asservlet
                                                                                  de
                                                                    Usa-o aumaservlet.
                                                                    Sabe de)correto
                                                                    service(     falar
                                                                    é finalizado.você
eto                        exibir pública
                           qualquer coisa                           Quando (eHTTP
                                                                    do entrega
                                                                    outros o
                                                                    service
                                                                        cliente.          dinâmico para o
      chamarstream de Usa-o para
      servlet. browser
      cliente. a ) ) ou
      Container.
      para o request. o
      com
      iniciar
      O Container
      response.
      gera encontrar
      o doGet( objetos
      doPost(
       Cria método
                           response
      Para aos othread. request e response   O conteúdo
      Aí o
      Chama método




      62 capítulo 2
arquitetura de alto nível




                             C9nt1nuac;ã9da S91uc;ã9
                             d9s Exel'cÍc9S...
- Servlet
 irnport javax.servlet.*;
 irnport javax.servlet.http.*;
 irnport java.io.*;

 public   class                  xtends   HttpServlet


                           HttpServletRequest


                           HttpServletResponse




     PrintWriter   out


     String   dI   Integer.toString((int)    ((Math.randorn()*6)+I»);
     String   d2   Integer.toString((int)    ((Math.randorn()*6)+I»);

     out.println("<htrnl> <body>" +
        "<hI align=center>HF's  Chap 2 Dice Roller</hl>"        +
        "<p>" + dI + " and " + d2 + " were rolled" +
        "</body> </htrnl>");




-DD-------------------




                                                    </servlet-narne>

                                                    /url-pattern>




                                                                     você está aqui ~   63
Dois objetos, dois blocos



Ul1 PeploYl1ettt Pescriptor      (PP) "funcionando»
Não se preocupe com o que isto realmente significa (você verá
isto em outros capítulos e fará testes). Aqui, nós quisemos apenas
demonstrar um DD web.xml que funciona de verdade. Ficaram
faltando muitos pedaços a serem ínseridos na tag de abertura <web-
app> nos outros exemplos deste capítulo. (Você pode perceber
porque nós geralmente não íncluímos isso em nossos exemplos.)


A forma que geralmente mostramos no livro
     <web-app     ... >


       <servlet>
                          <
         <servlet-name>Ch3    Beer</servlet-name>
         <servlet-class>com.example.web.BeerSelect</servlet-class>
       </servlet>

       <servlet-mapping>
         <servlet-name>Ch3    Beer</servlet-name>
         <url-pattern>/SelectBeer.do</url-pattern>
       </servlet-mapping>

     </web-app>




A forma que REALMENTE funciona                          L
     <web-app xmlns=''http://java.sun.com/xml/ns/j2ee''
          xmlns:xsi~''http://www.w3.org/2001/XMLSchema-instance''
          xsi:schemaLocation~''http://java.sun.com/xml/ns/j2ee/web-app   2 4.xsd"
         version="2.4rT>

       <servlet>
         <servlet-name>Ch3    Beer</servlet-n~me>
         <servlet-class>com.example.web.BeerSelect</servlet-class>
       </servlet>

       <servlet-mapping>
         <servlet-name>Ch3    Beer</servlet-name>
         <url-pattern>/SelectBeer.do</url-pattern>
       </servlet-mapping>

     </web-app>




64                2
arquitetura de a/to nível



Cot10   o J!EE cabe "isso tudo
                                                            Um set"Id9t de aplIcac;ã9
O Java 2 Enterprise Edition é meio um "superspec"
- ele incorpora outras especificações, incluindo a          J2EE IncluI tant9 9 C9ntmnet
é para o Web Container.2.4 e a especificação JSPJ2EE Isto
especificação Servlets Porém, a especificação 2.0. 1.4      Web7 C9m9 9 C9ntain et EJB.
                                                              1              "
também inclui a especificação Enterprise JavaBean 2.1
para o Container EJB. Em outras palavras, o Container       O ]9'mcat   é um C9ntmnet
web é para EJB é para componentes de negócios.e o
Container componentes web (Servlets e JSPs)                 Web7 mas N11.0 um set"Id9t
                                                                       A



Um servidor ter aplicação Contalller web, como um
o J2EE deve de tanto um tota~ente compatível com            de apllcadi9 J2EE c9mplet9.
                                                                     T
Contai~er EJB (alé~ de outras coisas, c?mo uma JNDI
e uma lmplementaçao JMS). O Tomcat e apenas um
                                                            Um set"Id9t J2EE 1.4 IncluI
especIflcaçao J2EE que se referem acordo às :porções da
Cont~iner -:eb! Embora esteja de ao Contamer web.           a especltlcadi9 Set"let
                                                                         T                2.4   7

O Tomcat é um Container web e não uma aplicação             a especltlcac;ã9 JSf 2. o e a
J2EE completa, pois ele não possui um Container EJB.
                                                            especltlcac;ã.9 ElB 2.1.

   iJ2EE     Application    Server




r:      Então o Tomcat é um Container
web standalone ... isso significa que
                                                      o Resin. Geralmente, os Containeres
                                                      web standalone são configurados para
também existem Containeres EJB                        trabalharem com um servidor HTTP (como o
standalone?                                           Apache), embora o Container Tomcat possa
                                                      atuar como um servidor HTTP básico. Mas,
                                                      para a função de servidor HTTP, o Tomcat
                                                      nem se aproxima da robustez do Apache.
1:     Antigamente, digamos, no ano                  Por isso, as aplicações web não-EJB
2000, você encontrava servidores J2EE                 mais comuns usam o Apache e o Tomcat
completos, Containeres web standalone e               configurados juntos - com o Apache como
Containeres EJB standalone. Hoje, porém,              Servidor HTTP e o Tomcat como Container.
quase que todos os Containeres EJB                    Alguns dos servidores J2EE mais comuns
são parte de servidores J2EE completos,               são o Weblogic da BEA, o JBoss AS de
embora existam ainda poucos Containeres               código aberto e o WebSphere da IBM.
web standalone, incluindo o Tomcat e
                                                                          você está aqui ~          65
Minitutorial do MVC




Criando e distribuindo uma aplicação Web MVC. Chegou a
hora de colocar a mão na massa e escrever um formulário HTML,
um controlador de servlet, um modelo (classe Java simples),
um deployment descriptor XML e uma view em JSP. É hora de
criar, distribuir e testar. Antes, porém, você deverá configurar seu
ambiente de desenvolvimento     - uma estrutura de diretórios para o
projeto que esteja separado da sua aplicação real distribuída. Em
seguida, você terá que configurar o seu ambiente de distribuição,
de acordo com as especificações    do servlet e do JSP, e as
exigências do Tomcat. A partir daí, você estará apto a começar a
escrever, compilar, distribuir e executar. Concordo, construímos
uma aplicação bem pequena. Porém, quase NÃO existe aplicação
que seja tão pequena e use o MVC. Afinal, a aplicação pequena
de hoje é o sucesso da internet de amanhã ...

                                                               este    é um   novo capítulo.   õl
objetivos do exame oficial da Sun




                                    o
Distribuição Aplicação Web                             Notas sobre a Abrangência:

2.1 Construir a estrutura de arquivo e diretórios de   Todos os objetivos nesta seção são abordados
    uma aplicação que possa conter (a) conteúdo        completamente no capítulo sobre Distribuição;
    estático, (b) páginas JSP, (c) classes servlet,    aqui daremos apenas uma primeira olhada. Este
    (d) o deployment descriptor, (e) bibliotecas de    é o único capítulo com um tutorial completo, do
                                                       início ao fim. Portanto, se você pulá-Io, poderá
    tags, (f) arquivos JAR e (g) arquivos de classe
                                                       ter problemas mais tarde, quando for testar
    Java. Descrever como proteger os arquivos de
                                                       alguns outros exemplos nos próximos capítulos
    recursos do acesso HTTP.
                                                       (não repetiremos cada detalhe novamente).
2.2 Descrever o propósito e a semântica de cada        Assim como nos anteriores, você não precisará
    um dos seguintes elementos do deployment           se preocupar em memorizar o conteúdo deste
    descriptor: error-page, init-param, mirne-         capítulo. Apenas vá e faça.
    mapping, servlet, servlet-class, servlet-
    mapping, servlet-name e welcome-file.
2.3 Construir a estrutura correta para cada um
    dos seguintes elementos do deployment
    descriptor: error-page, init-param, mime-
    mapping, servlet, servlet-class, servlet-name
    e welcome-file.




68 capítulo 3
praticando com o MVC



Vattos cot1struir utta (pequetW aplicação de verdade
Nós vimos a função de um container, falamos um pouco sobre
deployment descriptors e demos uma primeira olhada na arquitetura do
MVC Model 2. Mas você não po.de ficar aí sentado e lendo o dia todo -
agora é hora de realmente jazermos alguma coisa.


Os quatro passos que seguiremos:
                O Revisar as views doe usuário (o quedeo
                  browser mostrará)    a arquitetura
                    alto nível.




     8   Criar o ambiente de desenvolvimento que usaremos
         neste projeto (que você poderá usar para qualquer
          outro exemplo no livro).



                                                                             Gl



                       e   Criar o ambiente de distribuição que
                           usaremos neste projeto (que você
                           poderá usar para qualquer outro
                            exemplo no livro).
                                                                         i~~
                                                                        f~
                                                                        _~    _~    --...01_   ~




                o   Desenvolver e testar repetidas vezes os vários
                     componentes de nossa aplicação. (Tudo bem,
                     isto é mais uma estratégia do que um passo.)


                    Nota: Nós recomendamos desenvolvimentos
                          e testes repetitivos, embora nem sempre
                          mostraremos todos os passos aqui.




                                                                              você está aqui ~     69
A view do usuário



A View do Usuário para a aplicação "&eer Advisor"
(Especialista eltt Cervejas)
Nossa aplicação será uma esp~cialista em cervejas. Os usuários
poderão navegar em nossa aplicação, responder perguntas e
receber conselhos valiosÍssimos sobre cervejas.




                                                           ~
                                                           .     ~            t~ HrM.l_ eser:
                                                                              z.s.f-a p~tP1a ti":
           Beer Seleetion Page                                                N!.spós.f-a
                                                                              eJ?vi'o,PldlJ
                                                                                          CIJ~"
  Select ooer characteristics
                                                                              ClJir ~lIe   <)   lISllfJ.I'i'(>
  Color:   {light   .;   j




                                                                     ís.f-a              lI~a
                                                                     IJ clJPlselt.ó C(l~ base PIo.
                                                                                  I
                                                            ~        dI) lISlIfJ.l'i6.

    Beer Recommendations JSP

    try: Jack's Pale Ale
    try: Gout Stout

                                                                              f:    Por que estamos
                                                                               criando uma aplicação
                                                                               que dá conselhos sobre
                                                                               cervejas?


                                                                               1:  Depois de uma
                                                                               exaustiva pesquisa de
                                                                               mercado, concluímos que
                                                                               90% dos nossos leitores
                                                                               apreciam cerveja. Para
                                                                               os outros 10%, basta
                                                                               simplesmente substituir a
                                                                               palavra "cerveja" por "café".




70 capitulo 3
praticando com o MVC



Aqui está a arquitetura ...
Ainda que esta seja uma aplicação bem pequena, vamos
construÍ-la usando uma arquitetura MVC simples. Desta forma,
quando ela se tomar O SITE mais badalado da web, estaremos
prontos para aumentá-la.

              Container
                                                                       1 - O cliente solicita a página
                                                                            jorm.html.




                                       -~
                                       servlet
                                                 C(J;r/-l'cladcl"
                                                                       2 - O Container vai buscar a
                                                                             páginajorm.html.

                                                                       3 - O Container retoma a página
                                                                            ao browser, o usuário
                                                                            responde às perguntas do
                                                                            formulário e...

                                                                      A-pe"llJ.s   tllJ'I

                                                     componente       D/J Java tJldec.f.
                                                     BeerExpert
                                                                      JavlJ, sllty.>les).
                                                                       4 - O browser envia os
                                                                              dados da solicitação ao
                                                                              container.
                   Container
                                                                       5 - O Container encontra o
                                                                            servlet correto baseado
                                                                              na URL e passa a
                                                                              solicitação para o servlet.
                                                                       6 - O servlet pede ajuda ao
                                                                            BeerExpert.
                                                                       7 - A classe responsável
                                                                            retoma uma resposta, a
                                                         componente
                                                                            qual o servlet adiciona ao
                                        solicitação BeerExpert              objeto solicitação.
                                                                       8 - O servlet encaminha a
                                                                              solicitação ao JSP.
                                                                       9 - O JSP recebe a resposta do
                                                                            objeto solicitação.

                                                                       10 - O JSP gera uma página
                                                                            para o Container.
                                                                       11 - O Container retoma a
                                                                              página para o usuário feliz.




                                                                              você está                 71
ambiente de desenvolvimento



Criat'ldo         O   seu attbiettte          de deset1volvittettto
Existem várias formas de você organizar a sua estrutura de diretórios
de desenvolvimento, mas esta é a que recomendamos para projetos de
pequeno e médio portes. Na hora de distribuir a aplicação, copiaremos
uma porção disso para onde quer que o nosso Container específico
queira. (Neste tutorial, usaremos o Tomcat 5.)




     ru "" .- pl"eclstI.
     I,.v"ce 410.6
     Jes-fe      Jll"e-!-:1"16      ---7                                                                           Sevs CtrJl'I1flJl1t:l1ffS
                                                                                                                   Vrf!W es-!-:-I-rctrJs e
     pal"tI.   6 -!-V-!-61"I"o.I)                                                                                       ...•..


                                                                                                                   JinlA",i(;ós        fleal?! a~tlr.

                                                                                                                                              j


                        li.   í ....
                       rr~vi' V6Ce có161:f1.
                       6S (U'3V1'vtrJSJA-Je
                       Je -hI"CfiÍ"óS (J"
                                                                                                                                 result.jsp       form.html
                       Sfl"vle-!-rJe-vs).

J'     T                                                                                                                                            r
í a~vr         Sve fica Sf!V                                                                                           f..XfI'l1fItJS Je fI.;vns
Je C4I1fijvl'o"';ó.                                                                                                    C6l'11flJnel1-H::Svtew.




                                                 BeerSelect.java        BeerExperLjava          BeerSeleel.elass    BeerExperLelass


F


i. duó          ave eS-!-lAl?!as tlSfl.I1Jó a
                                                                   ~j
                                                                    JeepfJ.I"e~ve Sf!PD.I'D."'l'JSóS CIJ"'fIJI?f!I?+es                 d"
eS-!-l"v-!-vI"o.-po.Jl"ãa           pal"a   ó Pfl.C6+e;
                                                                    clJl?-!-I""'adal"    ell'JS c""'fIJI1f!I?+es     dó "'t>Jel.
pal"tI. ~ve pós StI."'óS ób+el" óS
         I
benef,cl6s 41ól"h'iIU'"s elele:

-       óI"5anl";4,';a     el" pl"~e-l-6
"7     5eN!l?crD."'f!I1.f.ó ela 1?D.",espD.ce

       p61"-!-d"'Maele           e I"f!lI-hlt";ajãó

72 capitulo 3
praticando com                 o MVC


Criat1do         O   atMbiettte de         distribui~o                                                   !s+e          é ti dlÍ"d:l"itJ        t.(JIr<f

Distribuir uma aplicação envolve seguir regras específicas                                               dtl t;Ir<Cfi.~
do Container e requerimentos das especificações dos
                                                                                                         +el" siiJó cI:'a.Ir<adóde
Servlets e JSPs (se você não está usando o Tomcat, terá que
descobrir onde exatamente a sua aplicação ligar-se-á ao seu
Container). No nosso exemplo, tudo abaixo do diretório                                                   +"Ir<ca-l-         S-.O.
"Beer -vI" é igual, independentemente do seu Container!
                                                                                             (dllel"f~J
                                                                                                                'Ís+a                  da
                      Específico para o Tomcat                                                                  es+I"I.I+vI"{J, lIle
                                                                                                                dlÍ"e-r,fjl"itJs e
                                                                                                                       1/        /

ís+e      l1ólr<f!de di'l'e+:l"iiJ    +aJi'lbélr<l"epl'f!:se~a    <:l                                          pe!tJ                   e
If        J               //                                            /
                                                                                                                 es+al'
      C6J'if"'eX+ I"Mi         alie ó 1;;Ir<ca+ lisa 1JlIfU1tlfJ
                                                               eS+a
l"esIJlvfl1dõ        fJJt.Ls. AJ:s exp!(Jl'ttl"f.Ir<(Js es+e c4I1ce4"(J                                          daixIJ       lIla set/
                                                                                                                 tlll"ef-:f'ltJ     t.(J~e,
telr<Ji'lQltJl"esJe+alt,es         '14 cap:+lIla sobl"e PiS+l"l!llll{ã(J.

                                                                            ~
1;;Jó A-8A-I>j.o des+a               hi1t.tJ.
p(ji1+lIt.aJn.       í. a o.pliélJ.{ãó; 3ve seI':
tJ.Ir<es~a; li1tlepe'1Je'1+e~ei1+e               Jó
Idl"ií::tJ.J1+e tllJ sell CIJW/-QIi1fl",



                                                                                                                                           result.jsp

                      Parte da                                                                                                            af'ôVlvt'J

                      especificação                                                                                    ~       wd.xIr<1
                                                                                                                                     es+1J.1"e~
                                                                                                                                               ríM.
                      dos Servlets                                                                   </webapp>



                                                                                                    web.xml                    wU;-IAlF


                                                                            ~
                                                                                     A- es.fl'v+vl"tJ.           tles+e pt4có+e é
                                                                                     exa.faJi'lt!I1+e a                    VStJ.Ji'l6S116
                                                                                     fJ.Ji'I!Ji'el1+e tlt!Sfl1l1d!Vllr<fl1+ó.
                                                                                                    tle                                          A-
                      Específico da
                      Aplicação                                                      Ir<el1"s 3ve                                 tllS+l"l!JVIi1tlt>
                                                                                     SVtJ.ScltJ.sses           f.Ir<   Vir<
                                                                                     (h,ItJ.l"eJi'llJs   t:l



                                                                                     +tJ.l"tle)J
                                                                                     de es.fl"v.fvl'{J,
                                                                                     llr<eJi'a.ffi.Ir<e~

                                                0010   00                            IAlFlda.sses.
                                                 100   1001
                                                0001   0011
                                                0101   0110


                                           BeerSelectclass        BeerExpert.class




                                                                                                                 você está                                73
construindo aplicação



Mapa para a COttstrução da aplicação
Quando iniciamos este capítulo, definimos um processo de quatro etapas para desenvolvermos nossa
aplicação. Até agora nós já:
1-   Revisamos as views do usuário para nossa aplicação.
2-   Vimos a arquitetura.
3-   Criamos os ambientes de desenvolvimento        e distribuição para montar e distribuir a aplicação.
Agora é a vez da etapa 4: criar a aplicação.
Nós tiramos isso de várias metodologias conhecidas de desenvolvimento         (muita programação e
incansáveis repetições) e adequamos aos nossos propósitos malignos ...




Os cittco passos que seguireiMos (ttOpasso 4):

     ~    Construir   e testar o formulário    HTML que o usuário irá solicitar primeiro.

     $Construir       e testar a versão 1 do servlet controlado r com o formulário HTML. Esta versão
          é invocada via formulário HTML e exibe o parâmetro que ela recebe.


     $    Construir   uma classe teste para a classe modelo/expert, além de construir e testar a classe
          modelo/expert em si.


     $Atualizar       o servlet para a versão 2. Esta versão nos dá a capacidade de chamar a classe
          modelo a fim de obter os conselhos sobre cervejas.


     ~    Construir o JSP e atualizar o servlet para a versão 3 (que agrega a capacidade de entregar
          para o JSP), e testar toda a aplicação.




74             3
praticando com o MVC



o HfML do forntulário da página inicial
o HTML é simples - ele coloca o cabeçalho, a lista drop-
down de onde o usuário seleciona uma cor para a cerveja e o
botão Submit.

   <html><body>
   <hl align=Hcenter">Beer         Selection    Page</hl>

   <form method="POST" ~                              Ar 3ve escljlt.eJr;ljsposre"",     vej P/e
      action~"SelectBeer.do">     ~
      Select beer characte:rístics<P>"-         OfirMI- pe#'lsa 3ve c servle+      -h"", es-h #'Ic~e.
      Calor:                                   AJ';1j"': AJltblt #'Iasva es-!-rv+vra P/eJtre+:rlcs
      <select     name="colo:r"   size="l "> c"'a"",aJIj5elec+8eer.P/(J/ Is+"
                                                       .                            ~ v"'"#'I{)~e
                                                                                                1:5lclJ •••

        <option
        <optíon     value="amber">
                    value="líght">    amber
                                      líght    </option>
                                               </oPtion»
        <option     value="brown">    brown </ oPtion>?      hl asstltl, 3ve crto.""'(Js "",e#'lvvll-
                                                                                        Q       p
         <option value="dark"> dark </option>               JMIl/#'IltI,assvas "pg';esfcJell'l varl"4l'.
      </select>
      <br><br>
                                              /                  ..,J L
                                                                                     I / ~/ 7
                                                             (4ce e#'l~#'I"ev (J sl-t.e= I .)
      <center>
         <input type~"SUBMIT">
      </center>
   </form></body></html>



r:   Por que o formulário está enviando para
"SelectBeer.do" se não há NENHUM servlet
com esse nome? Nas estruturas de diretórios
que vimos anteriormente, não havia nada com
o nome "SelectBeer.do".  E o que significa a
extensão" .do" afinal?


1: SelectBeer.do   é um nome lógico, não um nome de
arquivo de verdade. É simplesmente o nome que queremos
que o cliente use! Aliás, o cliente JAMAIS terá acesso
direto ao arquivo de classe servlet. Portanto, você não cria,
por exemplo, uma página HTML com um link ou ação que
inclua um caminho para um arquivo de classe servlet.
O truque é, nós usaremos o Deployment Descriptor
XML (web.xml) para mapear o que o cliente requisita
("SelectBeer.do"), para um arquivo real de classe servlet
que o Container usará quando entrar uma solicitação
"SelectBeer.do". Por enquanto, considere a extensão ".do"
como uma simples parte do nome lógico (e não um tipo
de arquivo mesmo). Mais adiante, você aprenderá outras
maneiras de usar as extensões (reais ou fictícias/lógicas) em
seus mapeamentos de servlet.



                                                                                   você está                  75
distribuindo   e testando


l1istribuit1do e testat1do        a págit1a it1icial
Para testá"la, você precisa distribuí-Ia na estrutura de diretórios
do Container (Tomcat), iniciar o Tomcat e acessar a página em
um browser.



8    Crie o HTML no seu ambiente de desenvolvimento
     Crie este arquivo HTML, chame-o deform.html e
     salve-o em seu ambiente de desenvolvimento, sob o
     diretório /beerVl/webl.


o    Copie o arquivo para o ambiente de distribuição

     webapps/Beer-vll. (Lembre-se, o diretório em tomeat/
     Coloque uma cópia do arquivoform.html      home do                                       ~              ~     ~
     seu tomcat pode ter um nome diferente).
                                                                                                                   form.html


e    Crie o DO em seu ambiente de desenvolvimento
     Crie este documento XML, nomeie-o de web.xml e salve-o em seu ambiente de desenvolvimento,
     sob o diretório /beerVl/etc/.
                                                                                             LI.••• ,..,
                                                                                             V6ce"tu" precisa Ct!JI1t.ecer


    <web-app     xmlns~''http://java.sun.com/xml/ns/j2ee''lJ('                    ~          l1o.d4diSS,,; apel1{).s
         xmlns:xsi=''http://www.w3.org/2001/XMLSchema~instance''
         xsi:schemaLocation=''http://java.sun.com/xml/ns/j2ee/web~app                                  2 4.xsd"
         version="2.4fl>
                                                                                  I                j I          .••• I
                                                                                  e li" 'U:J~e:lteru::"" ~ve Y<:Ice
                                                                                                                  vsara
      '<servlet>                                                                        e~ "v+ras        f'ar+es   d"
          '<servlet~name>Ch         Beer</servlet-name>
          '<servlet~class>c          .example.web.BeerSelect</servlet-class>
      </servlet>
                                                            ~                      AJ,,~e+(••fa/~el1+e
      <servlet-mapping>                                                            ar3vry"        de classe servle.f.
          <servlet-name>Ch3        Beer</servlet-name>
          '<url-pattern>/SelectBeer.do</url-pattern>


      </servlet-mapPing~~f:            "   I;.
                                            :     fJ.S 3ve "tlf!N!~II'JS 3ve " clre,,~L se
                                                     si'~
                                                        I        N         U I                       ,..,
    </web-app>       AJ'i1l'Je es~vesa servler.
                            s                               f)       .da     e apel1fJ.s
                                                                                       V~IJ. C611I1el1jfJ.IJ.

                     de c,,~egtlr CIJII'I
                     Vll'ltl barro..




76 capitulo 3
praticando com o fV1VC



A principal função deste DD é definir o mapeamento entre o
nome lógico que o cliente usa na solicitação
("SelectBeer.do") e o arquivo de classe servlet verdadeiro
(com.example.web.BeerSelect).


o    Copie o arquivo para o ambiente de distribuição
    Coloque uma cópia do arquivo web.xrnI em torneat/
    webapps/Beer- v IIWEB-INFI.
    Você DEVE colocá-Io aí para que o Container o
    encontre; do contrário, nada
    funcionará, e você ficará deprimido.




                                                                          web.xml



e    Inicialize o Tomcat
     Estamos usando ao longo do livro o Torncat tanto
     como Servidor, quanto como Container. No mundo
     real, você provavelmente usará um web server
     mais robusto (como o Apache) configurado com
     um Container (como o Tomcat). Mas o Tomcat é
     um servidor perfeitamente decente para tudo o que
     precisamos neste livro.
     Para iniciar o Tomcat, vá para o diretório home do
     tomcat e execute o bin/startup.sh.




o    Teste a página
     Abra a página HTML no seu
     browser e digite:

     http://localhost: 8080/Beer-v 1/
     fOfill.htrnl.

     Você deverá ver algo parecido
     com esta tela.                               Beer Seleetion Page
                                         Seleet beer eharaeteristics

                                         Color.   f light   i~l




                                                                       vocÊ~está          77
mapeando   o servlet




                       POST IBeer-VllSelectBeer.do
                     HTTP/1.1

                    Host   WV.rw.wickedlysmart.com

                    User-Agent Mozilla60 (MaCintosh- U'

                   :CMaCOSXMaCh-o;en_US;rV;l.~)         ,
                     ck0/20030624 NetscapeJ7. J
                   Accept telCt/xml,application!
                   xmr,application/xhnnl+xml,text/
                  htmJ~O.9,text/Plain;q""0.8,video!x_
                  ~ng,image/png,imageljpeg,jmijge/
                  grf;q:oO.2//';Q"'Ü.l
Cliente




e   o  Container procura o DD
    e encontra um <servlet-
    mapping> com um <url-
    pattern>, que coincide com                              <web-apP>
                                                              <serv1et>
    o /SelectBeer.do,   onde a                                   <servlet-name>
                                                                    Ch3 Beer
    barra (I) representa a raiz
                                                                  </servlet-name>
    do contexto da aplicação e                                    <servlet-class>    b Beerse~ect
    o SelectBeer.do é o nome                                        COIfL.examP1e.we   .
                                                                  </servlet-class>
    lógico de um recurso.                                       </servlet>

                                                                 <servlet-mapping>
                                                                   <serV      let _name>
                                                                        Ch3    Beer



eo
                                                                    </servlet-name>
                                                                    <url-pattern>
       Container vê que o                                               ISelectBeer.do
                                                                    </url-pattern>
    <servlet-name> para esta                                      </servlet-mapping>
    <url-pattern> é "Ch3 Beer".                                 </web-app>
    Mas este não é o nome
    verdadeiro de um arquivo de
    classe servlet. "Ch3 Beer" é
    o nome de um servlet, e não
    de uma classe de servlet.

    Para o Container, servlet é        Container
    aquilo que foi definido no DD,
    abaixo da tag <servlet>. O nome do servlet é
    simplesmente o nome usado no DD, para que as
    outras partes do DD possam mapeá-Io.


78 capítulo 3
praticando com o MVC



oo     Container procura dentro
    das tags <servlet> a tag
    <servlet-name> "Ch3 Beer".




                                  Container
                                                             <servlet-mapping>



o   O Container usa a <servlet-
    c1ass> da tag <servlet>
                                                                <serv1et-
                                                                   Ch3 Bee
                                                                <íservlet-name>
                                                                <url-pattern>
                                                                   IselectBeer.dO
    para descobrir que classe                                    </url-patter~>
    servlet é responsável por                                  </servlet-mapplng>
                                                             </web-app>
    tratar esta solicitação.
    Se o servlet não tiver
    sido inicializado, a classe
    é carregada e o servlet é
    inicializado.



o   O Container inicia uma nova thread
    para tratar a solicitação, e passar a
    solicitação para a thread (para o método
    serviceO do servlet).




                                                                resposta



o   O Container envia a resposta (através
    servidor, claro) de volta ao cliente.
                                            do




Cliente                                          Container



                                                                          você esta         79
primeira versão do controíador senríet



A pritMeiraversão do cotttrolador servlet
Nosso plano é construir o servlet em etapas, testando os vários links de comunicação,
conforme avançamos. No final, lembre-se, o servlet aceitará um parâmetro que venha da
solicitação, invocará um método no modelo, salvará a informação em um lugar que o JSP
possa encontrá-Ia e encaminhará a solicitação ao JSP. Mas para esta primeira versão, nosso
objetivo é apenas garantir que a página HTML possa chamar adequadamente o servlet e que
o servlet esteja recebendo o parâmetro HTML da forma correta.

                                                                      ~S~IA cer'+" de ~ue você US6UlU Itl.f!:SIYlfJ.S
Código do servlet                                                     es+ru+uri1.s de df!sf!I1vcllll#i-.f!I1+t:>
                                                                                                               f!

                       package     com.example.web;         ~•   /    dts+l"i!JGI/"{ãó~Uf! crl"aItl.CSal1+el"fórltl.e,,+e.




                                                                           r
                       import     javax.servlet.*;                                 tJ H#p:5erIl1e+              es+e"de "
                       import     javax.servlet.http.*;
                                                                                   bel1eriCSerll1e-lj            óGleIWtpleltl.el1+a
                       import     java.io.*;
                                                                                   IAIYt.ferlace dó Serllle+ •••
                       public     class      BeerSelect    extends        HttpServlet      {


                             public    void      doPost(HttpServletRequest              request,
                                                      HttpServletResponse           response)
                                                      throws     IOException,       ServletException


                                 response. setContentType             ("text/html");      J::::- 'l.s.fe Itl.é+ódó
                                 PrintWriter        out = response.getWriter();                          Vf!ltl.dIA
                                 out .println ("Beer Selection              Advice<br>")       ;         :5erIl1e+Je,!!sp"""Sf!..

                                 out.println("<br>Got
                                 String c ~ request.getParameter("COIOr");~
                                                       beer color " + c);                          , ~


                                             -                       ~)                            ~S+e ltl.é+cd6
                                                                                                   lIeltl. da Ii?.ferlace

li S&lr'fltl.tfJS Jc.R.s+ pal"&l
                ó                                              f!.S.f-&lItl.If)S                   :5erv1e+Jeeóvf!s+.
+rlA+ar IAsali'ct+a{ic          Hrr~                                       "el1t.vlYl              Jeepar'f ôve           IJ


1'61$  ó fCl"ltl.vl:r'lÍJ   tfntA.L.   IIIl"j=                                                     ar5vltl.e"+1J clJli?cide c<:)1tl.
ltl.e+t,ólll=PtJ:5r                                                                                  vll.l"r'
                                                                                                   <:)          1l.+I"I"'!JV+t:>
                                                                                                   /I
                                                                                                         I1ll.ltl.e "14
                                                                                                   <selec+> dtfJ
APls itMportantes




80
praticando com    o MVC


COlMpilando, istribuindo e testando o cotttrolador servlet
           d
Perfeito! Nós construímos, distribuímos e testamos nosso HTML,
e construímos e distribuímos nosso DD (bem, colocamos o web.
xml no ambiente de distribuição, mas tecnicamente o DD não será
distribuído até reiniciarmos o Tomcat). Agora é hora de compilar
a primeira versão do servlet, distribuÍ-I o e testá-Io via formulário
HTML. Vamos reiniciar o Tomcat para garantir que ele "enxergue"
o web.xml e a classe servlet.



Compilando o servlet
Compile o servlet usando -d para colocar a classe no ambiente
de desenvolvimento.                                                                                                            /
                             CCl1liJvre       ts.f." faro. ttle cÓIÍ1ctJa C<:l~ I) c4~1Í1t.1) de dtre.f.JU"I't!S #16 setl
                                          I                /
                                                          1'1
                              Sl"s.f.e*lti.. 1;;d6 IJf>)'S .f.ólt'oca.f.
                                                                                I    1"
                                                                          sei"a iJVo.l.




                                                    /
                        I         n .•..•.lJ se';       4f'fã6 -ç{ fai"Q. lÍ1-/fJi"I't'iI'U"ti,) CÓl!P>fllo.dói" l'J.i"4 (;lJlfJcal"
                                                                                                               p
(J se   tl fM.f.ó   e IIIt'jula    ;      li 1J.i"~1I1"v(J
                                                        ,das           05 PlIJ    ç{tre.f.:i"I't!       de c/(J;sses; de#1.f."tJi ç{a
l1ó SI"s-l-i!""tJ.Ófel"IJ.CI't!I?I'J.!
                                          ts.f.rv.f.vi"IJ.       CÓi"l"e.f.1J. flJ.cóff.
                                                                             ç{1/}                        Setl at'~vlvQ ,c/ass vai'
WIÍ1ç{óWS
                                          acabai" e"'" IbeerV                  IlclQ.sstslcfJl't'ilelfal!P>f1el             webl.



Distribuindo o servlet
Para distribuir o servlet, faça uma cópia do arquivo .class e mova-o para o diretório
/Beer-vlIWEB-INF/dasses/comlexample/web/         na estrutura de distribuição.




Testando o servlet                                                FI   Ed" Wid          Hl    SI hdtM

                                                                  %    cd tomcat
I - Reinicie o tomcat!                                            %    bin/shutdown.sh
                                                                  % bin/startup.sh
2 - Abra seu browser e digite: http://
localhost: 8080/Beer -vI /form.htrnl
                                                                   http://localhost:8080
3 - Selecione uma cor de cerveja e dique
em "Submit"                                                              Beer Seleetion Page
                                                                  Sckct bcen;l1arncterisocs
4 - Se o seu servlet estiver funcionando,                         Color::ug~
você deverá ver no browser a resposta do
servlet parecida com:
           Conselhos sobre Escolha de Cerveja
           Você escolheu a cerveja marrom

                                                                                                                       você está           81
classe modelo



Cot1struit1do e testat1do      a classe tModelo
No MVC, o modelo tende a ser o "back-end" da aplicação. Em geral, é o sistema
tradicional que está sendo exposto na web atualmente. Em muitos casos ele é apenas um
código Java simples, sem saber que talvez possa ser chamado pelos servlets. O modelo
não deve ficar restrito a ser usado por somente uma única aplicação, portanto ele deve
ficar dentro dos seus próprios pacotes de utilidades.


As especificações para o modelo
      Seu pacote deve ser com.example.model
      Sua estrutura de diretórios deve ser /WEB-INF/c1asses/com/example/model
      Ela disponibiliza um método, getBrandsO, que obtém uma cor preferida (como
      um String) e retoma uma ArrayList de marcas de cervejas recomendadas (também
      como Strings).


Construa a classe de testes para o modelo
Crie a classe de testes para o modelo (sim, antes de construir o modelo em si). Aqui,
você está por sua própria conta, pois não temos uma neste tutorial. Lembre-se, o modelo
ainda estará no ambiente de desenvolvimento quando você testá-Io pela primeira vez - é
como outra classe Java qualquer, e você pode testá-Io sem o Tomcat.

Construa e teste o modelo
Os modelos podem ser extremamente complicados. Eles freqüentemente envolvem
conexões com bancos de dados tradicionais e chamadas a lógicas complexas. Aqui está
nosso sofisticado e inteligente sistema baseado em regras que dá conselhos sobre cerveja:

     package com.example.model;
     import java.util.*;

     public class BeerExpert   {
       public List getBrands(String     color)
          List brands = new ArrayList();
          if (color.equals ("amber")) {
             brands.add("Jack  Amber");                   C4i1'1él   Cap+VI'Il."'4S   as ,;;ftU·"'tl.gDes
             brands.add("Red  Moose");
                                                especi'Q!"~flI.dtl.s e clJ"'P1l!xas dlJ l!Xl!"'P!1J da cel'v~4.J
         }
         else {                                 vSIJ.'IdlJ expl'es sDes ct:J'Idi'ci'IJ'Iais alla'lsadfl.s.
            brands.add("Jail      Pale Ale");
            brands.add("Gout      Stout") ;
         }
         return(brands);




  % cd beerVl
  % java -d classes        src/com/example/model/BeerExpert.java



82             3
praticando com o fvlVC



Melhorando o servlet para chatMar o tModelo,para
obtertMos conselhos VEVE~VAVE...

Nesta segunda versão do servlet, iremos melhorar o método
doPostO para chamar o modelo para oferecer o conselho (a versão
três fará com que o conselho venha de um JSP). As alterações
de código são triviais, mas a parte importante é entender a
redistribuição da aplicação melhorada. Você pode tentar escrever o
código, recompilar e distribuir por sua própria conta, ou então virar
a página e seguir adiante ...




          AP9nte seu lápIS
                                    Melhorando o servlet, versão dois
                                    Esqueça os servlets por um minuto, vamos pensar apenas em Java.
                                    Quais são os passos que devemos tomar para realizar estas tarefas?

                                     1. Melhorar o método doPostO para chamar o modelo.
                                    2. Compilar o servlet.
                                    3. Distribuir e testar a aplicação atualizada.




                                                                                você está           83
chamando o modelo para o controlador servlet



o código do servlet versão dois
Lembre-se, o modelo é apenas Java simples, então o chamaremos
como faríamos para qualquer outro método Java: instanciar a
classe modelo e chamar o seu método!


   package    com. example. web;                 AJãô se eS3f1esa «lJ i"Y>tJt''';'' parti.         tJ   PQCô..fe lJI'lille "
   import
   import
             com. example .model. *;
             javax.servlet.*;
                                       V-        8eerl.xper";"      es";": l'P7seri(Jl).

   import    javax.servlet.http.*;

   import    java.util.*;.                                                                                  J
                                             Ct'IfJ.I1"lJ ulI';a I1"V4 cltJ.sse.
   import    java .io. * ; /                 íS.ffJ.IMS 1I';1IJ"i'Ii'ct/,l'UJlJ servle";"
                                                                             (J                ôrij/'P7al       e l1ã"
   public    class BeerSelect      extends     HttpServlet         (

      public    void   doPost(HttpServletRequest             request,

                               HttpServletResponse               response)
                               throws IOException,               ServletException

            String   c = request.getParameter("color");


            List result be be.getBrands(c);
            BeerExpert   = = new BeerExpert();~              ~
                                                                       II1S";"fJ.l1clfJ.1' 4 classe 8eet'1..J(fel''';''    fi!

            response.setContentType("text/html");
            PrintWri ter out = response. getWri ter (); C tllI';éI lJ,e
                                                                        li            ";"8,,,s ()•
                                                                                        t'tll1
            out.println("Beer    Selection Advice<br>");



            Iterator it = result.iterator();
            while(it.hasNext(»      {
                out.print("<br>try:   " + it.next(»;
praticando com o MVC



Os prit'lcipais passos para o servlet versão dois

Temos duas tarefas importantes a fazer: recompilar o servlet e
distribuir a classe modelo.


Compilando o servlet

Nós usaremos o mesmo comando compilador que usamos quando
construimos a primeira versão do servlet.
  FI Edl '1" d   Hei PI Go
                                                <

  % cd beerV1
  % javac -classpath   /Users/bert/Applications2/tomcat/common/libl
  servlet-api.jar:classes:.    -d classes src/com/example/web/BeerSelect.java
                                                             __ ~_~_'Âq,,,"_,,,,.
                                                              ~




Distribuindo e testando a aplicação

    Agora, além do servlet, nós também temos que distribuir o modelo.
    Os principais passos são:


    1-     Mova uma cópia do arquivo .class do servlet para:
      ../Beer-v lIWEB-INF /classes/com/example/web/
      Isto substitui a primeira versão do arquivo de classe do servlet!

    2-      Mova uma cópia do arquivo .class do modelo para:
      ../Beer-v l/WEB- INF /classes/com/example/modeV

    3-      Feche e reinicie o tomcat

    4 - Teste a aplicação via form.html; o browser deverá
        mostrar algo como:
            Conselhos sobre Escolha de Cerveja
            experimente: JackAmber      Fie Ed"! Wndow Help S IIH h
                                        % cd tomcat
            experimente: Red Moose      % bin/shutdown.sh
                                        % bin/startup.sh




                                        5elect beer chamcteristics.


                                        COIDr::'Ii!lht',;i            ~~/




                                                                            você está         85
a aplicação MVC


Revendo a aplicação MVC, parcialt1ente cot1pleta,
que dá conselhos sobre cervejas

o que está        funcionando até aqui ...




                          ~t
                                                           1 - O browser envia os dados da
                        Container
                                                              solicitação para o Container.
                        Lógica do Container                2 - O Container encontra o servlet
                                                              correto baseado na URL e passa
                                                              a solicitação para o servlet.
                        I~. ;;:.;;,                        3 - O servlet chama o BeerExpert
                                                               para ajudar.
                                    ~                      4 - O servlet exibe a resposta (que
                                                               exibe o conselho).
                                              componente
                                              BeerExpert   5 - O Container retoma a página
                                                               para o usuário feliz.




o que nós QUEREMOS...
                                                           1 - O browser envia os dados da
                                                              solicitação ao Container.
                                                           2 - O Container encontra o servlet
                                                               correto baseado na URL e
                   Container
                                                              passa a solicitação ao servlet.
                                                           3 - O servlet chama o
                                                              BeerExpert    para ajudar.
                                                           4 - A classe responsável retoma
                                                               uma resposta, que o servlet
                                                               adiciona ao objeto request.
                                                           5 - O servlet encaminha a
                                                              solicitação para o JSP.
                                                           6 - O JSP recebe a resposta do
                                                               objeto request.
                                                           7 - O JSP gera uma página para o
                                                               Container.

                                                           8 - O Container retoma a página
                                                               para o usuário feliz.


86 carlítulo 3
praticando com         o MVC


Criando a "view'" JSP que dá o conselho
Não fique tão ansioso. Você terá que esperar mais alguns
capítulos antes de realmente começarmos a falar sobre JSPs.
Na verdade, este JSP nem é tão bom assim (devido ao seu
código scriptlet, que falaremos mais adiante). Por agora, ele
deve ser bem fácil de ser lido, e se você quiser experimentá-
10, mãos à obra. Embora nós pudéssemos testar agora
este JSP direto do browser, vamos esperar até depois de
modificarmos o servlet (versão três) para ver se ele funciona.


Aqui temos o JSP...                                      ís,/-o.    é "'''ta   tlt,.e·hv4       de p:5'-l'Ia
<%@ page    import~"j ava. util.     *"   %>             (es.J.a"t6s        c6l'1siíle"lJ.l'ldlJ 3",e 6 3",e
<html>                                         ~         e/a   Ia;    S~4       be"t :bVI"6).
<body>
<hl align="center">Beer
<p>                              Recommendations            JSP</hl>
                                                                               ~
                                                                                            A
                                                                                            n'5"'''t
                                                                                                         H rM.L p,uJ,.ãlJ       (3",e e
                                                                                                                                       I
<%                                                                                          cDJ'It.eciíllJ ClJ"tlJ .fe41p/4.fe     .fe1e.J.
     List styles - (List) request.getAttribute                     ("styles") ;             1'16"t"'l?dlJ J.sf1.
     Iterator it ~ styles.iterator();
     while (it. hasNext ()) (
       out.print("<br>try:    " + it.next());                               ~
%>                                                                          A-3v/~ esh."t6s              "ece!JeI?J6    V/IfI
                                                                            a..J.,..l!JlI.J.1J IJtje.J.6 S6/tcl.J.lJ.jã6.
                                                                                             dlJ
</body>     !t'5V"t   J4V4 plJ.d,.ã" del'l.J."lJ das
</html>                                                                     fJ"t PIJVClJ "tais adl41'1.fe;
            +';3s <% %> (clJl?t.eddlJ          CIJ"t1J
                                                                            flep/i"cfJ."e"t6s          .J.(/dlJ s66N!
            ClJd~lJ scrtp.J.te.J.).
                                                                            a..J.,..l6",.J.IJS e Có"tlJ cÓl?se5""N.IJS
                                                                            ,,6.fe,.   IJ   IJtje.J." SIJ/lci.J.lJ.jãlJ•••




Distribuindo o JSP
Nós não compilamos o JSP (o Container faz isso na
primeira solicitação). Mas nós temos que:

1-     Chamá-Io de "result.jsp".

2-     Salvá-Io no ambiente de desenvolvimento,             em: /webl.


3-     Criar uma cópia dele no ambiente de distribuição, em: /Beer-vII.




                                                                                                                   result.jsp     form.html




                                                                                                             você está                     87
despachando uma solicitação para o JSP



Melhorat1do       O   servlet para "chatMa(~O JSP (versão três)
Neste passo, modificaremos o servlet para "chamar" o JSP
para gerar o resultado (view). O Container providencia um
mecanismo chamado "request dispatching", que permite
que um componente gerenciado pelo Container chame
por outro. É assim que usaremos: o servlet receberá a
informação do modelo, irá salvá-Ia no objeto solicitação e
entregará a solicitação para o JSP.


Mudanças importantes que devemos fazer no
servlet:
     I - Adicionar a resposta do componente modelo ao objeto request, para que o
         JSP possa acessá-Ia.
     2 - Pedir ao Container que encaminhe a solicitação para "result.jsp" (passo 5).


                                                                      I - O browser envia os dados da
                                                                          solicitação para o container.
                                                                     2 - O Container encontra o servlet
                      Container
                                                                         correto baseado na URL e
                                                                         passa a solicitação ao servlet.
                                                                     3 - O servlet chama o BeerExpert
                                                                         para ajudar.
                                                                     4 - A classe responsável retoma
                                                                         uma resposta, que o servlet
                                                                         adiciona ao objeto solicitação.
                                                                     5 - O servlet despacha para o JSP.
                                                                      6 - O JSP recebe a resposta
                                                                          originada do objeto solicitação.
                                     solicitação
                                                                     7 - O JSP gera uma página para o
                                                                         Container.
                                                                      8 - O Container retoma a página
                                                                          para o usuário feliz.




88
praticando com o fvJVC



o código        para o servlet versão três
Eis aqui o que modificamos no servlet para adicionar a
resposta do componente modelo ao objeto solicitação
(assim o JSP poderá recuperá-Ia) e como pedimos ao
Container para despachar ao JSP.

paekage        eom.example.web;

import     com.example.model.*;
import     javax.servlet.*;
import     javax.servlet.http.*;
import     java.io.*;
import     java.util.*;

publie     elass       BeerSelect     extends          HttpServlet               (

    publie           void  doPost(HttpServletRequest     request,
                                      HttpServletResponse    response)
                     throws IOExeeption,    ServletException    (

String c ~ request.getParameter(~color");
BeerExpert be ~ new BeerExpert();
List result ~ be.getBrands(c);
                                                                                                       tt161"4 ~vetJ JSPVfJljf.I"til.1" til
                                                                                                       1"esUI.f-{).(/c Jevehõs I"e~vel" J(J;
                Ii    response.setContentType(~text/html");                                                              )
                I I PrintWriter       out = response. getWriter                               () ;~sel"vld61"e.sUI.f-4Jti                     Jti
          II    out. println (~Beer Seleetion                      Adviee        <br>");               1;fl.l1slól"WiG.~s               t""
                                                                                                                             .•..

                                                                                                      pfJJ"fl.   Zue   VóCe' fJ.t;;JtJ. P"SSt1,




                                                                                                       A-di'ci'tJl1fJ. u""

                                                                                                       Ól6e.f-6 s6Itct.f-tJ.jfICi
               request.setAttribute(~styles",
                                                                         result);.J               /               • I 1_
                                                                                        ~              VSfJ.I".Nó'T'e 3ve (j
                                                                                                       pI"CCUI"fJ.l1dCi
                                                                                                                      Pt:J1"
               RequestDispatcher            view
                            request.getRequestDispatcher(~result.jsp");~                                                 .
                                                                                                                       1I1s+fJ.J"JclQ.        VI!?!

               view. forward(request,                response);                                                        J.           1    I
                                  ~                                                                                    ~t~4~~~
                                        fJ SfJ..,    1"t!1JUt!S.f-
                                                                 di'spa.f-ct.el" pal"ti.
                                       pf.Jll"       til.Q   C"I1.f-fJ.i;;f.1"   ave   l'i7i(;tfJ.lt-;t! '"

                                        J.sfJ., f!I1VifJ.I1J6 paN. e/e                 til.    scllcl-l-a{ãiJ
                                        e   fJ.   l"t!sp"S.f-u..




                                                                                                                             você está aqui...        89
compíle, distribua      e teste


CotMpile,distribua e teste a aplicação final!
Neste capítulo, construímos uma aplicação MVC completa
(embora pequena), usando HTML, servlets e JSPs. Você já
pode incluir isso no seu currículo.


Compilando o servlet
   Usaremos o mesmo comando compilador que usamos antes:
     d" Wi      R   I

 % cd beerVl
 % javac -classpath   /Users/bert/Applications2/tomcat/common/lib/
 servlet-api.jar:classes:.    -d classes src/com/example/web/BeerSelect.java




Distribuindo e testando a aplicação
Agora é hora de redistribuir o servlet.

1 - Mova uma cópia do arquivo .class do servlet para ../Beer-vlIWEB-INF/c1asses/comlexample/web/
(novamente, isto irá substituir o arquivo .class da versão dois anterior).


2 - Feche e reinicie o tomcat.




3 - Teste a aplicação via form.html.




                                                          Beer Recommendations   JSP




90 capítulo 3
praticando com o MVC




                              Tudo bem, então agora ele sabe fazer uma
                           aplicação MVC, mas ele ainda não tem nenhuma
                         idéia de como usar a linguagem JSP ou JSTL. Ele
                          não sabe nem usar uma tag customizada,   nem um
                          Itro. E eu o f1agrei escutando um CD do Weezer ...
                         e isso foi DEPOIS daquele álbum verde. Ele aind
                                    tem MUITO o que aprender ...




Ait1da há tltuito    O   que apret1der.


A festa acabou. Você teve três capítulos inteiros para curtir,
escrever um pequeno código e revisar tudo sobre solicitação/
resposta HTTP.
Mas ainda existem 200 perguntas preparatórias esperando por você
neste livro. E elas começam no próximo capítulo. A menos que
você já esteja familiarizado com desenvolvimento e distribuição de
servlets, você não deveria virar a página antes de realmente jazer o
tutorial deste capítulo.
Não que estejamos tentando pressioná-Io, ou fazê-Io se sentir
culpado, ou algo parecido ...




                                                                           você está aqui ~   91
Sendo um Servlet

                                   Ele usou uma solicitação GET
                                     para atualizar o banco de
                                   dados. A punição será a mais
                                   severa ... sem aulas de "Ioga
                                      com Suzy" por 90 dias.




Servlets vivem para servir clientes. A função de
um servlet   é receber   uma solicitação do cliente e devolver
uma resposta. A solicitação talvez seja simples: "traga-me
a página de Boas-vindas". Ou pode ser complexa: "Finalize
o processo do meu carrinho de compras." A solicitação traz
consigo dados cruciais e o código do seu servlet tem que
saber como encontrá-Ias e utilizá-Ias. A resposta leva a
informação que o browser precisa para montar uma página
(ou baixar alguns dados) e o código do seu servlet tem que
saber como enviá-Ias. Ou não ... em vez disso, seu servlet
pode decidir encaminhar a solicitação adiante (para outra
página, servlet ou JSP).




                                                        este é um novo capitulo"   93
objetivos do exame oficial da Sun




o Modelo de Tecnologia                                             Notas sobre a Abrangência:
do Servlet
                                                                   Todos os objetivos desta seção são cobertos
1.1 Para cada um dos Métodos HTTP (como GET,                       completamente neste capítulo, com exceção
    POST, HEAD e assim por diante), descrever                      da parte dos cookies, no objetivo 1.3. Grande
    o propósito do método e as características                     parte do conteúdo deste capítulo foi comentada
                                                                   no capítulo dois, mas lá nós dissemos: "Não se
    técnicas do protocolo do Método HTTP,
                                                                   preocupe em decorar isto. "
    listar triggers que possam levar o cliente
                                                                   Neste capítulo, você TEM que ir devagar,
    (geralmente um browser) a usar o Método                        realmente estudar e memorizar o conteúdo.
    e identificar o método HttpServlet que
                                                                   Nenhum outro capítulo cobrirá estes objetivos
    corresponda ao Método HTTP.                                    com detalhes; então, esta é a hora.
                                                                    Faça os exercícios, revise o material efaça seu
                                                                   primeiro teste preparatório nofinal deste capítulo. Se
1.2 Usando a interface HttpServletRequest,                          você não conseguir pelo menos 80% das respostas
    escrever o código que retira da solicitação                     corretas, volte para descobrir o que você deixou
    os parâmetros do formulário HTML, a                             escapar, ANTES de passar para o capítulo cinco.
    informação do header da solicitação HTTP                       Algumas das perguntas do teste preparatório que
    ou os cookies.                                                 fazem parte destes objetivos foram colocadas nos
                                                                    capítulos 5 e 6, por requererem um conhecimento
                                                                    adicional de alguns assuntos que não explicamos
1.3 Usando a interface HttpServletResponse,                         até aqui. Isto significa que teremos um número
    escrever o código que cria um header                            menor de questões preparatórias neste capítulo e
    para a resposta HTTP, configura o tipo de                       maior nos próximos, evitando testá-lo naquilo que
                                                                    você ainda não viu.
    conteúdo da resposta, recebe um stream
    de texto para a resposta, recebe um stream
    binário para a resposta, redireciona uma
    solicitação HTTP para outra URL, ou                            Nota importante: enquanto os três primeiros
    adiciona cookies na resposta. *                                capítulos abordaram assuntos que servem de
                                                                   base, desta página em diante quase tudo o que
                                                                   você verá está diretamente relacionado ou é
                                                                   explicitamente parte do exame.
1.4 Descrever o propósito e a seqüência de
    eventos do ciclo de vida de um servlet:
       (1) carregar a classe servlet, (2) instanciar
       o servlet, (3) chamar o método initO, (4)
       chamar o método serviceO, e (5) chamar o
       método destroyO.



*Não falaremos muito a respeito dos objetivos relacionados   aos
cookies até o capítulo que trata das Sessões.

94 capítulo 4
solicitação   e resposta


Os Servlets são cot1trolados pelo Cotttaitter
No capítulo dois nós vimos as funções completas do Container na vida
do servlet: ele cria os objetos request e response, cria ou aloca uma nova
thread para o servlet e chama o método serviceO do servlet, passando as
referências de request e response como argumentos. Aqui vai uma rápida
revisão ...




                                                                               o usuário  clica em um
                                                                               link que tem uma URL
                                                                               para um servlet.




   -,Cliente


                                     •
                                  request
                                                                               o Container

                                                                               objetos:
                                                                                             "vê" que
                                                                               a solicitação é para
                                                                               um servlet e cria dois

                                                                               1) HttpServletResponse
                                                                               2) HttpServletRequest




e
   --Cliente
               L'
                                                                               o Container encontra
                                                                               o servlet correto
                                                                               baseado na URL da
                                                                               solicitação, cria ou
                                                                               aloca uma thread para
                                                                               a solicitação e chama
                                                                               o método serviceO do
                                                                               servlet, passando como
                                                                               argumentos os objetos
                                                                               request e response.




                                                                             você está                  95
Servlet no container



A história cotttit'lua...


o                                                               o método    serviceO



   ..•)
     Cliente

                                                    • •
                                                                descobre qual método
                                                                do servlet chamar,
                                                                baseado no Método
                                                                HTTP (GET, POST,
                                                                etc.) enviado pelo
                                                                cliente.
                                   doGet(request,   response)
                                                                o cliente  envia uma
                                                                solicitação HTTP GET,
                                                                para que o método
                                                                serviceO chame o
                                                                método doGetO do
                                                                servlet, passando como
                                                                argumentos os objetos
                                                                request e response.




e                                                               o

   •..)
                                                                   servlet usa o objeto
                                                                resposta para escrever a
                                                                resposta para o cliente .
                                                                A resposta volta através
     Cliente                                                    do Container .


                                                •
                                             request




                                                                Quando o método
                                                                serviceO termina,
                                                                a thread morre ou
                       Container                                retoma para um pool
                                                                de threads gerenciadas
                                                                pelo Container. As
                                                                referências dos objetos
                                                                solicitação e resposta
                                                                saem do escopo e eles
                                                                se dão mal (prontos
                                                                para virarem lixo).
                                                                O cliente obtém a
                                                                resposta.

96 capitulo 4
solicitação e resposta



Mas a vida do servlet t1ão é só isso
Nós fomos até o meio da vida do servlet, mas ainda existem perguntas:
Quando a classe servlet foi carregada? Quando o construtor do servlet foi
executado? Quanto tempo vive o objeto servlet? Quando o seu servlet
deve iniciar os recursos? E quando ele deve limpá-Ias?

o ciclo de vida do servlet é simples: existe apenas um estado principal
- inicializado. Se o servlet não está inicializado, ou ele está sendo
inicializado (rodando seu construtor ou o método initO), sendo destruido
(rodando seu método destroyO), ou simplesmente não existe.
                                                                                                               construtor
                                                                                                                   initO           I  destroyO




Contain~r web                Classe        ~ervlet                   Objeto 1"ervlet
                                           I



    hd                                     •                                          o CtJl1s-l-r'V-ftJI'7,Ri/I'';tl",J4         sfla elas se
                                                                                      ser'lIle-l-       rói/o. (lIócê    IJt}O   i/el/e escrever
         :Carreoar classe               I:::~::J                                      fi"" CÓI1S-fl'fI-I-ÓI'J vse ., po.i/I'';''         IÓl'l1eclJó
                               AServl~t.class
                                                                                      CÓ1l'l    ()   sev CÓ"'f'lIfJ.i/ffJl').

          Instanciar o servlet (o c~nstrutor roda)
                                                                      r

                                                                                               Ct.41WJ.Jó
                                                                                                       apel1fJ.SUM               Vi2,i/Vt'4nfe     ti

          initO                                                                                v"i/s.da      sel'v'dj   deve c~,eff41'
                                                                      r                        lpe ti ~atl1f!l'         ct.a~   () set'lIi'ceO.
                    A-3(1t ~ 4'1Je {; ~et'lIle+ p/J,ssa a
                    I>/J,'ÓI' ar-l-e
                             p           J..e:   s(la IItJa.
         serviceO                          :




         destrovO


                                               o CffJl1-1-at"l'lf!t'ct.a1l'lfl.pal'R           daI'    a<l

                                               set'vle-l-      fliI'Ia cl.fJ.l1ce de Ii'""ftl.t' tl.l1hs

                                               i/e iI'I<ll't'et' (~vel'     dtjel'j       fi!s+tJ.r'
                                               pl'epfJ.Nl.diJ pal'tJ. I/t"ral" ''';ce). C"ljU:l               IJ

                                               t"l'lr+oJ eJe é. Ct.RiI'I4dlJ tJ.pfi!I1RS
                                                                                       V1I'ItI. ve'],




                                                                                                                   você está aqui         li>      97
•..
o servlet AP!
                                                     IJ6-1-a:   IJlfo      ffJ1ff     lIe1l61't;41' -I-l/d6 i'S-I-6
                                                     h.J6NJ.!P,eJ1tJ.sSI.,,-I-4C6116
                                                                                    a                IfPI -I-l'daI1.4 •••
Seu servlet herda os Iftétodos do ciclo de vida
                 «mter ace»                          A interface Servlet
                     Servlet                         (j avax. serv let. Servlet)
 ervice(ServletRequest, ServletResponse)
°nit(ServletConfig)
                                                     If l;,ffrf(J,ce Servle.-I- ~(t; 31/e-!-#das as
 estroyO                                             se.l'vle-l-s P6SS(Jt'1It'SffS CI;'CfJ 1I:-I-ad6s
 etServletConfigO
                                                     (ós -I-/es ell J1t'jrt-l-ó sãa 1I:-I-(jdfJS
 etServletlnfoQ
                                                     refel'el'JffS (J,(j i'cló de VI"JfJ,).
                                                                        c


                          I
                Generic                              A classe GenericServlet
                                                     (j avax. servlet. GenericServ let)
serVIce ervletRequest,
°nit(ServletConfig)
'nitO                                                    be'lel'i'cSel'vle.f:          (JIIIJ.
                                                                                              classe ds-I-I'IJ.-I-a ~I/e
                                                     1~/e~e'l-l-a        a /illifJ.tfJrtafJS /iIIi:-I-6dtfJS
                                                                                        d                  lJ:siC6S dll
destroyO                                                                       •••               I
getServletConfigO                                                    3",e Vtlcepreclsar~ 1;'c/"'I;,dIJ fJ.1J",e1es
getServletInfoO                                            I;,ffrlf;.ce Servle-l-. I4cê pr""valle/~eJ1ff
getInitParameter(String)                             MUMC/lr lar: "'11 xff'ld l'Jesh classe.
                                                                                e
                                                                        11                               /1
getInitParameterN amesO                              /illiatarl"IJ. d(j ciJh'iffJr-l-o.lIeJ1-!-IJ
                                                                                               sel'lIle+    dl!Ji el/
                                                                                                                s
getServletContextO
                                                     serllle-l- lIell daZ"'i'.
log(String)
log(String, Throwable)



                   Http ervlet                       A classe HttpServlet
         ttp erv et equest, ttp erv et               (j avax. servlet.http .HttpServlet)
service(ServletRequest, ServletResponse)
doGet(HttpServletRequest, HttpServletResponse)                                   (+fJ.~!J:/iIIi",~a classe
doPost(HttpServletRequest, HttpServletResponse)
doHead(HttpServletRequest, HttpServletResponse)                          ,~/e/illie'l-!-a   fJ

doOptions(HttpServletRequest, HttpServletResponse)                          as
doPut(HttpServletRequest, HttpServletResponse)                           -tl
doTrace(HttpServ letRequest, HttpServletResponse)
                                                     AlíAlHu JlA.. se rl/le-!- de
doDelete(HttpServletRequest, HttpServletResponse)
 etLastModified(HttpServletRequest)                  4J1-h5,,;/illih.S (JíJh.
                                                                             StfJli'cl-l-h.Sãtl
                                                                                            e
                                                     es,eclfiCa parti.         I/rrp'

                                                     A classe MyServlet
                                                     (com.wickedlysmart.foo)

                                                     lJr lIfJ.i"tfJrta
                                                                     das co.rac-/-eris-!-,cas           dtfJ    se",
                                                     servle-l- é -I-rfJ.-I-adfJ.
                                                                              pelas ~é-l-i!;d(js das
                                                                                                               /
                                                     s(Jperclasses. 1[;dtl ti 1Jve                             e a'lvlar I/,)S
                                                     íJ:-!-lJdIJS I/rrp         1J(Je
98 caplitulo4
solicitação   e resposta


     Os   rrês   G-randes MotMetttos do Ciclo de Vida




                          (GET, POST, etc.) da
              baseado no é chamado

seque
serviceO
            o
            Quando ele método HTTP tiver outros a
                 solicitação é chamadoostrataranalisadoGetO
                   doGetO
                  instância
métodoservinitO vocêPOSTo
classe você let. na sua o
          correto. chamar
solicitações suporta. anula
objetos), então
o método do HTTP
   preocupe HTTPServlet
               em
                                   queinformar uma anulado?
                                   estabelecer claro, conexão
                                   Possivelmente.dizendo
            Quando ele oudo cliente,deoéemserveservlet.é
                                   Este Dificilmente.você
                                   antes métodoodomenos,
                                   você podeetc.doGetO, UM
                                   métodosetc.)chamaranular
                                   Por estaráSeu nodeixar
                                   objetos,queseu código
                                   responsável servlet
                                   inicialize
                                  para exemplo,vocêmétodo
                                   nãovocê queseréquaisquer
                                   Parainicializaçãoovocê
                                   Se
                                   iráaqui que       ou (como
                                   EleContainer eseuque
              naOsolicitação.servlet respectivoquechamasua
                                doPostOcomeçadeveContainer
                                   manualmentedetermina
                                                     o método
                                  Vocêanularmétodosanular
                                   e/ou NÃO
                                   É método Esteaotrabalho
                                   começa! HTTP(GET,
                                   Possibilita peloporcliente.
                                   solicitações
                                   o depois
                                  Não. esperamosdaqui. outros
                                   Aquele(doGetO doPostO,
                                   SEMPRE, FAÇA.porém
                                   aplicação
                                   anularpode
                                   solicitação,
                                   POST,
                                   ao
                                   tudo
                                   doPostO,
                                   serviceO.        se tudo
                                   deles! doPostO que doPostO)
                                                         este
                                                    e código
                                                                 com umnão dá suporte às
                                                                 ou registrar-se em dados
                                                                 servlet banco de outros
                                                                 que a implementação




                                                                                      você está                   99
servlet threads




                                               o método service() é sempre chamado
                                               em sua própria pilha...
                     Inicialização do             Solicitação do                Solicitação do
                          Servlet                    cliente 1                    cliente 2




                        Thread A                     Thread B                     Thread C
                  O Container chama           Quando a primeira             Quando a segunda
                  o initO na instância        solicitação do cliente        (e todas as outras)
                  servlet depois que esta     chega, o Container inicia     solicitações do cliente
                  é criada, mas antes que     (ou localiza) uma thread e    chegam, o Container
                  o servlet atenda alguma     induz o método serviceO       novamente cria ou
                  solicitação do cliente.     do servlet a ser executado.   encontra uma outra
                  Se você tiver código        Você normalmente              thread e induz o método
                  para inicialização (como    NÃO anulará o método          serviceO do servlet a ser
                  estabelecer uma conexão     serviceO, e o método          executado.
                  com um banco de dados       do HttpServlet é que          Então, a seqüência
                  ou se registrar em outros   rodará. O método              do método serviceO
                  objetos), então você        serviceO descobre qual        -->doGetO ocorre cada
                  anula o método initO na     método HTTP (GET,             vez que existe uma
                  sua classe servlet. Do      POST, etc.) está na           solicitação do cliente.
                  contrário, o método initO   solicitação e chama           Em um determinado
                  do GenericServlet roda.     o respectivo método           momento, você terá ao
                                              doGetO ou doPostO.            menos, tantas threads
                                              O doGetO e o doPostO          sendo executadas,
                                              dentro do HttpServlet         quantas solicitações
                                              não fazem nada, então         de clientes houver,
                                              você terá que anular          limitadas pelos
                                              um ou ambos. Esta             recursos ou políticas/
                                              thread morre (ou é            configuração do
                                               colocada de volta em         Container. (Você pode,
                                              um pool gerenciado pelo       por exemplo, ter um
                                               Container) quando o          Container que permita
                                               serviceO é finalizado.       especificar a quantidade
                                                                            máxima de threads
                                                                            simultâneas, e quando o
                                                                            número das solicitações
                                                                            do cliente ultrapassá-Ia,
                                                                            alguns clientes terão
                                                                            apenas que esperar).

 100 capítulo 4
solicitação        e resposta


Cada solicitação roda etlt utMathread separada!
Você talvez já tenha ouvido alguém dizer coisas como: "Cada instância do
servlet...", mas isto está errado. Não existem múltiplas instâncias de nenhuma
classe servlet, exceto para um caso especial (chamado SingleThreadModel, de
natureza perversa). Porém, ainda não estamos falando desse caso especial.


o Container roda várias threads para processar as várias solicitações para
um único servlet.
E cada solicitação do cliente gera um novo par de objetos request e response ..
                                     Container

                                                 sotiCifõ.Çcro   Hn-p




                                                                          Cat1a     dte~-h f'€cebe
                                                                          1I1tlQ   +I.f'eaJ    Sf!p4f'at1o.

                                                                          pQ.f'a caJI! SlJli'ct·/-af'i4 e
                                                                          4   C4/'J+fJ1Pitf'   IJlifjCIJ.   /'J4V4$

                                                                          ótjff<JS sóll'ct+0-jã4 e
                                                                          t't!sf'cs+a.


        Nã9 ex'lst~m
f eth'untas Idl9tas
f:   Isto está confuso ... na
figura acima você mostra
                                   f:    E se o Container
                                    usar cluster e distribuir
                                                                        f:  Eu notei que o
                                                                        HttpServlet está num
dois clientes diferentes,           a aplicação em mais de              pacote diferente do
cada um com sua própria             uma JVM?                            GenericServlet... quantos
thread. O que acontece                                                  pacotes servlet existem?
se o mesmo cliente fizer
várias solicitações? É uma          1: Imagine que a figura
thread por cliente ou uma
                                    acima é para uma simples
                                    JVM e que cada JVM tenha
                                                                        1: Tudo relacionado a
thread por solicitação?                                                 servlets (exceto o que se
                                    a mesma figura. Então, para         refere ao JSP) está emjavax.
                                    uma aplicação distribuída,          servtet ou em javax.servlet.
1: Uma thread     por
                                    existiria uma instância de
                                    um determinado servlet para
                                                                        http. E é fácil ver a diferença ...
solicitação. O Container não                                            o que se refere a HTTP está
                                    cada JVM. Porém, cada JVM
se importa com quem fez a                                               no pacote javax.servlet.http e
                                    ainda teria apenas uma única
solicitação - cada solicitação      instância daquele servlet.          o restante (classes genéricas
que chega significa uma                                                 de servlet e interfaces) está
nova thread/pilha.                                                      em javax.servlet. Veremos
                                                                        capítulos que tratam do JSP
                                                                        mais adiante.
                                                                              você está aqui ~                    101
ínícía/ízação do Servlet



No COi1eço: carregat1do        e it1icializat1do

o servlet  nasce quando o Container encontra o arquivo de
classe servlet. Isto acontece quase sempre quando o Container
inicia (por exemplo, quando você roda o Tomcat). Quando
o Container inicia, ele procura por aplicações distribuídas e            Seu set'Íl et       é
então localiza os arquivos de classe servlet. (No capítulo sobre
Distribuição, nós entraremos em mais detalhes de como, por               sempte canegad9 e
que e onde o Container procura os servlets.) .
Encontrar a classe é o primeiro passo.
                                                                         'lnlclallzc1d 9 ANTES
Carregar a classe é o segundo passo. E isso acontece na                  de              à
inicialização do Container ou na primeira utilização do
cliente. Seu Container talvez lhe possibilite escolher qual classe
carregar, ou talvez carregar a classe sempre que ele quiser.
Independentemente de o seu Container preparar o servlet
antes ou exatamente no momento que o cliente necessita, um
método serviceO do servlet não rodará até que o servlet seja
inteiramente inicializado.


    o init() sempre         termina antes da primeira chamada ao service()




  +           EXERCITE SUA MENTE
               Por que existe um método initO? Em outras
               palavras, por que o construtor não é suficiente para
               inicializar um servlet?

               Que tipo de código você deveria colocar no
               método initO?

               Dica: o método initO usa um argumento de
               referência ao objeto. O que você acha que seria o
               argumento para o método initO e como (ou por que)
               você o usaria?




                                 lJr ••.• shtl CiJl'.>tA ••.•
                                        e              CiJ tAresfcs+tA •••iJHHf.serv!e+/t.esf~PíSe
                                                é+IJJt:>s3ve serãIJ lífl'ftlr+fl.PíffS
                                 tlcrescePí+a ••.•                                       se viJcê es-hvel"
                                 VSfl.'1JtlH.,-.,-?   eI"N;s) c(u;J.les e ~e4Jers.
102             4
solicitação   e resposta


                          A lt1icialização do Servlet: quat1do UtM objeto
                          toma-se       UtM   servlet



                                            o momento mais orgulhoso da minha vida é quando o
                                         Grande Mestre Container me transforma em um servlet,
                                            criando um ServletConfig para mime chamando meu
                                           initO. Até então, eu sou apenas um mero objeto. Mas
                                          como um servlet, eu tenho privilégios especiais (além
                                            do handshake secreto), como a capacidade de logar
                                          eventos, entregar referências para outros recursos e
                                                 armazenar atributos para outros servlets ...




Um servlet vai do não existe para inicializado (que na verdade significa pronto para
servir às solicitações dos clientes), começando com um construtor. Mas o construtor
cria apenas um objeto, não um servlet. Para ser um servlet, o objeto precisa adquirir
padrão de servlet.
Quando um objeto toma-se um servlet, ele recebe todos os privilégios que se têm
quando se é um servlet, como a capacidade para usar sua referência ServletContext para
obter informações do Container.




Porque em algum lugar entre o construtor e o método initO, o servlet está no estado servlet
Schroedinger*. Você pode possuir um código para inicialização do servlet, como receber
informação de configuração da aplicação web, ou procurar por uma referência em outro
trecho da aplicação, que irá dar erro se você executá-Ia muito cedo na vida do servlet.
Contudo, é muito simples se você se lembrar de não colocar nada no construtor do servlet!
Não há nada que não possa esperar até o initO.



* Se sua parte mecânica está um pouco enferrujada,      talvez você queira fazer uma pesquisa
no 800gle    por "Schroedinger's   Cat" (cuidado: se você ama animais, não a faça). Quando nos
referimos ao estado Schroedinger,     nos referimos a algo que não está nem totalmente   morto, nem
totalmente   vivo, mas em algum lugar estranho entre ambos.

                                                                        você está                 103
ServletConfig   e ServletContext


                Quanto vale para você "ser um servlet"?
                                    o que acontece quando            para cá?
                                    um servlet vai daqui:




                                                      o     Um objeto ServletConfil:
                                                            Um objeto ServletConfig por servlet.
                                                            Use-o para passar informações de tempo
                                                            de distribuição para o servlet (um banco
                                                            de dados ou a pesquisa do nome de um
                       Não confunda os                      enterprise bean, por exemplo) que você não
                       parâroetros do                       queira fazer hardcode no servlet (parâmetros
                   ,   ServletConfig coro                   init do servlet).
   veja 'lstº.          os parâroetros do
                        ServletContextl                     Use-o para acessar o ServletContext.

                                                            Os parâmetros são configurados no
    Nós realmen~e .não fal~~~o~~:f:          que
    isso até o proxlmo capl,                 s              Deployment Descriptor.
                            fundem, vamo
    tantas pessoas se con         ra' preste
     plantar uma semente ago .
     atenção nas diferenças.
                    lh d Pelos nomes:
                                                      e     Um ServletContext
      Comece o . an o                     " nfi"            Um ServletContext por aplicação. (Eles
                                 Palavra co g
      O ServletConfig tem a                  N"             deveriam tê-Io chamado de AppContext.)
              me que lembra "configuraçao .
      no no       ,            d t po de                    Use-o para acessar parâmetros da aplicação
      Ele lida com valores ~ eO~~gurou para o               (também configurado no Deployment
         . 'b' ção que voce c
       dlStrl til             I t) Aquilo que seu           Descriptor) .
       servlet (um por serv e .               você
           rvlet pode querer acessar e que                  Use-o como se fosse um quadro de avisos
       se                        d     mo o nome
        não quer fazer hardco e, co            I            da aplicação, onde você pode escrever
        dum banco de dados, por exemp NO.                   mensagens (conhecidas como atributos) que
          e                        I tC nfig nao
               arãmetros do Serv e o              .         as outras partes da aplicação possam acessar
         Os P N desde que este servlet esteja               (mais sobre isto no próximo capítulo).
         mudarao,         d ndo Para alterá-Ios,
          distribuído e ro a·                I              Use-o para obter informações do servidor,
          você terá que redistribuir o s~rv et.             incluindo o nome e a versão do Container e a
         O ServletContext dever-se-la cdhamar
                              I     NOnos eram              versão da API que é suportada.
         AppContext (mas e es na
               N ) pois há somente um por
         ate~çaoN' NÃO um por servlet. De
         aphcaçao .e .      '    traremos neste
          qualquer jeito: n.os en 'tulo _ isto é só
          assunto no proxlmo capl
          um alerta.




104   capítulo 4
solicitação e resposta



Mas a VERUAUEIRA fut1~o de                UiM   Servlet é tratar solicitações.

É   aí que a vida do servlet faz diferença.
No capítulo seguinte estudaremos o ServletConfig e o ServletContext, mas por hora,
estamos vendo em detalhes a solicitação e a resposta. Porque o ServletConfig e o
ServletContext existem apenas para darem suporte à Única e Verdadeira Tarefa do
servlet: tratar as solicitações do cliente! Portanto, antes de vermos como os seus objetos
contexto e configuração podem ajudá-Io em seus trabalhos, teremos que voltar um
pouco e rever os fundamentos da solicitação e resposta.
Você já sabe que a solicitação e a resposta são passadas como argumentos para o método
doGetO ou doPostO, mas que poderes estes objetos request e response oferecem? O que
você pode fazer com eles e por que você se importa com isso?




Coloque o nome nos Container Web                   Classe Servlet            Objeto Servlet
trechos em branco (as
caixas vazias) da linha
do tempo do ciclo de
vida. (Verifique suas
                                                        101201
respostas com a linha                                   Ionel
                                                        Hil.llU00010
                                                        11)101(;     o
do tempo mostrada                                       1.'1(11) 1
                                                        101.1)101

anteriormente neste                                     H,lOto!O
                                                        1001010101


capítulo.)


Acrescente também suas
próprias anotações para
facilitar a memorização
dos detalhes.




                                                                                    está            105
solicitação e resposta



Solicitaeão e Resposta: a chave para tudo, e os
argutMetttos para o service(}*



        Interface ServletRequest                                 Interface ServletResponse
      G avax.servlet.ServletRequest)                          G avax. servlet. ServletResponse)
              «interface»                                                «interface»
            ServletRe uest                                             ServletReslJonse
 getAttribute(String) : Objeet                           getBujJerSizeO : int
getContentLengthO : int                                  setContentType(String) : void
getlnputStreamO : ServletlnputStream                    getOulputLenght(int) : void
getLoealPortO : int                                     getOutputStreamO : ServletOutputStream
                                                        getWriterO : PrintWriter




                                                                            i
getParameter(String) : String
getParameterNamesO : Enumeration                        getContentTypeO
Ii MUITOS outros métodos ...                            Ii MUITOS outros métodos ...


                                                              Interface HttpServletResponse
      Interface HttpServletRequest                        G avax. servlet.http .HttpServletResponse)

G avax.serv   let.http.HttpServletRequest)                               «inte    ace»
              "«mtertace»                                          Htt S~rvletRes onse
         .flttpS~rvletB.~qlJ~st                         addCookie(Coolde) : void
 getContextPathO : String                               addHeader(String name, String value) : void
 getCookiesO : Coolde {]                                encodeRedireetURL(String url) : String
 getHeader(String) : String                             sendError(int) : void
 getQueryStringO : String                               setStatus(int) : void
 getSessionO : HttpSession                              Ii MUITOS outros métodos ...
 getMethodO : String
 Ii MUITOS outros métodos ...




*Os objetos solicitação e resposta também são argumentos para os outros
métodos HttpServlet que você escreve: doGetO, doPostO, etc.
106    capitulo 4
solicitação          e resposta

                                                                   o    .••••••••.••••••••••••••••••••

         .Nã9 eXIstem

f eth'Untas Íd1'9télS                                          .         que você saiba
                                                           ~:,~"'lU$ exame não usando
                                                                    O
                                                                    desenvolver espera
                                                                         servlets não-HTTP.
f:   Quem implementa as interfaces para o
HttpServletRequest e o HttpServletResponse?              Você não precisa saber como usar servlets
São aquelas classes na API?                              com um protocolo que não seja HTTP No
                                                       : entanto, espera-se que você saiba como a
P . N~o. O Contalner.
L . _.                                 _      _       :
                         As c1a~ses na? esta o na. : hierarquia saber classes HttpServletRequestvocê
                                                     TEM que das que o funciona. Logo,
API, pOISfica a cargo dos fabncantes Implementa-:e o HttpServletResponsesão          extensões do
Ias. A boa notícia é que você não precisa se       :ServletRequest e do ServletResponse, e que
preocupar com isso. Apenas creia que quando        : a maior parte da implementação de um
O método serviceO é chamado em seu servlet,        :HttpServlet vem, de fato, do GenericServlet.
ele receberá referências para dois excelentes      : Mas é isso. O exame entende que você é um
objetos que implementam o HttpServletRequest e : desenvolvedor HttpServlet.
o HttpServletResponse. Você jamais se preocupa :••••••••••••••••••••••••••••••••••••••••••••••
com o nome e o tipo verdadeiros da classe
envolvidos nesta implementação. Tudo que interessa é que você terá alguma coisa com
todas as funcionalidades do HttpServletRequest e do HttpServletResponse.
Ou seja, tudo o que você precisa conhecer são os métodos que você pode chamar nos
objetos que o Container oferece como parte da solicitação! A verdadeira classe na qual
serão implementados não faz diferença - você se refere aos objetos request e response
apenas pelo tipo da interface.


f:     Eu estou lendo esta UML corretamente? Essas interfaces estão estendendo interfaces?


1: Sim. Lembre-se,  as interfaces podem ter sua própria árvore de herança. Quando uma
interface estende uma outra interface (e é tudo o que elas podem fazer - pois interfaces não
implementam interfaces), significa que quem implementar uma interface deve implementar todos
os métodos definidos na interface e em suas superinterfaces. Isto quer dizer, por exemplo, que
aquele que implementar o HttpServletRequest deve prover métodos de implementação para os
métodos declarados nas interfaces HttpServletRequest e ServletRequest.


r:   Eu ainda estou confuso com o porquê de existir um GenericServlet, um
ServletRequest e um ServletResponse. Se ninguém está fazendo nada, exceto os
servlets HTTP ... qual é a intenção?


1:   Nós não dissemos ninguém. Alguém, em algum lugar, não sei, está usando o modelo
de tecnologia servlet sem o protocolo HTTP. Mas nunca encontramos ou soubemos da
existência desse alguém.
Além disso, o modelo servlet possui flexibilidade para atender àqueles que queiram usá-Io
com, por exemplo, o SMTP, ou talvez um protocolo proprietário customizado. Porém, a API
só oferece suporte nativo ao HTTP, que é o que quase todo mundo usa.



                                                                           você está aqui ~                 107
métodos HTTP




o ~étodo de solicitação       HffF defit'le se é o dokt()
ou doFost() que rodará                                                                       HTTP/1.J
                                                 Mac os X Mach-                              Host: WWW.WíckedJysmartcom
                                                                      lpeg,lmage/gif;q~O.2//*;q=o.1 Mach-O; en-US; rv:L4) GeckofPPC
                                                                       .     .             lvIac OS' X 9 MoZíIJa/5.0 (Macintosh; u;
                                                                                            User-Agent:    png,rmageJ
                                                  xhtml+xmi,text
                                                   ptain;q=:O.8,vid
                                                 Accept: textlxm       Host:www.wicked~mart.(om
                                                                       20030624 Netscape!7.1
                                                                                   NetsG
                                                                        Us~r-Agent: Mozil
                                                                      20030624Iselect/selectBeerTaste. .
                                                                         GET text/xrnl,apPlicatfon/xml,apPJicationl '
                                                                       Accept-I..anguage: en-us,en;q==o.5
                                                                       xhtml+xml.textlhtml;q~.9,text!
                                                                      Plain;q=O,B,Video/x_mn9 POST Iseleet!selectBeerTaste2.do
                                                                        do? color~dark&taste~malty
                                                                         HTTP/1.1
                                                                       Accept:                      imâ eI

Lembre-se, a solicitação do cliente sempre inclui um
Método HTTP específico. Se o Método HTTP for um
GET, o método serviceO chama o doGetO, Se for um
POST, o método serviceO chama o doPostO.




         Você continua mostrando
           o doGetO e o doPostO
          como se eles fossem os
         únicos... mas EU SEI que
         existem oito métodos no
                  HTTP 1.1.

                    Q
                     o
                                     É bem capaz de você não
                                     se importar com os outros
                                     métodos HTTP, exceto o GET
                                     e o POST
                                     Sim, existem outros Métodos HTTP 1.1 além do
                                     GET e POSTo Temos também o HEAD, TRACE,
                                     OPTIONS, PUT, DELETE e CONNECT.
                                     Todos, exceto um, têm um método doXXXO na
                                     classe HttpServlet. Ou seja, além do doGetO e
                                     doPostO, temos o doOptionsO, doHeadO, doTraceO,
                                     doPutO e doDeleteO. Não existe nenhum mecanismo
                                     na servlet da API para tratar o doConnectO, então ele
                                     não faz parte do HttpServlet.
                                     Mas, enquanto os outros Métodos HTTP
                                     talvez sejam importantes para, digamos, um
                                     desenvolvedor web, um desenvolvedor servlet
                                     raramente usará outro além do GET ou do POSTo
                                     Na maior parte do desenvolvimento servlet
                                     (provavelmente todo), você usará o doGetO (para
                                     solicitações simples) ou o doPostO (para aceitar e
                                     processar dados de formulários), e não terá que se
                                     preocupar com os outros.




108 capítulo 4
sol/citação    e re:::posta




        Na verdade~ é possível que algum outro Método HffP
        faça uma (rápida) aparição no exame ...
        Se você está se preparando para o exame, deve ser capaz de
        reconhecer todos eles e ter pelo menos uma idéia de suas funções. Mas
        não perca muito tempo aqui!

        No mundo servlet de verdade, só interessam o GET e o POSTo

        Para o exame, vai interessar também um pouquinho dos
        outros Métodos HTTP.


         GET          Pede para obter a coisa (recurso/arquivo)   na URL
                      requisitada.

         POST         Pede para o servidor aceitar a informação do corpo
                      anexada na solicitação, e a entrega para aquilo que
                      consta na URL solicitada. É como um GET com mais
                      calorias ... um GET com informação extra enviada com
                      a solicitação.

         HEAD         Pede apenas a parte do header daquilo que o GET
                      vai retomar. É como um GET sem corpo na resposta.
                      Informa a URL requisitada sem, de fato, retomar a
                      coisa.

         TRACE        Solicita um loopback da mensagem de solicitação, para
                      que o cliente veja o que está sendo recebido do outro
                      lado, para teste ou troubleshooting.

         PUT          Diz para colocar a informação anexada (o corpo) na
                      URL requisitada.

         DELETE       Diz para apagar a coisa (recurso/arquivo)      na URL
                      requisitada.

         OPTIONS      Solicita uma lista dos métodos HTTP para os quais a
                      coisa na URL requisitada pode responder.


        CONNECT Diz para conectar no caso de tunneling.
    




                                                   você está                   109
GETe POST



A diferet1ça etttre tEr e posr
o POST        tem um corpo. Essa é a dica. Ambos podem enviar parâmetros, mas com o GET, o parâmetro
é limitado ao que você pode colocar na linha de Solicitação.                                                        fJr VE'I"S4I:J
                                                                                                                                 d6

O blé1-cdó                O CQbli;'t." fQI"tJ.       <[J      íbl tlill'la SIJli'ci1-agãlJ bít;      I:JS



ifrrp        ~           ~I"fCtlI"S6                         I',r"',ir •• (S'     ~ 1.4              ";".J
                                          #1':> S.fl"Vld. C.I".. S4':>a#1E'xad.:>S fJJe.L I"fSili'Si1-adtJ.
                                              ...         ~                             •."'"
fJr li;,l.a de ~                GET       /select/;electBeerTaste.dO?C~:;-                                                 HTTP/

S ""'+ '"                   (  Host: www.wickedlysmart.com
                             . en-US; rv:l.4     Gecko/20030624 Netscape/7.1
  ':>iCI tJ.ítJ.4]            User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O;

  Ost.etJ.dE'~Sda /             html;q=0.9,text/plain;q=O.8,video/x-mng,image/png,image/
                                Accept: text/xml,application/xml,application/xhtml+xml,text/




AJíAJHfJ
          J
  Sóhc/~actJ.ó




              M
                           l   jpeg,image/gif;q=O.2,*/*;q=O.1
                            ",.Accept-Language: en-us,en;q=0.5



                                Accept-Encoding: ISO-8859-1,utf-8;q=0.7,*;q=O.7
                                Accept-Charset: gzip,deilate
                                Keep-Alive: 300

                    cal'fIJ •••Connection: keep-alive

I'íf'f#1tJ.StJ. i"PIIIJI'ill'ltJ.f4iJ ~
dIJ




            ~ ~:;,~a ~
                   d':
            ..JIJllci-rajtl;é)-r
                                          '"..POST/ advisor /selectBeerTaste. do HTTP/1. 1 ~
                                            Host: www.wickedlysmart.com
                                            User-Agent:    Mozilla/5.0   (Macintosh; U; PPC Mac OS X
                                            Mach-O; en-US; rv:l.4) Gecko/20030624      Netscape/7.1
                                            Accept: text/xml,application/xml,application/
         Os t.eo.del"S JII.
                                            xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-
        S<tJh(;/~tJ.í4(j.                   mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
                                            Accept-Language:   en-us,en;q=0.5
                                            Accept-Encoding:   gzip,deilate
                                            Accept-Charset:   ISO-8859-1,utf-8;q=0.7,*;q=0.7
                                            Keep-Alive:   300
                                            Connection:         keep-alive

                                                                                                  beS1-a VE']; 6S fal"~f!1-I""S
O C61"f6 dO.ill'lel1s~e~
tl;ljVill'lIi.S vf}es                     [. color=dark&taste=malty                ~               eSha a~l/l ebl!laix6 116             e
                                                                                                  fI:J1" i'SS6 #144 eSh6 liill'li~4daS;
Ct.li.bI!i.Jó de ffJ.j'(JfJ.J.                                                                     C(JbllJeS1-al"l4b1 se l/s:ssf!blas     (j
                                                                                                  bíre      1-tvésseblós           caü';f~:-
                                                                                                  I(ls 11{(1t"PIt.tI;
                                                                                                                   de


110 capiitulo 4
solicitação   e resposta




o
tl




     Não, não se trata só do tatManho
     Nós falamos de outros problemas do GET no capítulo U1l1, lembra?
     Quando você usa o GET, os dados do parâmetro aparecem na barra de
     endereços do browser, logo após a URL (e separados por um "1").
     Imagine uma situação em que você não quisesse que os parâmetros
     fossem exibidos.




     Então, segurança pode ser outro problema.
     Outro problema poderia ser se você precisasse ou quisesse que
     os visitantes fizessem um bookmark da página. As solicitações
     GET aceitam bookmark; já as POST, não. Talvez seja realmente
     importante que sua página, digamos, permita aos usuários
     especificar critérios de busca. Os usuários podem querer retomar
     uma semana depois e fazer a mesma busca novamente, quando
     existirão novos dados no servidor.
     Mas além de tamanho, segurança e bookmark, existe outra
     diferença crucial entre o GET
     e o POST: a maneira como devem ser usados. O GET deve ser
     usado para obter coisas. Ponto. Simplesmente receber. Claro, você
     deve usar os parâmetros para ajudar a descobrir o que enviar de
     volta, mas a questão é: você não está fazendo nenhuma mudança
     no servidor! O POST deve ser usado para enviar dados para serem
     processados. Isto pode ser tão simples como pesquisar parâmetros
     usados para descobrir o que será enviado de volta, assim como
     no GET. Mas quando você pensa em POST, você pensa em
     atualização. Você pensa: usar os dados do corpo do POST para
     mudar alguma coisa no servidor.
     E isso traz um outro problema ... se a solicitação é idempotente.
     Se não for, você pode estar diante de um problema que aquele
     pequeno comprimido azul não resolverá. Se você não está
     familiarizado com a maneira com que o termo "idempotente" é
     usado no mundo web, continue lendo ...



                                             você está                  111
a solicitação não-ídempendente


A história da solicitação •.• o-idetMpotettte
                            ã
Diane tem uma necessidade. Ela está tentando desesperadamente
comprar o "Use a Cabeça Tricô" na livraria on-line Wickedly Smart que,
sem que ela saiba, ainda está na fase de testes. Ela tem pouco dinheiro
- apenas o suficiente para comprar um livro. Ela pensou em comprar
direto do Amazon ou do Q'Reilly.com, mas decidiu que queria uma cópia
autografada, disponível apenas no Wickedly Smart. Decisão que ela
futuramente viria a se arrepender ...



o        Diane c1ica em CHECKOUT.
         (Ela já havia enviado
         os dados de sua conta
                                        o browser envia uma
                                        solicitação HTTP para o
                                                                      o Container envia
                                                                      a solicitação para o
                                        servidor com as informações   servlet Checkout para
         corrente.)                     da compra do livro e o        processamento.
                                        número da ID da cliente.




G     o servlet faz um débito eletrônico da
      conta bancária da Diane.
                                                      eo     servlet atualiza o banco de
                                                           dados (tira o livro do estoque, cria
                                                           um novo pedido de entrega, etc.).
                      débito
                                                                           atualiza



                                  Servidor remoto
                                  da conta bancária




o    O ~ervlet
     NAO envia                                         o browser envia uma
     uma respos'                                       solicitação HTTP para
     óbvia, Diane                                      o s.ervidor com as
     vê a mesma                                        informações da compra do
     página do                                         livro e o número da ID da
     carrinho de                                       cliente.
     compras e
     pensa ...




112 capítlJ.lo4
solicitação   e íesposta


Nossa história eottlit1ua...

e      o Container envia a solicitação
       para o servlet Checkout para
                                                     o servlet não quer saber se
                                                     Diane está comprando o mesmo
       processamento.                                livro novamente




                                                                    o
    Servidor/Container da                                           C;



       Wickedly Smart



oo     servlet faz um débito eletrônico
     da conta bancária da Diane, pela
                                           oo    banco de Diane aceita o
                                              débito, mas cobra uma tarifa por
     segunda vez.                             ultrapassar seu limit

             débito



                      Servidor remoto da
                        conta bancária
                                           Servidor remoto da
                                             conta bancária


e   Por fim, Diane
    acessa a página
    de Verificar
    Status do Pedido
    e percebe que
    tem DOIS
    pedidos para o
    livro de tricô ...




                                                                  está               113
HTTP métodos




                             Quais dos métodos HTTP você acha que são (ou deveriam
                             ser) idempotentes? (Baseado em seu prévio entendimento da
                             palavra e/ou na história da compra duplicada de Diane que
                             você acabou de ler.) As respostas estão no final desta página.

                             DGET
                             DpOST
                             DpUT
                             DHEAD
                             (Deixamos o CONNECT de fora de propósito, visto que ele
                             não faz parte do HttpServlet.)




                     EXERCITE SUA MENTE
                             o que houve   de errado com a transação da Diane?
                             (E não foi apenas UMA coisa ... provavelmente, o
                             desenvolvedor terá que consertar diversos problemas.)

                             Quais seriam algumas formas do desenvolvedor reduzir
                             riscos como esse?
                             (Dica: talvez elas não sejam todas soluções de
                             programação.)




                            O
                   qGAGI~IT)· h02.1 Url0 ~ Com:l~qGwqo ~qGmbo~Gu~GbG1IT G2bGqgcITcrlO H.1.1h 1"1"
                   drrG AOC~h022V G2CIGAGIrm mQ~oqo qOOG~O urlo-~qGmbo~Gu~G 20S~UJIO(mIT2 Url0
                                               r
                                   H.1.1h I· I qGC1ITW
                   V G2bGc~l!cITCrlO                  OE.1' HEVD G hD.1 como ~qGmbO~GU~G2'   IT~uqIT
114   capitulo 4
solicitação   e re~,post8




Ser idem potente    é BOM.    Significa que você
pode fazer a mesma coisa repetidamente, sem
os indesejáveis efeitos colaterais!



             Idempotente




Cliente            lf~... O servlet ~nyia de volta uma resposta
_~e::;:~>                    /servlet
                   .;::,.. com uma pagma gerada em HTML




                                         O servlet usa os dados
          NÃO Idempotente                do POST para atualizar
                                         o banco de dados.




                                                     você está               115
o posr não é idetltpotente
o HTTP GET é usado apenas para         conseguir coisas
e não deve mudar nada no servidor. Então um GET é,
por definição (e de acordo com a especificação HTTP),
idempotente. Ele pode ser executado mais de uma vez, sem
causar qualquer efeito colateral danoso.
O POST não é idempotente. Os dados submetidos no
corpo de um POST podem ser destinados a uma transação
que não pode ser desfeita. Portanto, tenha cuidado com a
funcionalidade do seu doPostO!

o  GET é idem potente. O POST, não. Cabe a você
ter certeza de que a lógica da sua aplicação pode
lidar com casos como o de Diane, em que o
POST aparece mais de uma vez
                                                                           o GET é sempre
                                                                           considerado
                                                                           idempotente no
                                                                           HTTP1.l ...

                                                                       você encontre códigos
                                                        ...mesmo que        m parâmetroS GET
                                                        no exa me que use        laterals , O u
                                                                                        .
                                                                      .Feitos co          .
                                                         que causem eJ:idem atente de acordo
                                                         seja, o GET ~       ã: HTTP. Mas
                                                          com a especijicaç        ssa impedi-Ia
                                                          não existe nada que p~ todo doGet()
                                                         de- implementartumno~:u servlet. A
                                                                 'd mpoten e
                                                         nao-l e _ GET dos clientes deve
                                                         solicitaçao           . da ue a SUA
                                                          ser idempo~ente, a:Fadosqause um efeito
                                                                                      c
                                                          manipulaçao dos          re em mente a
                                                           negativo. Tenha sem? d HTTP GET e O
                                                           di.(. ren a entre o meto o
                                                           metodo Çdo Ge té')do seu servlet.
                                                              IJ;           J




                                             1!   I.
                                             N~""4:
                                                         "                ,."
                                                       /"4 V4ri"aS (U:fpUM!.S 1'41"4 ti p41IJ.Vr4
                                             "                    "     ,J
                                               liifll!lpfrh"ff     • AJós t.s·h."'tJS   tlslJ."JtJ-a
                                                        paro. I) Hr.,-p! serllle-l- ptJ.ra #';6S
                                             IItJl-I-o.J4
                                             Jel,~tr    &tlt. IJ. "'es""a s6Ilcl-l-tl{ã" p6Je ser

                                             lel-l-a titlas vejes) se", "e"l.tI",a C6"S~;';~d4
                                             "e<:a-l-lvfJ.
                                             IIV          parfJ. fi servliifJr. AJ~s *"tl6 tlSIJ."'tJS
                                                                 ()
                                               Mell!lptJff"ff        p4rIJ. til;er ~tle a ",es",a
                                             StJllct-l-IJ.ftl6sell!lpre re-l-,u'J1fJ.fJ.-'eSIM resp6s-l-a
                                             e AJíJ,( p4rtl «'-3er !tlf tI-'4 s6li'cl-l-aftl6      "tliJI   ff'"
                                             AJi.AJHuJ,( eler-l-6 c6laffr4/.

116           4
solicitação         e res:posta


o que detenMit1a se o browser ettviará utMa
solicitação tEr ou POSr?



  <A HREF=••ttp://www.wickedlysmart.com/index.html/••click here</A>
           h                                        >




  POST
                  t
  <form method="POST"

    <select name="color"
                          Se   !lãcê J)ISSílf
                          itle+-t.t.ld"'PfJSr;

                          ClIl'iaSaitlewh:J
                         action="SelectBeer.do">
    Select beer characteristics<p>
                           size="l">
                                                        eXf1i'cl-/-4it1el1-1-e

                                                     t!11.f.ã<"J)

                                                    ele seI':    PfJSr




       <option>light

       <option>amber
       <option>brown                                i:.                    1                      ""
                                                    UflltJ.l1dDD lISl/M't6 c/lctJ.116bC+l'AtJ Sth;;MI-r;  n   12         1/ 6S
       <option>dark                                        ••• J_
                                                               _            ""        _,                  ~         J •• J   '"
     </select>                                     flJ.l'l'Al/1f["'f'"1'6S fJ.(),
                                                                          S      e'I1Vtl1t&llr6S
                                                                                            1 1'16C61'f6 &llrfJ. StUlCI-r"fJ.CfJ.iJ
                                                                                                                           J
     <center>                     ~                p{)Sr:AJes-k:            exeitlf/t.l;     tofJ. óitlel?-k:
                                                                                                 s               lIit1ftl.I'~e+NJ;
       <input type="SUBMIT">
     </center>                                     ,                                        1
                                                                                              é
                                                   Ct.ftitlfJ.dt'JCt.lll!il' e ó lIa!(J1" ti. <(Jrfl61?> l'eleN!I?-I-e

  </ form>                                         ti C61' da cel"v~tI. ~lIe c l/SlIal"lt:. se!ecI6I?tJl/ (c!fJ.I'fJ.;
                                                   ...
                                                   fJ.l/1bfJ.l';
                                                               itll1ll'l'()Wi 4V escl/I'a).




         t
o que acot1tece       se você NÃO disser tMethod=~~POSr~~
                                                       t10seu <foYiM>?

                 ?I             ""I                                        IIp          1/

              Yf!s-/-a vej) I1tU'J I1el?t.VII11I1e+t,(),d =
                                  t.a                                            os-r        41l'1l
  <form   action="SelectBeer.do">
    Select beer characteristics<p>
    <select   name="colorH     size="l">
      <option>light
      <option>amber
      <option>b:r;own
      <option>dark
    </select>                                    !JrtfJlf!Jr;    ., 3l/e (wm-k:ce             C.,1I1 f(J,I'~e+-1'6S
                                                                                                    "S                         3l/4I?d"
    <center>
      <input type="SUBMIT"> ~                    DN
                                                  VSV:1'16      cli'Co.    I1lJ 96htJ 11
                                                                                       sv$K4.I-r;1/         se   lJ   1(JI'II1V':l'i6
    </center>
  </form>
                                                 114lJ
                                                     flJS SlIl      lIWi    lI1e+t.6d= PfJS-r            ?




                                                                                                      você está aqui           !o'      117
formulários        e HTTP


o vosr         NÃO é       O   padrão!
Se você não colocar method="POST" no seu formulário, o
padrão será uma solicitação HTTP GET. Isso quer dizer que o
browser envia os paràmetros no header da solicitação, mas este é
o menor dos seus problemas. Em virtude de a solicitação chegar
como GET, significa que você estará com um problemão no
momento da execução, se você tiver no seu servlet apenas um
doPostO e não um doGetO'


Se você fizer isto:


      <form
               r                   no
                      IJeP1t.VII1 1I1e+t.fJtJ=rOsr
                    action="SelectBeer.do">
                                                     n                     /
                                                         P1fJfef'lI1vllJ.l"to
                                                                                Il
                                                                                rrrllA.L




E depois isto:
      public       class   BeerSelect    extends   HttpServlet         {

         public       void     doPost(HttpServletRequest         request, HttpServletResponse    response)
                                                                       throws IOException,  ServletException

              Ii    code here




Você terá isto:

      ERRO! Se o seu formulário HTML usa GET em vez
      de POST, você TEM que ter o doGetO na sua classe
      servlet. O método-padrão para formulários é GET.
I




r:        E se eu quiser suportar tanto GET
    como POST em um único servlet?
                                                                 I:     Os desenvolvedores que querem
                                                                 dar suporte a ambos os métodos geralmente
                                                                 colocam a lógica no doGetO, e fazem com
                                                                 que a implementação doPostO delegue
                                                                 poderes àquela doGetO:

                                                                       doPost() method delegate to the
                                                                       doGet() method if necessary.
                                                                       public void doPost( ... )
                                                                                         throws ... {
                                                                          doGet(request,   response);


    118 capítulo 4
solicitação        e resposta


Etwiattdo e utilizattdo            UtMúttieo parâtMetro

Formulário HTML

   <form    method="POST"           action="SelectBeer.do">
     Select       beer   characteristics<p>
     <select       name="color"      size="l">


          <option>amber          o 6r()wser       el'llll"ar:    1I11D.
                                                                      tleS.f.D.S 1JlIfI..f.r6 6.Pcães 1'10.
          <option>brown                ./ ,.,
                                 S6IiCiT"lJ.jfJ.();D.SS()CI'"4tla   6
                                                                C611 I'I()lIe       U c616r IJ"• nu'
                                                                                                   D

       <option>dark
       <option>light         ~   eXell1lj>16;"C()IM' •• D.1I6erll•
     </select>
     <center>
        <input type="SUBMIT">
     </center>
   </form>




Solicitação HTTP POST
   POST    /advisor/SelectBeer.do           HTTP/l.l
   Host: www.wickedlysmart.com
   User-Agent:   Mozilla/5.0    (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:l.4)
   Gecko/20030624    Netscape/7.1
   Accept: text/xml,application/xml,application/xhtml+xml,text/htm1;q=O.9,text/
   plain;q=O.8,video/x-mng,    image/png, image/jpeg, image/gif ;q=O.2,*/*;q=O.1
   Accept-Language:    en-us,en;q=O.5
   Accept-Encoding:    gzip,deilate
   Accept-Charset:    ISO-8859-1,utf-8;q~O.7,*;q~O.7
   Keep-Alive:   300
   Connection:   keep-alive
                                            L.eIil'l6re-se;
                                                         "'"      é () 6r()wser      311e5eNJ. es.f.fJ. s6Ite,..f.fJ.{;()~ I
                                                                                                           ,
                                                   V6Ce 1'146
                                                            frects4           se fN!lJclIffJ.r          t'1I cri't;.-IfJ..JIiI'IfJ.S
                                                                                                                                    e
 Eor=~
                                            O,ss"iJ SlIe elfJ.se fD.rece 311fMUi6lIelil'l              "4   ser'lti:((Jr •••


 Classe servlet

   public       void   doPost(HttpServletRequest                 request,    HttpServletResponse                    response)
                                                                            throws IOException,                    ServletException

         String    colorParam      = request.getParameter(~color");

           //     mais   códigos    esclarecedores              aqui...      ~

                                                                                  Is.f.6     c6,-"cti:(e C61i1'1
                                                                                                              ()
                                                                                                               I
                                                                                  I'I()lIe /'I() flJrlllIlfJ.rii~




                                                                                                     você está aqui"                    119
formulários parâmetros




Et1Viat1do e usat1do dois parâ'ltetros


   Formulário HTML

   <form    method~"POST"          action~"SelectBeerTaste.do">
      Select     beer     characteristics<p>
      COLOR:
      <select      name=Ucolor"         size=fTl">

        <option>light
        <option>amber
        <option>brown
        <option>dark
      </select>
      BODY:
      <select      name="body"         size="l">


        <option>medium
                                   V   :n"owst.r     e'1VU~l'a "",a «es-rfJ.S -r1'!f!S tJP5tiff.S
                                                     '"                                 U          /I
        <option>light
        <option>heavy          J                          •       !
                                 Ir. Sf:;lict..fajfJ.iJ) fJ.SSf:;cta«(J, J f:; ii'1@"'t
                               . '14 i.                                CO'"       J....       N
                                                                                            b@~;
      </select>
      <center>
        <input         type="SUBMIT">
      </center>
   </form>



   Solicitação HTTP POST
    POST ladvisorlSelectBeerTaste.do       HTTP/l.l
    Host: www.wickedlysmart.com
    User-Agent:   Mozilla/5.0    (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:l.4)
    Gecko/20030624    Netscape/7.1
    Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,textl
    plain;q=0.8,video/x-mng,    image/png, image/jpeg,image/gif  ;q=0.2,*I*;q~0.1
    Accept-Language:    eD~us,en;q=0.5
    Accept-Encoding:    gzip,defiate
   ·Accept-Charset:    ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive:   300
    Connection:   keep-alive




   Classe servlet

   public       void    doPost(HttpServletRequest                  request,    HttpServletResponse            response)
                                                                              throws IOException,            ServletException

       String colorParam  ~ request.getParameter{~color");
       String bodyParam ~ request.getParameter(~body");
           IImais código aqui

                                                          f}J.u'~:IfJ.l't';'vei
                                                                 1                S..ft~t'15
                                                            «fJ.I'J::   ea               h",   f) 110./01'


120
solicitação e resposta




             Você pode ter vários valores para um único
             parâmetro! Isto significa que você precisará
             que o getParameterValues() retorne um array,
             e não um getParameter() que retorne uma
             String.
Veja lst9!
Alguns tipos de entrada de dados, como um grupo de checkboxes, podem ter mais
 de um valor. Isso quer dizer que um único parâmetro ("tamanhos", por exemplo)
 terá diversos valores, dependendo de quantos boxes o usuário assinalou. Um
fonnulário em que o usuário possa selecionar diversos tamanhos de cerveja
 (indicando que ele está interessado em TODOS aqueles tamanhos) será algo
 como:

   <forrn rnethod=POST
     action="SelectBeer.do">
      Seleet beer characteristics<p>
      Can Sizes: <p>
      <input type=checkbox  name=sizes      value="12oz">    12 oZ.<br>
      <input type=checkbox  name=sizes      va1ue="16oz">    16 oZ.<br>
      <input type=checkbox  name=sizes      value="22oz">    22 oZ.<br>
      <br><br>

      <center>
        <input type="SUBMIT">
     </center>
   </form>


No seu código, você usará o método getParameterValuesO      que retoma um array:

    String   one = request.getParameterValues(~sizes")        [O];

    String   [] sizes   = request.getParameterValues(~sizes");


Se você quiser ver tudo no array, só por diversão ou teste, pode usar:

    String [] sizes = request.getParameterValues(~sizes");
    for(int x=O; x < sizes.length   ; x++) {
       out.println(~<br>sizes:  ~ + sizes[x);



(Considere que "out" é um PrintWriter que você obteve da resposta)




                                                               Você   está aqui"     121
o objeto l-fttpSe!VletRequest


Aléltt dos parâlttetros,     O que Ittais eu pOSSO
obter de Ultt objeto Reques11

As interfaces ServletRequest e HttpServletRequest possuem
uma tonelada de métodos que você pode chamar, mas você
não precisa memorizar todos eles. Sozinho, você realmente
deveria ver todas a API para javax.servlet.ServletRequest
e javax.servlet.http.HttpServletRequest,   mas aqui nós só        Interface ServletRequest
veremos os métodos que você mais usará no seu trabalho (e        Gavax.servlet. ServletRequest)
que podem também aparecer no exame).                                    <. <.mterjace>>


No mundo real, você estará com sorte (ou sem sorte,            getAttribute(String)
dependendo de sua perspectiva), se usar mais de 15%            getContentLengthQ
da API de solicitação. Não se preocupe se não ficou            getInputStreamQ
claro para você como ou por que você usaria cada               getLocalPortQ
uma delas; nós veremos mais detalhes de algumas delas          getRemotePortQ
(principalmente os cookies) mais adiante.                      getServerPortQ
                                                               getP arameter(String)
                                                               getP arameter Values(String)
 A plataforma do cliente e a informação do browser             getParameterNamesQ
                                                               Ii MUITOS outros métodos ...
   String client      request.getHeader(~User-Agent");



 Os cookies associados a esta solicitação
                                                                Interface HttpServletRequest
   Cookie[] cookies        request.getCookies();             Gavax. servlet.http.HttpServ letRequest)
                                                                         <: <:Tnterjace>>   ..
                                                                      HTTPServletReauest
 A sessão associada a este cliente                              getContextPathQ
                                                                getCookiesQ
   HttpSession session          request.getSession();
                                                                getH eader(String)
                                                                getlntHeader(String)
                                                                getMethodQ
 O Método HTTP da solicitação                                   getQueryStringQ
                                                                getSessionQ
   String    theMethod       request.getMethod()        ;       Ii MUITOS outros métodos ...


 Um stream de dados da solicitação
    InputStream input       request.getlnputStream();




122 capítuío 4
solicitação   e res:posta


                               Nã9 exlst~m
                      Yetbuntas Idl9tas
r:    Por que algum dia eu iria querer obter uma InputStream da solicitação?


I:   Com uma solicitação GET, não há nada além da informação header da solicitação. Em outras
palavras, não há corpo com que se preocupar. MAS ... com um HTIP POST, há informação de corpo.
Na maioria das vezes, tudo o que interessa em relação ao corpo é retirar os valores dos parâmetros (por
exemplo, "color=dark") usando o request.getParameterO, mas esses valores podem ser enormes. Se você
quer analisar a fundo tudo o que chega com a solicitação, você pode usar o método getlnputStreamO. Com
ele você pode, por exemplo, destrinchar todas as informações do header e processar byte a byte o payload
(o corpo) da solicitação, copiando imediatamente para um arquivo no servidor, talvez.


r:  Qual é a diferença entre getHeaderO e get/ntHeaderO? Pelo que eu posso dizer, headers
são sempre Strings! Até mesmo o método getlntHeaderO leva uma String representando o
nome do header; então, para que serve o int?


I:  Os headers têm um nome (como "User-Agent" ou "Host") e um valor (como "Mozilla/5.0 (Macintosh;
U; PPC Mac OS X Mach-O; en-US; rv:1.4) Gecko/20030624 Netscapel7.1" ou .. ww.wickedlysmart.com ..).
                                                                               w
Os valores retomados dos headers estão sempre no formato String, mas para alguns casos, a String
representa um número. O header "Content-Length" retoma o número de bytes que compõe o corpo da
mensagem. O header HTIP "Max-Forwards", por exemplo, retoma um valor inteiro, indicando quantos
hops (saltos de roteadores) a solicitação pode fazer. (Você pode querer usar este header se estiver
tentando fazer um trace da solicitação, que você suspeite estar presa em um loop em algum lugar.)
Você pode obter o valor do header "Max-Forwards"       usando o getReaderO:
   string forwards         request.getHeader(~Max-Forwards");
   int forwardsNum       = Integer.parselnt(forwards);


E isso funciona perfeitamente. Mas se você soubera valor que o header deve assumir como int, você
pode usar o getlntHeaderO como um método de conveniência para poupá-Io da etapa de conversão
da String para int:
   int forwardsNum       = request.getIntHeader(~Max-Forwards");




                 getServerPortO,        getLocalPortO      e getRemotePortO        são confusos!

                                                           A diferença entre getLocalP~rtQ
      o getServerPortQ    deveria ser auto-                e getServerPortQ é mais sutzl: o
     explicativo ... até que você se perguntasse           getServerPortQ diz "para qual porta a "
     para que serve então o getLocalPortQ.                 solicitação foi inicialmente ENVIADA? ,
      Vamos começar pelo mais fácil.~       .               enquanto que o getLocalPortQ diz "em qual
                                                                                        RAR?" S· tem
      getRemotePortQ. Primeiro v~ce vaz ?"                 porta a solicitação FOI PA        .,   ~n:, _
      perguntar "remoto em relaçao a quem ...               uma diferença, porque emb?r.a as so!zcztaçoes
      Neste caso, já que é o servidor q~em so!zczta,        sejam enviadas para uma umca porta (a
       remoto é o CLIENTE. O cliente e remoto na            qual o servidor está escutando), o servzdor
       vzsao do servz·dor. Logo getRemotePortQ
         . -             ".,,'                               encontra uma porta local diferente para cada
      significa "obter a porta do cltente . Ou se~a,         thread, para que a aplicação possa atender a
      o número da porta do cliente de ~nde partm             vários clientes ao mesmo tempo.
      a solicitação. Lembre-se: se voce for um
      servlet, remoto significa cliente.
revisão do cicio da vida



Revisão: Cielo da vida do servlet e API                                      «inter ace»
                                                                          ·avax.servlet.Servlet
                                                             service(ServletRequest, ServletResponse)
                                                             init(ServletConfig)
                                                             destroyO
                                                             getServletConfigO
      o  Container inicializa um servlet carregando a
                                                             getServletInfoO
      classe, invocando o construtor-padrão do servlet
      e chamando o método initO do servlet.

      o método   initO (que o desenvolvedor pode                      j avax.servlet.GenericServlet
      anular) é chamado apenas uma vez no ciclo
                                                             service(ServletRequest,  ServletResponse)
      de vida do servlet, e sempre antes do servlet
                                                             init(ServletConfig)
      atender a qualquer solicitação do cliente.
                                                             initO
                                                             destroyO
      o método   initO dá ao servlet acesso para os          getServletConfigO
      objetos ServletConfig e ServletContext, que o          getServletInfoO
      servlet precisa para conseguir informações sobre
                                                             getInitParameter(String)
      a configuração do servlet e a aplicação web.
                                                             getInitParameterN amesO
                                                             getServ letContextO
      o Containertermina com a vida de um servlet
                                                             log(String)
      chamando seu método destroyO.                          log(String, Throwable)

      o servlet  passa a maior parte da sua vida
                                                                                         .~.




      rodando um método serviceO para uma                                                      I
      solicitação do cliente.                                        j avax.servlet.http.HttpServlet
                                                             service(HttpServletRequest,            HttpServletResponse)
      Cada solicitação para um servlet roda em uma           service(ServletRequest,      ServletResponse)
      thread separada! Só existe apenas uma instância
                                                             doGet(HttpServ IetRequest, H ttpServ IetResponse)
      para qualquer classe servlet.
                                                             doPost(HttpServletRequest,         HttpServletResponse)
                                                             doHead(HttpServletRequest,            HttpServletResponse)
      Seu servlet quase sempre estenderá o javax.
                                                             doOptions(HttpServletRequest,           HttpServletResponse)
      servlet.http.HttpServlet, do qual ele herda uma
      implementação do método serviceO, que traz um          doPut(HttpServletRequest,         HttpServletResponse)

      HttpServletRequest e um HttpServletResponse.           doTrace(HttpServletRequest,           HttpServletResponse)




                                                                                               i
                                                             doDelete(HttpServletRequest,           HttpServletResponse)
      o HttpServlet estende o javax.servlet.GenericServlet   getLastModified(HttpServletRequest)
      - uma classe abstrata que implementa a maioria dos
      métodos básicos do servlet.

                                                              com.wickedlysmart.examples.MyServlet
      o GenericServlet   implementa a interface Servlet.
                                                             doPost(HttpServletRequest,
                                                             HttpServletResponse)
      As classes servlet (exceto aquelas relacionadas        myBizMethodO
      aos JSPs) estão em um dos dois pacotes: javax.
      servlet ou javax.servlet.http.

      Você pode anular o método initO e deve anular
      pelo menos um método de serviço (doGetO,
      doPostO, etc).



124    capitulo 4
solicitação   e re::;posta


Revisão: HffF e HttpServletRequest



 Pontos de bala


     Os métodos doGetO e doPostO do HttpServlet               Interface ServletRequest
     levam um HttpServletRequest e um
                                                             Uavax.servlet. ServletRequest)
     HttpServletResponse.
                                                                    <<interfaee> >
     O método serviceO determina se o doGetO ou                     ServletReaªesL
     o doPostO rodará, baseado no método HTTP           getAttribute(String)
     (GET, POST, etc.) da solicitação HTTP.
                                                       IgetContentLengthO
     As solicitações POST têm um corpo; as              getInputStreamO
     solicitações GET, não, mas as solicitações
                                                        getLoealPortO
     GET podem ter parâmetros anexados à VRL
     da solicitação (algumas vezes chamada              getRemotePortO
     "query string").                                   getServerPortO

     As solicitações GET são idempotentes por           getParameter(String)
     herança (de acordo com a especificação HTTP).      getParameter Values(String)
     Elas devem ser capazes de rodar várias vezes,      getParameterNamesO
     sem causar nenhum efeito colateral no servidor.



                                                                          t
     As solicitações GET não devem mudar nada no
                                                        Ii MUITOS outros métodos ...
     servidor. Mas você pode escrever um método
     doGetO não-idempotente e maldoso.
                                                         Interface HttpServletRequest
  .• O POST é não-idempotente por herança e cabe                Gavax.servlet.http.
     a você projetar e codificar sua aplicação, de             HttpServletRequest)
     forma que, se o cliente enviar uma solicitação                         I
     duas vezes por engano, você possa cuidar disso.               <<interfaee> >
                                                                 HTTPServletReauest
     Se um formulário HTML não diz
                                                        getContextPathO
     explicitamente "method=POST", a solicitação
     é enviada como um GET e não como POSTo Se          getCookiesO
     você não possui um doGetO em seu servlet, a        getHeader(String)
     solicitação falhará.
                                                        getIntHeader(String)
     Você pode receber parâmetros da solicitação        getMethodO
     com o método getParameter("paramname").     O
                                                        getQueryStringO
     resultado é sempre uma String.
                                                        getSessionO
     Se você tem múltiplos valores de parâmetros        Ii MUITOS outros métodos ...
     para um determinado parâmetro, use o método
     getParameterValues ("paramnane") que retoma
     um array de Strings.

     Você pode obter outras coisas do objeto
     solicitação, como headers, cookies, uma
     sessão, a query string e um stream de dados.




                                                                    você está                 125
o objeto HttpServletResponse


Etrl'ão,essa foi a Solicitação ... vejatMos
agora a Resposta

A resposta é o que volta para o cliente. Aquilo que
o browser recebe, analisa e retribui ao usuário.
Tipicamente, você usa o objeto response para
conseguir um stream de saída (geralmente um
Writer), e você usa este stream para escrever o
HTML (ou outro tipo de conteúdo) que retoma para
o cliente. Contudo, o objeto response tem outros
                                                                                                                    !   A
métodos além do IIO output. Veremos alguns deles                                                                   yoce usa a
com mais detalhes.

                                                                                                                   apenas pata envIal- dad9s
      interface ServletResponse                                                                                    de volta     9
             Gavax.servlet.
            ServletResponse)                                                                                       Você chama
         <<interface> >
   ---_
        ServletResonse
          ..   _----------------.-.-----.-----_.--------.-----   . __ ... _   .....   __   .... _.,
                                                                                                                   resp9sta: setConte.nf7jpei) e
    etBuiferSizeO
   setContentTypeO
                                                                                                      l/I#itJ.ts   gefVdtetD.

    etWriterO
                                                                                                                   DepoIS dIss9>v9cê estadt
  ~etoutputStreamo
    etContentLengthO                                                                                               tétZendo sImplesmente
   'IMUITOS outros métodos ...
                                                                                                                   pata escl"evet o
                                                                                                                   alg9 mms) no
                                                                                                                   ]tlas Í9cê tamlJém pode
                                                                                                                   a resposta pm-a
                                                                                                                   outt9sheadets.          ettOS
   addCookieO
   addHeaderO
   encodeURLO
   sendErrorO
   setStatusO
   sendRedirectO
    'IMUITOS outros métodos ...




126            capíitulo 4
solicitação   e resposta




 Espere um momento ... Eu
pensei que não íamos enviar
   HTML de um servlet,
porque é horrível formatá-
10 para o stream de saída ...




         o
         o                      Usando a resposta para o I/O

                                Tudo bem, deveríamos estar usando JSPs em vez de
                                enviar HTML de volta no stream de saída a partir de um
                                servlet. Formatar um HTML para enfiá-Io no método
                                príntlnO do stream de saída é penoso.

                                Mas isso não significa que você nunca terá que trabalhar
                                com um stream de saída do seu servlet

                                Por que?

                                1)   Seu provedor de hospedagem pode não suportar
                                     JSPs. Existem vários servidores e containers mais
                                     antigos por aí que suportam servlets, mas não JSPs,
                                     então, você fica "preso".

                                2)   Você não tem a opção de usar JSPs por algum outro
                                     motivo, como um gerente chato que não permite
                                     usar JSPs porque em 1998 seu cunhado lhe dissera
                                     que os JSPs eram ruins.

                                3)   Quem disse que HTML era a única coisa que você
                                     poderia enviar de volta em uma resposta? Você pode
                                     devolver outras coisas em vez de HTML ao cliente.
                                     Algo para o qual um stream de saída faça sentido.




                                                              você está aqui"         127
enviando bytes na resposta



ItMagit1eque você queira mviar UtMJAR para o cliet1te...
Digamos que você tenha criado uma página para downloads onde o
cliente pode baixar códigos a partir de arquivos JAR. Em vez de enviar
de volta uma página HTML, a resposta contém os bytes representando o
JAR. Você lê os bytes dos arquivos JAR e os escreve no stream de saída
dos dados da resposta.




o    Diane está desesperada para fazer
     o download do J AR com um código
     do livro que ela está usando para
     aprender servlets e JSPs. Ela acessa                                    o Container envia a
     o site do livro e c1ica no link "código    o browser    envia uma       solicitação para o servlet
     jar", que se refere a um servlet           solicitação HTTP para        CodeReturn (mapeado para o
     chamado "Code.do".                         o servidor com o nome        nome "Code.do" no DD) para
                                                do servlet requisitado       processamento.
                                                ("Code.do").


                                           ~




      o J AR inicia   o download na                              o servlet    CodeReturn recebe
      máquina do cliente. Diane                                  os bytes    para o J AR, recebe da
      está satisfeita.                                           resposta    um stream de saída e copia
                                                                 os bytes    representando o J AR


                                               A resposta HTTP contém
                                                   agora oS bytes que
                                                  representam o J AR.




                                                                                 resposta




128 capítulo 4
solicitação     e resposta


o código servlet        que faz o dowt1load do JAR
   Ii   um monte    de imports         aqui


  public    class    CodeReturn           extends   HttpServlet          {


        public   void   doGet(HttpServletRequest                  request,           HttpServletResponse             response)
                                                                        throws        IOException,         ServletException

                                                                                      IJ:S 3Vfl'fll>aS ~ve a/l'tJwsel'
                                                                   ~                  I'fccl'Jt.e5Q 3Vf is+o e ClII>
           response. setContentType              ("application/jarU)             ;     IA;e'" ClII>Ji..-r;!ilAJ ••1'J-ra<1l;
                                                                                      Vf"(, J I114Q rr 1Vl.l-;• '" JN
                                                                                      Ct:Jl'Jft'iClNI.JMSti +ib{J Je C<1lI'J#tJJe.
           ServletContext          ctx = getServletContext();                         pP.N. ~F QppltcU.-hêl1{jal'r, n
           InputStream       is    =   ctx.getResourceAsStream("/bookCode.jarU);


                                                                   It-
                                                                   . ~                    -r'
                                                                                          .s..S+e. .lI'; apfl'JlJ.S FI Je-lI>e VII>
                                                                                                                        •••
           int read = O;
           byte[]    bytes    = new byte[1024];
                                                                                          s+reall> Je el'J+l'aJIJ. pQrlJ.     (J
                                                                                                                                        n
                                                                                          I'f!CClI'Só ct.all>aJa bQâ/<:CI,lJe,jO:I'

           OutputStream       os = response.getoutputstream();)



                         =
              os.write(bytes,
           while «read             is. read read); !=
                                        0, (bytes»                -1)    {           ,J
                                                                                      >
           os. flush();           1.s+a    é a PfAl'#   fVI1Jfi.lI>e~aIJ          é
                                                                             1I>4S apel1t1.s ClII>        xl   tJ S{"II>IpI<!s!   I
           os. close ();      lJaJa espectal)           S4~el1#     lê tiS   bj#s            Jó JI}Je     e 4S escreve       PfU'Q      tJ

                                                                                     de
                                  s+l'efi.íJ'l, de sa;Ju. ~(le l1:s CÓl'Jse.5V{"'II1tlS tJtje.+tl respós+a.


                                                        Não ex'lst~m
                                              YerguntLls Idl9télS
f:  Onde estava localizado o arquivo JAR
"bookCode.jar"? Em outras palavras, onde o método
getResourceAsStreamO PROCURA para localizar o
arquivo? Como você lida com o caminho?


I:    O getResourceAsStreamO requer que você
inicie com uma barra ("t'), que representa a raiz
da sua aplicação. Já que a aplicação foi chamada
de JarDownload, então a estrutura de diretórios
é semelhante à figura. O diretório JarDownload
está dentro de webapps (o diretório-pai para todos
os outros diretórios da aplicação), e dentro do
JarDownload nós colocamos o WEB-INF e o código
JAR em si. Assim, o arquivo "bookCode.jar" está
situado no nível raiz da aplicação JarDownload. (Não
se preocupe, nós entraremos em maiores detalhes
sobre a estrutura de diretórios de distribuição quando                                                 web.xml
chegarmos no capítulo que trata da distribuição.)
                                                                                                      você está                         129
tipo de conteúdo



Opa. Qual      éo     problettta COttto tipo do cot1teúdo?
Você deve estar surpreso com esta linha:
   response.setContentType(~application/jar")        ;
Ou pelo menos deveria. Você tem que dizer ao browser o que você está
devolvendo, para que ele possajazer a coisa certa: abrir uma aplicação
"assistente", como um leitor PDF ou um player de vídeo, criar um HTML,
salvar os bytes da resposta como um arquivo de download, etc. E já que
você está aí se perguntando, sim, quando nós dizemos tipo do conteúdo,
queremos dizer a mesma coisa que tipo MIME. O tipo do conteúdo é um
header HTTP que deve ser incluído na resposta HTTP.




       Caramba, obrigado Servidor. É
      gentil de sua parte me informar
       que tipo você está enviando de
       volta. Voudeixar o Quicktime
        player pronto para o vídeo...

                       D
                       o                                                  Tipos MIME comuns:
                                                                          text/html
                                                                          application/pdj
                                                                          video/quicktime
                                                                          application/java
                                                                          image/jpeg
                                                                          application/jar
                                                                          appl ication/octet-stream
                                              Servidor/ Container
                                                                          application/x-zip



    Você não precisa memorizar um monte de tipos do conteúdo.


          o Você deve saber o que o setContentTypeO jaz e como usá-lo, mas você
          o  não precisa saber nem mesmo os mais comuns tipos de conteúdo, exceto
                 o text/html. O que você precisa saber sobre o setContentTypeO
         .laxe     geralmente é de senso comum ... por exemplo, não será bom para
                   você mudar o tipo de conteúdo DEPOIS de ter escrito o que vai
                  para o stream de saída da resposta. Óbvio. Isso quer dizer que
         você não pode configurar um tipo de conteúdo, escrever algo e, em seguida,
    mudar o tipo de conteúdo e escrever outra coisa. Pense um pouco: como o
    browser lida com isso? Ele só pode tratar um tipo de COISA da resposta de cada
    vez.
   Para ter certeza de que tudo junciona bem, o que você deveria jazer (e em
   alguns casos é um requisito) é sempre chamar o setContentTypeO primeiro,
   ANTES de chamar o método que gera o stream de saída (getWriterO ou
   getOutputStreamO). Isto garantirá que você não terá conflitos entre o tipo de
   conteúdo e o stream de saída de dados.



130               4
solicitação   e res:po,sta


                       Nã.9 eXIstem

              ferh'untélS idl9télS

r:   Por que você tem que definir o tipo de
conteúdo? Os servidores não podem descobrir
                                                         r:    Espere um segundo ... por que você
                                                         precisaria usar um servlet para enviar de volta
isso a partir da extensão   do arquivo?                  aquele arquivo JAR, quando você pode ter o
                                                         servidor enviando-o como um recurso? Em
                                                         outras palavras, por que não fazer com que o
1:A maioria dos servidores pode, para conteúdo          usuário clique em um link que vá para o JAR
estático. No Apache, por exemplo, você pode              em vez do servlet? O servidor não pode ser
configurar os tipos MIME mapeando a extensão             configurado   para enviar o JAR diretamente
do arquivo (.txt, .jar, etc.) para um tipo de conteúdo   sem sequer PASSAR pelo servlet?
especifico, e ele usará isso para configurar o
tipo de conteúdo no header HTIP. Mas estamos
falando sobre o que acontece dentro de um servlet        1: Sim. Boa pergunta.    Você PODERIA
quando NÃO HÁ nenhum arquivo! É você quem                configurar o servidor de forma que o usuário
está enviando de volta a resposta; o Container não       dique em um Iink HTML que o leve, digamos, ao
tem idéia do que você está enviando.                     arquivo JAR localizado no servidor (assim como
                                                         qualquer outro recurso estático, como JPEGs e

r:   E com respeito ao último exemplo onde
você lê um arquivo JAR? O Container não
                                                         arquivos de texto), e o servidor simplesmente o
                                                         enviaria na resposta.
                                                         Mas ... estamos considerando que você tenha
pode ver que você está lendo um JAR?                     outras coisas que queira fazer no servlet ANTES
                                                         de enviar de volta o stream. Você pode, por
                                                         exemplo, precisar que a lógica no servlet que
1: Não. Tudo o que fizemos      do servlet foi          defina qual arquivo JAR a enviar. Ou você pode
ler os bytes de um arquivo (por acaso era um             estar devolvendo bytes que você esteja criando
arquivo JAR), e escrever de volta esses dados            ali mesmo, na hora. Imagine um sistema em que
para um stream de saída. O Container não faz             você recebe parâmetros do input do usuário e os
idéia do que fazíamos quando líamos aqueles              usa para gerar dinamicamente um som que você
bytes. Pelo o que ele saiba, nós estávamos lendo         devolve. Um som que não existia antes. Ou seja,
a partir de um tipo de informação e escrevendo           um arquivo de som que não se encontra em lugar
algo completamente diferente na resposta.                algum no servidor. Você acaba de criá-Io e agora
                                                         está enviando-o na resposta.

r:   Como eu posso descobrir
tipos comuns de conteúdo?
                                      quais são os
                                                         Então você está certo, talvez o nosso exemplo
                                                         de enviar apenas um JAR localizado no servidor
                                                         seja meio manjado, mas por favor ... use sua
                                                         imaginação e enfeite-o com tudo aquilo que
                                                         você puder adicionar para torná-Io um servlet
1:   Faça uma busca no Google. Sério. Novos             de verdade. Talvez seja algo tão simples como
tipos MIME estão sendo adicionados todo o tempo,
                                                         inserir um código no seu servlet que - junto
mas você pode encontrar facilmente listas na Web.
                                                         com a devolução do JAR - escreva alguma
Você também pode dar uma olhada nas suas
                                                         informação no banco de dados sobre este
preferências do browser por uma lista daqueles que       usuário em particular. Ou talvez você tenha que
foram configurados para seu browser, e também pode
                                                         checar para ver se ele está liberado para fazer o
checar seus arquivos de configuração. Novamente,
                                                         download deste JAR, baseado em alguma coisa
você não precisa se preocupar com isto para o exame
                                                         que você tenha detectado no banco de dados.
e provavelmente não lhe causará muito estresse no
mundo real também.




                                                                               você está                131
printWriter   e OutputStream


Você tetM duas opções para saída: caracteres ou bytes
Isto é apenas um simples java.io, exceto pela Íllterface
ServletResponse que oferece apenas duas opções de
streams para escolher: ServletOutputStream para bytes ou
PrintWriter para dados em caracteres.
~ Printwriter
Exemplo:

    PrintWri ter wri ter = response                .AnUtmm                             Você DEVE
                                                                                       memorizar estes
    writer.'.ff''''p(''sorne         text and HTML");
                                                                                       métodos
Usado para:                                                            Você tem que saber isso para o exame.
                                                                       E é uma armadilha. Repare que para
Exibir dados de texto para um stream de caracteres.                    escrever para um ServletOutputStream
Embora você ainda possa exibir dados em caractere                      você writeO,porém, para escrever
usando o OutputStream, é ele que você utilizará para                   para um PrintWriter você ... printlnO!
tratar seus dados em caractere.                                        É comum considerar que você escreve
                                                                       para um escritor, mas não. Se você já
                                                                       usa o java.io, já passou por isso. Se não,
                                                                       lembre-se:

                                                                       printlnO para um PrintWriter
~ OutputStream                                                         writeO para um ServletOutputStream

Exemplo:                                                               E não se esqueça de que os nomes dos
                                                                       métodos para obter o stream ou o escritor
    ServletOutputStream            out       response.                 perdem a primeira palavra, conforme
    getOutputStream()                                                  segue:
                                                                           ServletOutputStream
    out·CiiIII(aByteArray)           ;
                                                                                response.getOutputStream()

                                                                           Pr:intWriter
Usado para:                                                                     response.getWriter()

    Escrever qualquer         outra coisa!                             Você precisa reconhecer nomes FALSOS,
                                                                       como:
                                                                                       er()       "


                                                                                          ream ()
                                                                                          er ()
                                                                                                       l   ís.f.es AJj,O
                                                                                                       ) exts.f.elPof



       Para 5va Ii1{tif'lrla{it:;;       f) fi,iÍ'IWf'i+ef'   PIaverdade e~ac{j.fa        {j
       5ef'lI!e+ov.fpv.f.5.frealrl.          Ov s!i"J t:;f1.1),Wrl.f.et'   +elrl vlrla t'e{et'~âà
      pua     til   Set'lIle+ov.fpv.f.5.ft'ealrl      e de1eja t:;s ct.alYladaspat'a ele.
       trpei1tJ.s
                vJl1. s.frefJ.1Pl e sfJ.fdade "adas v"l.f.a para a c1te~J
                                d                                                          IrlQS(j
       PrI),-ANt't.f.et' (J elYlbe1ejatkdlct<;I1QJ1da
                                                   lYIé.f.ad()sde 4/.f.<;J1:vel Ctlf4j'!S
       de .f.t'l'J..f.fJ.t' Cl'J.f'ac+eres,
                        as




132                  4
soliCitação   e res.:posta


Você pode configurar headers de resposta,
você pode adicionar headers de resposta
E você pode querer saber qual é a diferença. Mas pense
nisso por um segundo e faça o exerCÍcio.


 Correlacione a chamada ao                  Trace uma linha do método HttpResponse para o seu comportamento.
 método com o seu comportamento             Nós fizemos o mais óbvio para você.
                                                      Adiciona um novo header e um novo valor na
 response. setHeader (ftfoo", ftbar");                resposta, ou acrescenta um outro valor para um
                                                      header existente.
                                                      Um método de conveniência que substitui o valor
 response.addHeader(ftfoo",      ftbar");
                                                      de um header existente por seu valor integral, ou
                                                      acrescenta um novo header e um novo valor na
                                                      resposta.
                                                      Se um header com este nome já existir na
 response. setlntHeader    (ftfoo", 42);
                                                      resposta, o valor é alterado por este. Ou então,
                                                      acrescenta um novo header e um novo valor na
                                                      resposta.



Bem fácil quando você os vê todos juntos.
Mas para a prova, você deve memorizá-Ios, pois se na
próxima terça-feira o cara no final do corredor perguntar:
"Qual é o método de resposta que me
permite acrescentar um valor para um header
existente?", você possa dizer, sem pestanejar:
"É o addHeader, e ele possui duas Strings,
para nome e valor." Assim mesmo.
O setHeaderO e o addHeaderO acrescentarão
um header e um valor na resposta, se o header
(o primeiro argumento para o método) ainda
não estiver lá. A diferença entre configurar e
adicionar aparece quandô o header está lá.
Nesse caso:

setHeaderO sobrescreve o valor existente
addHeaderO adiciona um novo valor

Quando você chama o setContentType
("text/html"), você está configurando um
header como se dissesse:
setHeader("content-type", "text/html");
Então, qual é a diferença? Nenhuma ...
considerando que você digite corretamente o header
 "content-type". O método setHeaderO não vai reclamar
se você escrever errado o nome dos headers - ele
simplesmente acha que você está adicionando um outro
tipo de header. Porém, algo dará errado lá na frente, já
que agora você não configurou corretamente o tipo de
conteúdo da resposta!
                                                                                  você está                133
redírecionando    a



Mas     algutMas vezes você tMestMO não quer
lidar COtMa resposta ...


Você pode decidir que algo diferente trate a resposta para a sua
solicitação. Você pode ou redirecionar a solicitação para uma
URL completamente diferente, ou despachá-Ia para algum
outro componente da sua aplicação (geralmente um JSP).




Redirecionando



o     no cliente digita uma URL
      O browser ...                     e   servidor/Container para o
                                            A solicitação vai           8   O servlet decide que a
                                                                            solicitação deve ir para
                                                                            uma URL completamente
                                                                            diferente.




                                                                                          e
                                                                                            /
e   O browser recebe a resposta, vê
    o código de status "301" e procura                                        o
    por um header "Location"                                                 O servlet chama o
                                                                            sendRedirect(aString)   na
                                                                            resposta e pronto




  i i

  .•.•... I
 I! :•,{y.
     ..
                                          li
                                       A resposta HTTP possui um
                                       código de status "301" e um
                                       header "Location" contendo
                                           uma URL como valor




134              4
solicitação    e resposta




oo  browser faz uma nova solicitação
 usando a URL que representava           e                                o
 o valor do header "Location" na         Não há nada de exclusivo         O servidor recebe
 resposta anterior. O usuário          na solicitação, ainda que ela       o que consta na
 pode notar que a URL na barra de       tenha sido ativada por um          URL solicitada.
 endereços do seu browser mudou...          redirecionamento               Nada de e?pecial
                                                                                     aqUi




                 •A resposta HTIP é
                igual a qualquer outra
               resposta ... exceto pelo
              fato de que ela não vem
     o          do local que o cliente
     Cl
                        digi!ou          ~
                                        O browser exibe a nov
                                         página. O usuário fica
                                              maravilhado


     Ifr

                                                                   você está                 135
redirecionamento      do serviet



o redireciotlatltettto      do Servlet faz o browser trabalhar
o redirecionamento  deixa o servlet completamente aliviado. Após perceber que ele não poderá
desempenhar o trabalho, o servlet simplesmente chama o método sendRedirectQ:

   if     (worksForMe)  {
        Ii   trata a solicitação
        else {
         response.sendRedirect{  •• ttp://www.oreilly.com
                                  h                                        ••
                                                                            );



                                                                                                                                     I
                         Ir f//t.L   3l1e' vócê alieI' 3l1e' ~ ;;1'i)wst:1'      lIse piAl'a a sõliér+#.fíia.                        í lssa
                         ., clte"h vê


Usatldo URLs relativas tiOsetldRedirectO
Você pode usar uma URL relativa como um argumento para o sendRedirectO, em vez de especificar o
endereço completo ''http://www ...''. As URLs relativas vêm em dois sabores: com ou sem a barra ("/")
inicial.
Imagine que o cliente digitou primeiramente:

         http://www.wickedlysrnart.com/rnyApp/cool/bar.do

                                                                                  f) CÓ"+fJ,IPíf!1' sde                              Q


chama o sendRedirectO com a URL relati a que NtO inicia                           lÂe s.:;llCl+fJ.jíilJi             lJil'lj'Pít:!

com a barra:                                    I                                 IÂtJ   Ct:iJJ'l/Pít...:;       ~fJrpplca6/~
                 'I                             I
Quando sendRedlrect{"foo ao servlet Cha'tadO "b~.dO", ele
        a solicitação chega stuff.htrnl');      I                                 ptll'+rt,,,+tI;                se ve..cê "íie.. lIStAl' tA
                                                                                  blJ,l'l'IJ" f!S+fJ.PIJ,I'+t tia
                                                                                   "           J
                                                                                       IU::I'íf!sce,,+aJa                                     Je
o header "Location" que ele coloca na res10sta H TP),

relativa à URL da solicitação completa
O Container constrói a URL inicial:             p1
                                             (elIreCisr'dela
         http://www.wickedlysrnart.com/rnyApp/cool/foo/
                                                                    para

         stuff.htrnl

Mas se o argumento      para o sendRedirectO            INICIAR
com a barra:

         sendRedirect   ("/foo/stuff .htrnl");~                             fJr   1141'1'1II;"ó CÕIl'lf!jÕ

O Container constrói a URL completa relativa ao container                   l'eItJ.+ivlJ. ~          1'11I;1'5    Jó
web em si, em vez de relativa à URL original da solicitação.
Assim, a nova URL será:

         http://www.wickedlysrnart.com/foo/stuff.htrnl

                                         I         1
                               "fila" e illI'I Ilpllct!l.-h·Vf)   WebJ sep4N.Jõ
                               JIJ ti.fllca-h·V6     web "~fJrpp".


136     C81PítlJlo4
solicitação    e resposta



                Você não pode
                fazer um
                sendRedirectO
                depois de escrever
                a resposta!

Isto provavelmente é óbvio, mas é a LEI e
nós estamos apenas ratificando.
Se você procurar o sendRedirectO
 na APL você verá que ele envia uma
 IllegalStateException se você tentar chamá-Io
 depois "da resposta já ter sido criada".
 Eles querem dizer com "criada" que a
  resposta foi enviada. Isso significa que os
  dados foram enviados para o stream.
  Na prática, significa que você não pode
  escrever na resposta e depois chamar o
  sendRedirectO!
  Mas um professor exigente diria que,
   tecnicamente, você pode escrever no
  fluxo de dados sem que haja oflush, e o
   sendRedirectO não geraria uma exceção.
   Mas isto seria algo completamente estúpido
    e, por isso, não vamos tocar no assunto. (Se
    bem que ... acabamos defalar. ..)
    No seu servlet, decida, pelo amor de Deus! Ou
                                                                      o sendRedirecto
                                                                      Carrega um o .
    trate a solicitação, ou faça um sendRedirectO
                                                                      String e NÃ bJeto
    para que OUTRA entidade a trate.                                 URL'        O uma
     (Aliás, este papo de "uma vez enviada, já            em l             •
                                                            , e e carreo:
     era" também se aplica à configuração de                'RL             oa uma Str'                .
                                                                . A questão é. o           zng que E uma
     headers, cookies, códigos de status, o tipo de          rrega um objet' À se,!dRedirectO NA-O
     conteúdo e assim por diante ...)                       ssap ara ele um ttO tzpo U'RL• Vr
                                                                                 o C' •
                                                                                                  . oce
                                                                                                  A

                                                                                  a Dtrzng
                                                                completa ou l'              que e uma
                                                              P Utter trans+orm atzva . S.e o Container
                                                                  À               re                -,
                                                        nUma URL            '.Jl     ar uma U'RL
                                                       I.Z
                                                          legalStat E  complet. a, e l e manda relativa
                                                      l              e Xceptzon O                  uma
                                                        embrar que ISTO"                 que confunde é
                                                      send'Red'zrect/T T'RL errado' .
                                                                                 e
                                                      Com '')11:/       ! v, nova("htt· 'P.//www.oreilly.
                                                                                               IL




                                                                                                            137
requesf dispatch



o request              dispateh aeottteee no lado do servidor

E esta é a grande diferença entre um redirecionamento e um
request dispatch - o redirecionamento faz o cliente executar
o trabalho, enquanto que o request dispatch faz com que
outro componente no servidor execute o trabalho. Então,
lembre-se: redirecionamento = cliente, request dispatch =
servidor. Nós falaremos mais sobre o request dispatch mais
adiante, porém, estas duas páginas deverão dar a você uma
noção dos pontos mais importantes.


o Request                 Dispatch

•               O usuário digita a URL do
                servlet no seu browser ..   e   A solicitação vai para
                                                o servidor/Container
                                                                           e    O servlet decide que a
                                                                                solicitação deve ir para
                                                                                outra parte da aplicação
                                                                              . (neste caso, um JSP)




              O browser recebe a resposta
              normalmente e a entrega ao usuário.
                                                    o   O servlet chama
                                                        RequestDispatcher view ~
            . Já que a barra de endereços do              request.getRequestDispatcher(~result.jspn);
              browser não mudou, o usuário não          view.forward(request,response);
              sabe que foi o JSP que gerou a            e o JSP cuida da resposta
              resposta.




        í r .
    f
        f

            ,t.~,
            I

            i




138                       4
solicitação      e res:J)osta


RedirecionatMet1to   X Request Uispateh




                                                   Oi Kari, aqui é o Dan... Eu quero a sua ajuda
                                                  com um cliente. Vou encaminhar para você os
                                                   detalhes de como retornar para ele, mas eu
                                                        preciso que você cuide disso agora.
                                                    Sim. eu SEI que você também tem suas
                                                   necessidades ... sim, eu SEI como a View é
                                                  importante para o MVC ... não, eu não creio
                                                     que consiga outro JSP como aquele ... o
                                                    quê? Não entendi? A ligação está ruim .
                                                     desculpe ... eu não consigo ouvir nada .
Redirecionamento                                                perdendo pacotes ...




                                  Quando um servlet faz o                                   Request
                                  request dispatch, é como se                               Dispatch
                                  pedíssemos que um colega
                                  de trabalho cuidasse de um
                                  cliente. O colega de trabalho
                                  acaba respondendo ao cliente,
                                  mas o cliente não se importa,
                                  desde que alguém o responda.
                                  O usuário nunca sabe que
                                  outra pessoa assumiu o
                                  controle, pois a URL no
                                  browser não muda.



Quando um servlet faz um
redirecionamento, é como se
pedíssemos que o cliente ligasse para
outra pessoa. Neste caso, o cliente é
o browser, e não o usuário. O browser
faz a nova chamada em benefício
do usuário, depois do servlet que
foi originalmente requisitado dizer:
"Desculpe, chame este cara aqui. ../1

O usuário vê a nova URL no browser.




                                                                         você está                    139
revisão do HttpServietResponse



                                 Revisão: HttpServletRespo"se



       Você usa a Resposta para enviar dados de volta para o cliente.
       Os métodos mais comuns que você chamará no objeto response
       (HttpServletResponse) são o setContentTypeO e O getWriterQ.
       Tome cuidado - muitos desenvolvedores acreditam que o
       método seja getPrintWriterO, mas é getWriterO.
                                                                             interface ServletResponse
       O método getWriterO permite fazer I/O por caractere para           (javax.servlet.ServletResponse)
       criar o HTML (ou algo mais) para o stream.
                                                                                  <<interface> >
       Você também pode usar a resposta para configurar headers,                 ServletReslJonse
       enviar erros e adicionar cookies.
                                                                            getBujJerSizeO
       No mundo real, você provavelmente usará um lSP para
       enviar a maioria das respostas HTML, mas você ainda
       poderá usar um stream de resposta para enviar dados
       binários (como um arquivo lAR, talvez) ao cliente.
                                                                            getOutputStreamO
                                                                            setcon.tentTypeo
                                                                            getWriterO             3
                                                                            setContentLengthO
       O método que você chama na sua resposta para receber um              II MUITOS outros
       stream binário é getOutputStreamO.                                   métodos,,,

       O método setContentTypeO diz ao browser como tratar os dados
       vindos na resposta. Os tipos de conteúdos mais comuns são
       "text!html", "application/pdf' e "image/jpeg".                     I••"faee ll,,!rvle'RcsPonsc
       Você não precisa memorizar os tipos de conteúdos (também                 Oavax.servlet.http.
       conhecidos como tipos MIME).                                            HttpServletResponse)

   •   Você pode configurar headers de resposta usando o                        ~~. < < interjace > >
                                                                                      ~       .~

       addHeaderO ou o setHeaderO. A diferença depende de o
                                                                            addCookieO
       headerjá fazer palie da resposta. Se já fizer, o setHeaderO
       irá substituir o valor, mas o addHeader acrescentará um              addHeaderO
       valor adicional à resposta existente. Se o header ainda não          encodeURLO
       fizer parte da resposta, então o setHeaderO e o addHeaderO           sendErrorO
       comportam-se exatamente do mesmo modo.                               setStatusO
                                                                            sendR.edirectO
       Se você não quiser responder a uma solicitação, você pode            l/MUITOS outros métodos ...
       redirecionar a solicitação para outra URL. O browser encarregar"
       se-á de enviar a nova solicitação para a URL que você fornecer.
       Para redirecionar uma solicitação, utilize o
       sendRedirect( aStringURL ) na resposta.
       Você não pode chamar o sendRedirectO após a resposta ter
       sido gerada! Ou seja, se você já escreveu alguma coisa para
       o stream, é muito tarde para fazer um redirecionamento.
       Um redirecionamento de uma solicitação é diferente de um
       dispatch. O request dispatch (mais detalhado em outro capítulo)
       acontece no servidor, enquanto que um redirecionamento ocorre
       no cliente. No caso do dispatch, a solicitação é entregue para
       outro componente no servidor, geralmente na mesma aplicação.
       Um redirecionamento simplesmente informa ao browser para ir
       para uma URL diferente.

140 capítulo 4
solicitação e feSJIIllII




                                         fausa pata
                                         9 café
                   7e4tep~-e~·4



1Como o código do servlet de um método service (por exemplo, doPost () ) obteria o valor do
  header "User-Agent" da solicitação? (Escolha todas as que se aplicam.)

  [J   A. String   userAgent   = request.getParameter(~User-Agent")        ;
  [J   B. String   userAgent   = request.getHeader(~User-Agent");
  [J   C.String    userAgent   = request.getRequestHeader(~Mozilla");
  [J   D.String    userAgent   =   getServletContext()   .getInitParameter(~User-Agent");




2 Quais são os métodos HTTPusados para mostrar ao cliente o que o servidor está recebendo?
  (Escolha todas as que se aplicam.)

  [J   A. GET
  [J   B.PUT
  [J   C. TRACE
  [J   D.RETURN
  [J   E. OPTIONS




3 outra URL? do HttpServletResponse
  Qual método                               é usado para redirecionar uma solicitação HTTP para


  [J   A. sendURL  ()
  [J   B. redirectURL ()
  [J   C. redirectHttp ()
  [J   D. sendRedirect()
  [J   E. getRequestDispatcher      ()




                                                                      você está aqui"         14
teste



    4 Quais    os métodos   HTTP   que NÃO          são considerados idempotentes? (Escolha todas as que se
        aplicam.)



        o      A.GET
        O      B. POST

        O      C.HEAD
        O      D.PUT




    5   Sendo req um HttpServletRequest,               qual das alternativasrecebe um     stream de entrada de
        dados binários? (Escolha todas as que se aplicam.)


        o      A. BinaryInputStream     s       =   req.getInputStream();
        O      B.ServletInputStream         s   =     req.getInputStream();
        O      C.BinaryInputStream      s       =   req.getBinaryStream();
        O      D.ServletInputStream         s = req.getBinaryStream();




    6   Como    você configuraria um    header chamado            "CONTENT     -LENGTH"      no objeto
        HttpServletResponse?       (Escolha todas as que se aplicam.)


        o      A.response.setHeader(CONTENT-LENGTH,"1024");
        O      B.response.setHeader(~CONTENT-LENGTH","1024");
        O      C.response.setStatus(1024);
        O      D. response.setHeader(~CONTENT-LENGTH",1024);




    t   Escolha o trecho do código do servletque recebe um
        imagem,     ou outro tipo binário,no HttpServletResponse.
                                                                        stream binário para escrever uma




        o      A. java.io.PrintWriter           out        response.getWriter();
        O      B.servletOutputStream            out        response.getOutputStream();
        O      C. java.io.PrintWriter           out
                         new PrintWriter(response.getWriter(»;
        O      D.ServletOutputStream            out    =   response.getBinaryStream();




142               4
solicitação e respQSia




8 Quais métodos são usados por um servlet para tratar os dados do formulário vindos de um cIieoIe?
  (Escolha todas as que se aplicam.)

  o     A. HttpServlet.doHead()
  O      B. HttpServlet.doPost()
  O      C.HttpServlet.doForm()
  O      D. ServletRequest.doGet()
  O      E.ServletRequest.doPost()
  O      F.ServletRequest.doForm()




9 Quais dos seguintes   métodos são declarados no HttpServletRequest            ao contrário do
   ServletRequest?    (Escolha todas as que se aplicam.)

  o      A. getMethod ()
  O      B. getHeader ()
  O      C. getCookies   ()
  O      D. getInputStream()
  O      E. getParameterNames        ()




10   Como os desenvolvedores de servlet devem tratar o método service () do HttpServlet
   quando estenderem o HttpServlet?   (Escolha todas as que se aplicam.)

   o     A. Eles devem anular o método service      () na maioria dos casos.
   O     B. Eles devem chamar o método service       () do doGet () ou doPost () .
   O     C. Eles devem chamar o método service       () do método init   () .
   O     D. Eles devem anular pelo menos um método doXXX (como um doPost () ).
                                                        ()




                                                                          você está aqui ~           143
respostas do teste




                                          'fausa pata
                                            9 caté
                                íe~-~4



   1Como o código do servlet de um método        service (por exemplo, doPost () ) obteria o valor do
         header "User-Agent" da solicitação? (Escolha todas as que se aplicam.)

         o    A. String userAgent =

         •
         O
                    request.getParameter("User-Agent");
              B. String userAgent = request. getHeader ("User-Agent") ;
              C. String userAgent =
                                                                                         -If     óp{i<I!J lj lfJ!<l!Js.f.I"GI.
                                                                                         a chalfJ!tl.Ja ct:Jl"l"e-/-a at:J

                                                                                         II'~.f./J#(~~ye passa ô
                    request.getRequestHeader("Mozilla");                                           «6
                                                                                         "76<9e t.eaJel" C"1fJ!6
         o    D. String userAgent =                                                      tlII' p41"~e.f.l"fJ   S.f.I"I~5'
                    getServletContext().getlnitParameter("User-Agent");




    :2 Quais são os métodos HTTP usados para mostrar ao cliente o que o servidor está recebendo?

         (Escolha todas as que se aplicam.)
         o    A. GET
                                                                                (C.~. I  tJ, J <9e.f."J(J$     rrrrr.J
                                                                                                                Ii.o.

         O    B. PUT
         ~    C. TRACE
                                               <9~.f.(JJ(J lISfJ.Je.hpié4<9ft"7.f.ep4NJ.
                                                          ~
         O    D.RETURN
                                                           e "7';" pIJ.NJ.PI"(J«Yj';'"
         O    E.OPTIONS




    .3   Qual método do HttpServletResponse        é usado para redirecionar uma solicitação HTTP para
         outra URL?

         o    A. sendURL  ()
         O    B. redirectURL ()                                cól"l"e+a     e d6$   1fJl~.f.(J«t'I$
         O    C. redirectHttp ()                                  "76   l1#pSel"'il1e+/Cesp6i'1$f!.
         ~    D. sendRedirect()
         O    E. getRequestDispatcher     ()
144 car)ituio 4
solicitação e resposta




4 Quais os métodos HTTP que NÃO são considerados idempotentes? (Escolha todas as que se
    aplicam.)


    o      A.GET
    ~      B. POST      - ~r     áesijl'lJ   c posrJeve       cc~Jv·t/t. as Scli'cí'-hs':es ftu'a
    O      C.HEAD       fl.fva/ljfJ.r"
                          AI
                                         es..f.fl.tlõ.16 serlll«6r.
                                                         ,
                                                                      í", 5era/; fi."'es"'t< a.+VfJ.li'jtií46
    O      D.PUT        ~ac áeve ser apllcaÀa.varias vejes.




5 Sendo req um HttpServletRequest,        qual das alternativas recebe um stream de entrada de
    dados binários? (Escolha todas as que se aplicam.)

    o      A.BinaryInputStream s = req.getInputStream();
    !iir   B. ServletInputStream s = req.getInputStream();    -1Jr ep{i6 ~ eSfect/tca ó
    O      C. BinaryInputStream s = req.getBinaryStream();    ",é.fcJc e c+ipc Je re+iJrl'l"
    O      D.ServletInputStream  s = req.getBinaryStream();C6rre+cs.




6   Como você configuraria um header chamado "CONTENT-LENGTH" no objeto
    HttpServletResponse? (Escolha todas as que se aplicam.)
                                                                                                      (A-PI)
    o      A. response. setHeader (CONTENT-LENGTH,"1024") A- "f54" ~ II'!tls..f.ra
                                                     ; -                                              IJ,
    !iir
           B. response. setHeader ("CONTENT-LENGTH"
                                                ,"1024") itfI41'1elraC6rre..f.a lÃeCÓI'1/i5t1Na.r
    O      C. response. setStatus (1024) ;               VIPo t.eo.lÃer           C"1Po I/rrp
                                                                                       J!)l);
    O      D. response. setHeader ("CONTENT-LENGTH" ; po.rlJ.lPof:'"f"NJSJ •
                                                ,1024)        .•.•_ J.    .s-rr1I'1jS; VII'!
                                                                         represel'1+lIIl'1tl" ., 1'1t1lPoe
                                                                                                        Je.
                                                                         t.ef<Àer) e ., llv+r<!J) <!Jaler.
                                                                                                    v




1    Escolha o trecho do código do servlet que recebe um stream binário para escrever uma
    imagem, ou outro tipo binário, no HttpServletResponse.

    o      A. java.io.PrintWriter    out = response.getWriter();
                                                                                           -A-
    ~      B.ServletOutputStream out = response.getOutputStream();
    O      C.java.io.Printwriter     out =                                                 fS+: l"'cl:Jl"re+a)
                    new PrintWriter(response.getWriter(»;                                  p(Jl"~ve e/fi.lisa
    O      D.ServletOutputStream out = response.getBinaryStream();                         II~ fi.1.,,-PNl"l+er
                                                                                           4rren+o.JIJ f6r
                                                                                           C4f'itc+ere.
                                                                                                       j>       145
respostas do teste




        8 Quais métodos são usados por um servlet para tratar os dados do formulário vindos de um cliente?
            (Escolha todas as que se aplicam.)

            o     A. HttpServlet.doHead()
            ~     B. HttpServlet.doPost()
                                                             - A-s Ófj';eS C e F es-l-';c er;'fJ.dUJ fórafJe
            O     C.HttpServlet.doForm()
                                                             es-hs Irt:J.Ófi6S ,,';c exi's-hlrt.
            O     D. ServletReques       t. doGet ()
            O     E.ServletRequest.doPost()
            O     F. ServletRequest.      doForm ()




        9   Quais dos seguintes métodos são declarados no HttpServletRequest                         ao contrário do
            servletRequest?   (Escolha todas as que se aplicam.)

                  A. getMethod ()
                  B. getHeader ()
                   C. getCookies    ()
                                                   - A-s 6fj';eS A-;      8 e C relereli?l-     se QóSclJIPIfl)'Ie"ffs

                  D. getlnputStream()
                                                   fie fJIi?I4
                                                             scltet-l-4j';6   Hrrp'
                  E. getParameterNames        ()




         10   Como os desenvolvedores de servlet devem tratar o método service () do HttpServlet
            quando estenderem o HttpServlet?   (Escolha todas as que se aplicam.)

            o     A. Eles devem anular o método service             () na maioria dos casos.
-~
            O     B. Eles devem chamar o método service              () do doGet () ou doPos t () .
            O     C. Eles devem chamar o método service              () do método     ini t   () .
            ~      D. Eles devem anular pelo menos um método doXXX() (como um dopost(».

                                   -I}   I)f]';ó b es-I-~ córN~-I-tJ.. s Je.se"vlJlveJares
                                                                     O                                   5erl3.lli?Ie,,-h fJSO,Irt
                                   6S lrté-l-6fiós dóbe+o e J6fAS-I-().




     146 capitulo 4
Sendo uma Aplicação Web

                                                             Você tem que entender como as
                                                            partes de uma aplicação interagem
                                                               e deve respeitar as threads.
                                                              Se você se sair bem nos testes
                                                             preparatórios deste capítulo, eu
                                                                   pouparei a sua vida.

                                                                          o




/
    Nenhum servlet vive sozinho. Nas aplicações web atuais, vários
    componentes trabalham em conjunto por um objetivo. Temos os
    modelos, os contraladores   e as views. Temos os parâmetras e os
    atributos. Temos as classes helper. Mas, como juntar os pedaços?
    Como permitir que os componentes compartilhem informações?
    Como você oculta informações?    Como você toma uma informação
    thread-safe? Sua vida pode depender destas respostas. Portanto,
    certifique-se de que você tenha bastante chá quando for ler este
    capítulo. E que não seja aquela erva descafeinada detestável.




                                                                este   é um   novo cai'Jftl1Io~   147
objetivos do exame oficial da Sun




                                        o~                             s


    o Modelo     do Cotttait1er Web                       Notas sobre a Abrangência:
                                                          Todos os objetivos desta seção serão totalmente
                                                          abordados neste capitulo, exceto o 3.3, que será
    3.1 Para os parâmetros de inicialização do servlet
                                                          abordado no capitulo que trata dos Filtros.
        e do ServletContext: eserevero código servlet
        para acessar os parâmetros de inicialização e
                                                          A maioria dos assuntos deste capitulo aparecerá
        criar os elementos do deployment descriptor       em outras partes do livro, mas se você for fazer a
        para declarar os parâmetros de inicialização.     prova, é AQUI que esperamos que você aprenda
                                                          e memorize os objetivos.
    3.2 Para os atributos de escopo básicos do servlet
        (solicitação, sessão e contexto): escrever o
        código servlet para adicionar, processar e
        remover os atributos; dado um determinado
        cenário, identificar o escopo adequado para
        um atributo e as questões relacionadas a
        multi-threading em cada escopo.


    3.3 Descrever os elementos do modelo do                ./   íXpliCfí.dó   111)   Cfí.p':lvle.   Sue
        container para o procf:ssamf:nto de<;      L___         .fr/J..f.ti.sóbre I)S Fn.frfJs.
        solicitações: Filtro, cadeia de Filtros,
        wrappf:rs para solicitação e resposta e
        recursos Web (sf:rvlet ou página JSP).


/   3.4 Descrever o ciclo de vida do Container para
        solicitações, sessões e aplicações web; criar e
        configurar classes de listener para o ciclo de
        vida do escopo; criar e configurar as classes
        listeners para o ciclo de vida de cada escopo
        e, dado um cenário, identificar o atributo de
        listener adequado para o uso.

    3.5 Descrever o mecanismo RequestDispatcher;
        escrever o código servlet para criar um
        request dispatcher; escrever o código
        servlet para encaminhar ou incluir o recurso
        desejado; e identificar os demais atributos do
        escopo request fornecidos pelo container para
        o recurso desejado.




    148 capítulo 5
atributos e fisteners




 Eu quero que meu endereço de
  e-mail apareça na página das
cervejas que o meu servlet cria ...
 mas acho que ele vai mudar e eu
não quero ter que recompilar meu
  servlet só para alterar isso ...



               o
               a


                                                                          0
                                      Kith quer co•.•igurar seu e-thail •.• UU, e
                                                     f
                                      •.• o escrevê-Io detttro da classe servlet
                                        ã
                                      Eis o que Kim não quer em seu servlet:

                                      PrintWriter   out = response.getWriter();
                                      out.println(Uplooper@wickedlysmart.comV);




                                      É melhor que ele coloque seu e-mail no Deployment
                                      Descriptor (arquivo web.xml), para que, ao distribuir
                                      sua página, o servlet possa, de alguma forma, "ler"
                                      o seu endereço de e-mail a partir do DD. Assim,
                                      ele não terá que fazer um hard-code do seu e-mail
                                      dentro da classe servlet. Quando quiser alterá-Io,
                                      basta modificar apenas o arquivo web.xml, sem ter
                                      que mexer no seu código servlet original.




                                                                  você está        Ií"   149
parâmetros init



Os Parâtttetros lt1it dão uttta for~

Você já viu os parâmetros de solicitação que podem vir no
doGetO ou doPostO, mas os servlets também podem conter
parâmetros de inicialização.
                                                  Ao

                                              ~ce especi'fi'clJ. li"" pD.f'IJ.""-I/ID.""f!e li"" plJ.f'IJ.""-1I4Il1e.

                                              Si'''''P1es; bas+1J. +er cef'+e;14 Je aye eS~14
No arquivo DD (web.xml):                      J)ílJr;eo      dó ele""elf+ó <'sf!f'vle+> lfiJ J)J).
          <servlet>                                              ~
             <servlet-name>BeerParamTests</servlet-name>
             <servlet-class>TestlnitParams</servlet-class>

             <init-param>
                    <param-name>adminEmail</param-name>
                <param-value>likewecare@wickedlysmart.com</param-value>
             </init-param>

          </servlet>


No código servlet:

          out.println(getServletConfig()    .getlnitParameter(~adminEmail"»);


                                t




150               5
atributos   e lísteners


Você t'lão pode usar os parâtMetros it'lit do
servlet setMque ele teKha sido it'licializado
Você acabou de aprender que seu servlet herda o
getServletConfigO; portanto, você pode chamá-Io de
qualquer método do servlet para conseguir uma referência
ao ServletConfig. Uma vez que você tenha uma referência
ao ServletConfig, você pode chamar o getInitParameterO.            Q..uand9 9 C9ntalnet
Mas, lembre-se, você não pode chamá-Io direto do seu
construtor! A vida do servlet está apenas começando ...
                                                                   In'ldq11za um setvlet~
ele não terá toda a sua funcionalidade até que o Container                  "CJ       f   o
chame o initO.
                                                                   c9nstt91 um UnIC9
                                                                   SetvletC9nllg Péltétele.
                                                                   O C9ntVnel' ~·le~'9S
 IJ/f/)/f de Set"v1e-!-CIJ'7fij
                                                                   péltâmett9s ln'lt d9 setvlet
 pót" e'71//lJ.dlJ. I4vt-l-6 eedIJ••-----:::;
                                                                   éti:tétvésd9 DD e 9S
  I   <ti                            construtor
 í 4'f.Vl 'f.lIe IJ
 set"vle-r ,,6-n::IJt--7.lt
    li 1J1 I!. ..
                            . (S    I C fi)
                                 erv et on 9
                                                       destroyO PétSSét t9 SetVletC9nllg.
                                                                      é

 IJ sell 6!jdIJ
                                                                   Em seguldq~ passa 9
 Sel"vle-!-C6'7fij                                                 SetvletC9nllg          pélta 9
                                                                   mét9d9 InltO do set,let.
fi""'" • se;V1e+       e·••• ··
                           f        sQ(
t"IJd4t" IJSIJté-/-lJdlJs sel"vi"]IJ~
                        de
(dIJbe+oJ dIJR.s+oJ de)J           ele
t"eeebe lIIJt Set"vle-!-ClJ'7flj
                                                Nã9 ex'Istem

                                         fetbuntélS Ídl9tél5
f:   Lá no capítulo anterior você disse que um
servlet requer DUAS coisas para tornar-se um
                                                          I:   Nós não dissemos que o initO carrega um
                                                          ServletConfig porque aquele que você anula
servlet válido e fez-wearing. Você mencionou              não carrega um. Sua superclasse inclui duas
o ServletConfig e um tal de ServletContext.               versões do initO: uma que traz um ServletConfig
                                                          e uma versão de conveniência que é padrão.
                                                          O método init(ServletConfig) que foi herdado
I:   Tudo bem, sim, vamos falar sobre o                  chama o método-padrão initO. Assim, o único
                                                          que você precisa anular é o da versão-padrão.
ServletContext dentro de algumas páginas. Por
enquanto, vamos ver só o ServletConfig, pois é
aí que você especifica os parâmetros init do seu
                                                          Não há regra que o impeça de anular aquele
servlet.
                                                          que carrega o ServletConfig, mas se quiser
                                                          FAZER isso, é melhor que você chame o supero

f:   Espere um pouco! No capítulo anteríor
você disse que podíamos anular o método
                                                          init(ServletConfig)! Porém, realmente NÃO há
                                                          razão para que você queira anular o método
                                                          init(ServletConfig), já que você terá sempre o
initO e ninguém disse uma palavra sequer
                                                          seu ServletConfig chamando o método herdado
sobre o argumento ServletConfig!                          getServletConfigO·

                                                                                  você está aqui ~       151
parâmetros inít do servlet



Os parâtltetros itlÍf do servlet são lidos apetlas UMA
VEZ: quatldo o Cotrtaitler itlicializa o servlet
Quando o ContaÍner cria um servlet, ele lê o DD e cria os pares nome/
valor para o ServletConfig. O ContaÍner nunca lê os parâmetros init
novamente! Uma vez que os parâmetros estão no ServletConfig, eles não
serão lidos novamente até que (ou a menos que) você recrie o servlet.
Pense nisso.

00 Container lê DeploymentosDescriptor
                    O
 para este serv/et, incluindo
                                                    eo      Container cria uma nova instância
                                                         ServletConfig para este servlet
    parâmetros init «init-param»                                       new

                        lê

                                  web.xml




80 Containerpara cadapar de Strings do
 nome/valor
             cria um
                      parâmetro init
                                                     eo     Container dá ao ServletConfig as
                                                         referências para os parâmetros init
   servlet. Considere que temos apenas um.               nome/valor



                    ~
                 new             string
                 Lnew




eo    Container cria uma nova instância
    da classe servlet
                                                   eo Container chama o método initO do
                                                    servlet, passando a referência para o
                                                    ServletConfig
            >c/new           ~

      r•••••..•••..•.•instância de
      J~ontqihej
          ·v·•.••
            >.

                                 MyServlet.class                        Servlet-
                                                                         Config   string
                                                                           ~
                                                                 init(ServletConfig))

                                                                                       instância de
                                                                                   MyServlet .class

152
atributos   e listenets



                                                   Mas é bem melhor que colocá-Io
                                                   na fonte do meu servlet. Tudo
                                                   que eu tenho a fazer é alterar
                                                      o xml e pressionar o botão
                                                    "redistribuir", e o novo e-mail
                                                       estará no ServletConfig


                                                                    o
                                                                    o




f ethuntas Idl9tas
       Nã() exlstliom


                                                                    inteiras sem reinicializá-

r:   Então, bem, onde
está este tal botão
                                r:  É claro que é fácil
                                encerrar e reinicializar o
                                                                    10. Em um ambiente de
                                                                   produção, é assim que você
"redistribuir" no Tomcat?       Tomcat, mas e quanto às            faria. Porém, para teste,
                                aplicações que estiverem           é mais fácil simplesmente
                                rodando? Todas elas têm            reiniciar o Tomcat. Você
1: O Tomcat não                que ser encerradas?!                poderá obter informações
possui uma ferramenta                                               sobre a ferramenta de
administrativa, que                                                 gerenciamento em:
seja simples como um            1: Tecnicamente     sim.           http:/(jakarta.apaehe.org/
                                                                    torneat/torneat-5. O-doei
botão, para distribuição        Encerrar suas aplicações
e redistribuição (embora        para que você possa                 rnanager-howto. htrnl
exista, de fato, uma            redistribuir um servlet é           No mundo real, até uma
ferramenta administrativa       meio cruel, especialmente           redistribuição quente é
                                se houver demasiado                 Importante. E tirar do ar uma
que acompanha o Tomcat).
                                                                    aplicação, simplesmente por
Mas, pense comigo - qual        tráfego em seu site. Mas é
                                                                    causa de uma mudança no
é a pior coisa que você         por isso que a maioria dos          valor de um parâmetro init,
tem para fazer para alterar     Containers de qualidade             pode ser uma péssima idéia.
os parâmetros init de um        permite que você faça uma           Se os valores dos seus
servlet? Você faz uma           redistribuição quente, o            parâmetros init forem mudar
rápida alteração no arquivo     que significa que você não          com freqüência, é melhor
web.xml, fecha o Tomcat         precisa reiniciar seu servidor      que os métodos do seu
(bin/shutdown.sh) e o           ou derrubar nenhuma outra           servlet obtenham os valores
reinicia (bin/startup.sh). Na   aplicação. Aliás, o Tomcat          de um arquivo ou banco
                                inclui sim uma ferramenta           de dados, mas esta prática
reinicialização, o Tomcat
                                                                    resultaria em muito mais
pesquisa seu diretório          de gerenciamento que
                                                                    tráfego sempre que o código
webapps e distribui tudo o      permite distribuir, desfazer        servlet rodar, em vez de uma
que ele encontrar lá.           e redistribuir aplicações           única vez na inicialização.

                                                                            você está aqui ~       153
usando ServletConfig



                                                                j avax. servlet. Serv letConfig
restat1do      seu ServletCot1fig
                                                                        <<interfaee> >
A principal função do ServletConfig é disponibilizar                     ServletCon
os parâmetros init. Ele também pode fornecer um            getlnitP arameter(String)
ServletContext, mas geralmente obtemos o contexto
                                                           Enumeration getlnitParameterNamesO
de uma outra forma e o método getServletNameO
raramente ajuda.                                           getServletContextO
                                                           getServletNameO

No arquivo DD (web.xml):
   <?xml version="l.O"    encoding="ISO-8859-1"?>                         A-   1tIfJ,i"fJ!"là   Jas   peSSfJfJ,S
   <web-app xmlns~"http://java.sun.com/xml/ns/j2ee"
                                                                          1'1111'1CfJ,
                                                                                    lISfJ.      es.fe   1PI:-ftJJll
        xmlns:xsi~"http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation~"http://java.sun.com/xml/ns/j2ee/web-app              2 4.xsd"
        version=rF2.4">
      <servlet>
        <servlet-name>BeerParamTests</servlet-name>
        <servlet-class>com.example.TestlnitParams</servlet-class>
        <init-param>
           <param-name>adminEmail</param-name>
           <param-value>likewecare@wickedlysmart.com</param-value>
        </init-param>
        <init-param>
           <param-name>mainEmail</param-name>
           <param-value>blooper@wickedlysmart.com</param-value>
        </init-param>
      </servlet>
      <servlet-mapping>
        <servlet-name>BeerParamTests</servlet-name>
        <url-pattern>/Tester.do</url-pattern>
     </servlet-mapping>
   </web-app>




Em uma classe servlet:
   package com.example;
   import javax.servlet.*;
   import javax.servlet.http.*;
   import java.io.*;

   public class TestlnitParams     extends HttpServlet     {
      public void doGet(HttpServletRequest       request, HttpServletResponse    response)
                                                      throws IOException,  ServletException
          response.setContentType("text/html");
          PrintWriter   out = response.getWriter();
          out.println("test    init parameters<br>");

           java.util.Enumeration    e = getServletConfig() .getlnitParameterNames();
           while(e.hasMoreElements())      {
           out.println("<br>param     name = " + e.nextElement()   + "<br>");
           }
           out.println("main    email is " + getServletConfig().
    getlnitParameter("mainEmail"));
           out.println("<br>");
          out.println("admin email is " + getServletConfig() .getlnitParameter("adminEmail");




154 cap,ftuJo 5
atributos e /isteners




~                          JSP consegue                   obter os
    parâlMetros               inÍt do servlet?
    o ServletConfig   foi feito para a configuração do servlet
    (não é JSPConfig). Portanto, se você quiser que outras
    partes da sua aplicação usem a mesma informação
    declarada nos parâmetros init do servlet dentro do DD,
    você precisará de algo mais.

    Que tal a lManeira COlMO
                           fizelMos COlMa
    aplica~o da cerveja? Nós passalMOS a
    infortMa~o do lModelo para o JSP usando
    UlMatributo de solicita~o...  ~ se leW!bra? ()H,'ve~s                                                         l'l   CéU"


    Ii             .
       dentro do metodo doPost()   ~~lí'eJTl-eesc~tI                                           JI"~S lia


                                                                         ;l "
    String color = request.getParameter("color");


    List result be be.getBrands(color);
    BeerExpert   ~ ~ new BeerExpert ()                                                    v             I
                                                                                  ""'" se.:tltJD., J I1tJS
                                                                                  Ii,S.f-tJ.I1CIfJ."'tI>S   e VStJ.",ós

    request. setAttribute                   ("s;tes'"                   result)   ;óll4.tibíLO        ptU'tJ.
         •I        "êJ"ciD. es-tabe1ece"'óS                      ti'"             6bffl" a li,fól"hlaii6
     Na selP                ,,)               .   J      '"                              I
      /I IJ.-tf'i'bv-f-ó          114 sDlict-rC.fjfJ.ó        e/)",               PN!C1"s4114"'óS           ptJ.NJ.a

         J,SP;    »1If! I"ecebe :.s-tr;.              sóucr-taífl.l'J)
                   f'f!cebe-1D
         ctJl"Isejfli'tI
    Nós poderíamos ter feito assim. O objeto request nos
    permite criar atributos (considere-os como sendo o par
    nome/valor, onde o valor pode ser qualquer objeto)
    que qualquer servlet ou JSP que receba esta solicitação
    conseguirá usá-Io. Isto significa que para qualquer
    servlet ou JSP para o qual a solicitação é enviada, usa-se
    o RequestDispatcher. Vamos falar em detalhes sobre o
    RequestDispatcher no final deste capítulo. Por enquanto,
    nossa preocupação é passar os dados (neste caso, o
    endereço de e-mail) para os trechos da aplicação que
    deles necessitam, e não apenas para um único servlet.




                                                                                            você está aqui,",                   155
(imitações do ínít parameter



Criar Utlt atributo de solicitação futtciotta ...
tltas só para o JSP que recebe a solicitação                   Mas eu quero mesmo é que TODAS as
                                                                partes da minha aplicação aceSsem o
                                                              endereço de e-moi!. Com os parâmetros
No exemplo da cerveja, fez sentido armazenar as                init, eu tenho que configurá-Ias no DD
informações do modelo para a solicitação do cliente no         para cada servlet e, em seguida, fazer
                                                             com que todos os servlets disponibilizem-
objeto solicitação, pois o próximo passo foi encaminhar
                                                                nos para os JSPs. Que chato, não?! E
a solicitação ao JSP responsável por criar a view. Como o
                                                             pouco prático. Preciso de algo mais global.
JSP precisava dos dados do modelo e estes eram relevantes
apenas para aquela solicitação específica, tudo funcionou.

Mas isso não nos ajuda no caso do e-mail, pois podemos
                                                                                c'
                                                                                o
precisar usá-Io em toda a aplicação! Existe uma forma de
fazermos um servlet ler os parâmetros init e armazená-
los em um lugar onde outras partes da aplicação possam
usá-los. Mas, neste caso, precisaríamos saber qual servlet
seria sempre o primeiro a rodar no momento da distribuição
da aplicação, e qualquer alteração na aplicação poderia
estragar tudo. Não, isso também não funcionaria.




156 capítulo 5
atributos   e Iisteners


               Os parâtRetros itlit do cotttexto dão UtRaforça

               Os parâmetros init do contexto funcionam como os parâmetros init
               do servlet, exceto pelo fato de que os parâmetros do contexto ficam
               disponíveis para toda a aplicação, e não apenas para um único servlet.
               Isso significa que qualquer servlet e JSP da aplicação automaticamente
               têm acesso a eles. Portanto, não precisamos nos preocupar em configurar
               o DD para cada servlet, e quando o valor for alterado, você terá que
               mudá-Io em um só lugar!
                                                                   Jefl:hiQvei'VIi~S() elehie'l.f.6 <.i;'i-l--pIJ.1"4hi>
                                                                                                                       uft
               No arquivo DD (web.xml):                            ufe,,-fl"lJ uf4 elehif!l1-ftl <,stl"vle-f>
                     <servlet>
                          <servlet-narne>BeerPararnTests</servlet-narne>


               / ~ </servlet>
                        <servlet-class>TestlnitPararns</servlet-class>
               (     <context-param>

           f             <param-name>adminEmail</param-name>
           ,             <param-value>clientheaderror@wicked1ysmart.com</param-

       )             value>

   í                 </context-param>       ~                                              e
                                                            ~cê ct}lacavw.I'fi.I"fJ.w.-"ahie lJw.pfJ.rlJ.w.-vaivf!,j
                                                                                                                 ufa
IIU.POJerp,.lJrf./!                 O <.ct}PI+-ex-l----""""'" .fSWtfJ.
                                                            w       lal"w.4 ~ve v6cê Ia'] caw.6Spal"~e_f1"6S I."t.f. Ja
pfJ.l"aw.>vale pfJ.l"Q.
                      rODA               a                  sfrll/Hj   fiJb"l"IJ.tles-fo. Ve'] eles eS~IJ.iJ tle".f.I"EJJ.,
al'licag'iój 1'61"í'S ele J1"iií
                       S{j                                  elew.e".f.t:; 'U#t+e*pal"aw.>;
                                                                        <                       fw. vej Je <.i;'l-l--pfJ.N~hi>
tJ.l1i."t.fJ.Jtl
              fi.l1e"t.Yhi elew.f!I1+a

<'Sfl"vlf..f..>!! CcllJ3ve (j
ptJ.l"tJ.hI> e".f.1"6 ufI/J <.we!rapp>;
           d
hilJ.SFOJeA- de 3Vlai:SaVfr
tleclal"4jCeS <.serllle·h


                   No código servlet:
                     out.println(getServletContext().getInitParameter(~adminEmail"»);


                                             1';                              f) iJ:+6tllJ 5e_fSel"vie+ClJ",ffx+O
   Cada sfl"llle-f            "'trila   Vw.w.e+aJEJ
                                                                              1"e-fIJI"PI!J.;
                                                                                          cvri'óSIJ.iJtl1+-e;i'" t>tJe+6
                                                                                                             l
   5e..f..Servit-I-C"".fex+D  {f~4S JSPs ..f..alrlb~iJ
                                                     .fe"w.                   Sel"lIie-I-Ctm-l-ex+. í VIrI d6S sevs
   IJ.CeSS6 speclo.i 1M C/J,,+ex..f..6).
            e
                                                                              w.&adéJS ~ a 5e+IPli..;..pfJ.r!J.lYle+-eI"O.
                   ou:

                     ServletContext          context   = getServletContext();




           ~         out.println(context.getlnitPararneter(~adminErnail"»;
        A3l1l ,,:s dillitll",ós (J c:d~a tw. J)fJ As par.fes - I"f!cf!be"iló
         4 l"elel"ê"âtJ. da Sel"lIle-I-Ctm+-ex+ e Ct.fllYl!J.Plda w.é+'~Ja
                                                               Sf!lI

               5e-l-Il1l+Pal"tJ.lrle.ferO.
                                                                                                   você está aqui..         157
para/natras init do contexto            X parâmentros ínit do servlet


Leltbre-se da diferett9a ettlre os parâltetros ittit do
servlet e os parâltetros ittit do COtttexto
Aqui está uma revisão das principais diferenças entre os
parâmetros init do contexto e os parâmetros init do servlet. Preste
bastante atenção ao fato de que nos referimos a ambos como
parâmetros init, ainda que apenas os parâmetros init do servlet
recebam a palavra "init" na configuração DD.

   parâmetros init do Contexto                                              parâmetros init do Servlet
                                                       Deployment
                                                        Descriptor

Dentro do elemento <web-app>, mas NÃO                         Dentro do elemento <servlet> para cada servlet
inserido em um elemento específico <servlet>                  específico

   <web-app   ...>                                                <servlet>
     <context-param>                                                <servlet-name>
        <param-name>foo</param-name>                                    BeerParamTests
        <param-value>bar</param-value>                              <servlet-name>
     </context-param>                                               <servlet-class>
                                                                        TestlnitParams
    <!-- outros comandos,                incluindo                  </servlet-class>
   declarações do servlet                -->                           <init-param>
   </web-app>                                                            <param-name>foo</param-name>
                                                                         <param-value>bar</param-value>
                                                                       </init-param>
           1Je.+e &Ue     i'1fJ

            tl1t.f ftU'tA e.S                                       <!-- outros     comandos   -->
                                                                  </servlet>
            Cim+ex.fe.;      CfJ"""

            flJ.l'~e.frds         tl1i.f tl.1J

                                                     Código do Servlet

getServletContext()       .getlnitParameter(~foo");            getServletConfig() .getlnitParameter(~foo");




                                                     Disponibilidade

Para quaisquer servlets e JSPs incluídos                      Somente para o servlet para o qual o <init-param>
nesta aplicação.                                              foi configurado.

                                                              (Embora o servlet possa decidir aumentar sua
                                                              abrangência armazenando-o em um atributo.)




158   CBt)ítulo 5
atributos       e iisl!eflIE.!


ServletCotlfig é Utft por servlet
                                                                            Inicialização da
ServletCotttext é Utft por aplicação                                        aplicação web:
                                                                                  O Container lê o DD e cria um par
Existe um único ServletContext para toda a aplicação e                            de String nome/valor para cada
todas as partes da aplicação compartilham-no. Porém,                              <context-paratn>.
cada servlet na aplicação tem seu próprio ServletConfig. O
Container cria um ServletContext quando uma aplicação é                           O Container cria uma nova
distribuída, disponibilizando-o para cada Servlet e JSP (que                      instância do ServletContext.
se transforma em servlet) na aplicação.
                                                                                  O Container dá ao
                                                                                  ServletContext uma referência
                                                ClJl1ffx-l-"" tia o.pllcai'i"     a cada par nome/valor dos
                                        ~       ClJ4' iS pfJ.r~e+r6s
                                                     t                            parâmetros init do contexto.
                                                                                  Cada servlet e JSP distribuído

                                       ~a6s                                       como parte de uma única
                                                                                  aplicação tem acesso àquele
                                                                                  mesmo ServletContext.

                                                                                    S/~ "s JSPs Sã6
                                                                                    +rfJ.l1sf6r4'fJ.tl6s e"'"

                                                                                r:- servle+s    tle prl'ívlefra
  servletCo'<'
             ~
                    s. ....    ~        s..         ~                              c/use    e +fJ.".béi'l'
                      ervletCOf'          ervletCo'<'                                                      I

                    11
                                                rbar~e-l-"'6s    s.ervletCOf'~
                                                                          .         recebei'l' seils pr6p"'las
 par~e+Js           p(J.r~e';""'i:Js l"i-tt-..j. t"i-tt+
                                                       para D                       Servle+C"l1f~
 1"111+
      para "       para"" Servle+        8      Servle+ C
 Servle+ fJr       l"i-tse""aDS                 l"i-tserMós
  l"i-tserM""s

                                                                                   Se a aplicação for
                 Não confunda                                                      distribuída, existirá
                 parâmetros ServletConfig                                          um ServletContext
                 com parâmetros                                                    porJVM!
                 ServletContext!
                                                                    VeJa Íst9!
  Veja ist9!                                                        S~ ~ua aplicação for distribuída por
   Você realmente tem que saber isso para                           varros s~rvidores (provavelmente em
   o exame, mas confunde. Você TEM                                 um a~bIente de cluster), ela até PODE
   QUE saber que tanto o ServletConfig,                            ter maIS que um ServletContext. O
   como o ServletContext possuem                                   Servl~tContext é único por aplicação
   parâmetros init e ambos usam o mesmo                            ~~s so se a aplicação estiver em uma'
                                                                   ullIcaJVM!
   método getter - getlnitParameterO·
   MAS ... você também tem que saber_                              Em um ambiente distribuído você terá um
   que os parâmetros init do contexto ..sao                        Servl~tC~ntext por JVM. É até possível
   criados com <context-param> (e nao                             que nao.de problemas, mas se você tiver
    dentro de um elemento <sen:le.t»,                             uma. aplIcação distribuída, é melhor
    enquanto que os parâmetros mlt do                             avalIar as conseqüências de possuir
    servlet usam <init-param> dentro das                          contextos diferentes para cada JVM.
    declarações <servlet> no DD.

                                                                                            você está aaui ••           159
servlet   e o contexto do parárnetros init


                                                      campo de retenção magnética, deslizar até o centro
          Nã9 exJst~m                                 da Terra e destruir o planeta.
                                                      Ou talvez nada, porque não existe nenhum
feth'untas Id'i9tas                                   conflito de nomes, visto que você obteve os
                                                      parâmetros através de dois objetos diferentes


r: o    que acontece com a nomeação
                                                      (ServletContext   ou ServletConfig).

inconsistente do esquema? Como podem
os elementos do DD serem <context-param>
e <init-param>, porém no código servlet,
                                                      r:    Se você modificar o XML para alterar
                                                      o valor de um parâmetro init (ou servlet ou
                                                      context), quando o servlet, ou o resto da
AMBOS usam o método getlnitParameter()?
                                                      aplicação, reconhecerão a mudança?

1: Eles não nos solicitaram    para ajudá-Ias a
                                                      1:     APENAS quando a aplicação for
proporem um nome. Se eles tivessem pedido,
                                                      redistribuída. Lembre-se de que nós falamos
é claro que nós teríamos dito que deveriam ser
                                                      sobre isso antes- o servlet é inicializado apenas
getlnitParameterO e getContextParameterO, para
coincidir com os elementos XML no DO. Ou, eles        uma vez, no começo da sua vida, e isso acontece
                                                      quando é dado a ele o seu ServletConfig e o seu
poderiam ter usado diferentes elementos XML -
                                                      ServletContext. O Container lê os valores pelo
possivelmente <servlet-init-param> e <context-init-
                                                      DO quando ele cria estes dois objetos e configura'
param>. Mas não, isto teria absorvido toda a graça
                                                      os valores.
de tentar mantê-Ias corretos.


r:    De qualquer forma, por que eu usaria
                                                      r:   Eu não posso fazer isso configurando
                                                      os valores no runtime? Certamente
<init-param>? Eu não poderia sempre querer
                                                      existe uma API que me permite mudá-Ios
usar <context-param>, de modo que as outras
                                                      dinamicamente ...
partes da minha aplicação poderiam reutilizar
os valores e eu não teria que duplicar o
código XML para toda declaração do servlet?           1: Não, não existe.   Procure no ServletContext
                                                      ou no ServletConfig e você encontrará um getter
1: Tudo depende     de qual parte da sua             (getlnitParameter()), mas você não encontrará
aplicação supõe-se que veja o valor. A sua lógica     um setter. Não existe nenhum setlnitParameterO.
da aplicação talvez requeira de você usar um valor
que você queira restringir a um servlet individual.
Mas tipicamente, os desenvolvedores acham os          r:    Isto é terrível.
parâmetros init do contexto da aplicação inteira
mais auxiliar, do que um dos parâmetros init do
servlet de um servlet especifico. Talvez o uso
                                                      1:      Eles são parâmetros init. Init do latim
                                                      inicialização. Se você considerá-Ias simplesmente
mais comum de um parâmetro do contexto está           como constantes para o momento da distribuição,
armazenado no banco de dados dos nomes de
                                                      você terá a perspectiva correta. Na verdade, isso
procura. Você gostaria que todas as partes da         é tão importante que nós falaremos sobre isso de
sua aplicação tivessem acesso ao nome correto,
                                                      um jeito mais ousado:
e quando isso mudasse, você gostaria de mudar
isso em apenas um lugar.
                                                      Considere os parâmetros init como
                                                      constantes para o momento da
r:    O que acontece se eu der a um parâmetro
init do contexto o mesmo nome de um
                                                      distribuição!
                                                      Você pode obtê-/os no runtime, mas você
parâmetro init do servlet na mesma aplicação?         não consegue configurá-/os. Não existe
                                                      nenhum setlnitParameterO.
1:   O buraco negro do tamanho de uma
molécula criada milagrosamente em um centro
de pesquisas em Nova Jersey vai se livrar do seu


 160 capítulo 5
atributos    e listeners

                                              :
                                             lmã de GeladeIra

     ExercícIos                                  Rea;rume os ímã~ p~ra formar um DD que declara um
                                                 parametro que cOlllcIde com o código servlet:

                                                 getServletContext()   .getlnitParameter("foo");

                                              Você não usará todos os Ímãs!
                                              (Nota: ~uan~o você encontrar <web-app ...>,    lembre-se
                                              d~ ~ue ISSO~ o_nosso ata!h0. para economizar    espaço na
                                              pagllla. Voce nao pode dIstnbuir um arquivo    web.xml, a
                                              me~os que a.tag <web-app> possua todos os      atributos dos
                                              qUaISnecessIta.)




                                            I </servlet>I
                          </param-value>
                                           bar




             Se você se deparar com o "parâmetro init" e não
             souber se significa parâmetro init do servlet ou
                                                                         <servlet-name>
             context, considere como servlef.
Algumas pessoas usam "parâmetro init" para se referirem a
"parâllletro init do servlet". E usam "parâmetro de contexto", ou        BeerTest   < /servlet-name>
mesmo "parâmetro de aplicação", para se referirem a "parâmetro
init do contexto". Portanto, ainda que AMBOS sejam parâmetros de
inicialização - e derivem do método getInitParallleterO -, lembre-se
de que apenas os parâmetros init do SERVLET são listados no DD
como parâmetros init. Assim sendo, a expressão "parâmetro init"
significa "parâmetro init do servlet" por padrão.
                                                                          [:serVlet-param>]
Sabemos que, como desenvolve dor, você será gentil com as outras
pessoas e sempre dirá, explicitamente, se um parâmetro init é um
parâmetro init do servlet ou um parâmetro init do contexto.


                                                                            você está         ~     161
o ServletGontext



o que ",ais você pode fazer co", o seu
ServletCotttext?

Um ServletContext é uma conexão de
JSP ou de servlet com o Container e os
outros trechos da aplicação. Eis alguns
métodos do ServletContext. Colocamos
em negrito aqueles que você deverá
saber para a prova.




                                               < <interjace> >
                                               ServletContext

                                         getlnitParameter(String)
                                         getlnitParameterNamesO
   Db-#/tI 6S pal'~f..f-r6S              getAttribute(String)           Db-#/tI os p4r~e.f-r()s 1;'''+ e
   .;,,.+ f. 4b-#','/espect!lca          getAttributeNamesO
                                                                        IJb+é/tl/ especlli'cli. li..f-rtbv+(;$
   a.f-rl/;v.f-4S                        setAttribute(String)
                                         removeAttribute(String)

        I.I.
   Db-r-e/tl
                               '"
               1;'!6r/tllJ.f,IJes        getMajor VersionO
   slJbre 6                              getServerlnfoO
   U),,+IJ.I;,er.
                                         getRealPath(String)                  íscrevf.           fJ.1'~VlV,IJ
                                                                                         /'1(;            '""e
                                         getResourceAsStream(String)
                                         getRequestDispatcher(String)   1:;--"0   sel'lIt"t'J1'(especlli'c/J
   hlare/tl4S lJ."i"a"h                                                       1'41'Idrl'ca"h)      t)V '76
   "esh        cap:.f-VIIJfJbre
                         s          IJ   log(String)                          Sjsh/tl.'JiI.f-.
                                         // mais métodos
          s+Pts pl4+cheI' •
   }e.e1Jve




162                  5
atributos   ef



                       Você pode obter o ServletContext de duas
                       maneiras diferentes .••

                                              let sempre retém uma referência
            Um objeto ServletConjig do serv        let. Então, não se engane caso
            para o ServletContextserv e
                           'digo palratnesotee;~:eque diga:
            encontre um co                                  tInitParameter ()
                                tservletContext() .ge
            getServletConfig()
                             .ge
            Além de ser válido, faz o mesmo que:
                                           I itparameter O
               .     tservletcontext() .get n
             thJ.s . ge                         , PRECISARIA recorrer ao
                              ,.    vez que voce                   d      ê
             Em um servlet, a UJ1lca          letContext seria quan o voc
             ServletConjig para obt~r S~~t~::: não estendesse HttP~ervl~t oUd
             estivesse numa class; erv etServletContextO que voce ~er ou _o
              GenericServlet (o metodo g        d ALGUÉM usar um metodo n~o-
              GenericServlet). Mas a chan;eC e basta chamar seu próprio metodo
              HTTP é praticamente zero. _ n ao,       '+"so se você encontrar um
                                 os      nao jique conJ~
              getServletContext   ,ma 1 C ifi para obter o contexto.
              código que utiliza o Serv et on gd        a classe que NÃO seja um
                 as e se o código estiver dentr~ . e.u.m or exemplo)? Alguém pode
              ~r:let (uma classe assistente/utllztarw~~lasse e seu código terá que
               ter passado um ServletConjig para e~er a referência para o objeto
               usar o getServletContextO para rece
               ServletContext.




Y:     Como cada parte de uma aplicação               1: Hum,     não. A menos que você tenha uma
 consegue acesso ao seu próprio                        aplicação bem pequena mesmo. Existem formas
 ServletContext?                                       de fazer logging bem melhores. O mecanismo
                                                       mais popular e robusto de logging é o Log4j.
                                                       Você pode encontrá-Ia no site do Apache:
 1:  Para os servlets, você já sabe: chame o
                                                       http://jakarta.apache.org/logj4j
 seu método getServletContextO herdado.
~Para JSPs é um pouco diferente - os JSPs              Você também pode usar a API logging do java.
 têm o que chamamos de "objetos implícitos",           util.logging, acrescentada ao J2SE na versão 1.4.
 e o ServletContext é um deles. Você verá              É legal usar o método ServletContext logO para
 exatamente como o JSP usa o ServletContext            experiências simples, mas em um ambiente real
 quando chegarmos aos capítulos sobre JSP.             de produção você provavelmente vai querer
                                                       usar algo diferente. O livro Java Servtet & JSP
                                                       CookBook, da Q'Reilly, explica muito bem sobre
Y:    Então temos um logging ativo através do          logging de aplicações com e sem o uso do Log4j.
 contexto? Parece MUITO útil!
                                                       O logging não faz parte dos objetivos do
                                                       exame, mas é importante. Felizmente, as
                                                       APls são fáceis de usar.




                                                                                você está   aqui..   163
limitações do parâmetro de contexto




            Detesto estragar a festa do
           seu ServletContext, mas estes
           parâmetro~ init não passam de
          STRINGS! E isso! E se eu quiser
         inicializar minha aplicação com um
          banco de dados DataSource, que      E   se você quiser Uift parâiftetro it1it t1a
           todos os servlets podem usar?
                                              aplica9ão que seja Uift l1afaSource de
                          D                   bat1co de dados?
                          o
                                              Os parâmetros do contexto não passam de Strings.
                                              Afinal, você não pode inserir direito um objeto Dog em
                                              um deployment descriptor XML. (Na verdade, você
                                              poderia representar um objeto serializado em XML,
                                              mas não há nenhum recurso para isso na especificação
                                              do servlet atualmente ... talvez no futuro.)
                                              E se você realmente quiser que todas as partes
                                              da sua aplicação tenham acesso a uma conexão
                                              com um banco de dados compartilhado? Com
                                              certeza, você pode colocar o nome de loolmp do
                                              DataSource em um parâmetro init do contexto. Este
                                              é, provavelmente, o uso mais comum dos parâmetros
                                              de contexto hoje em dia.
                                              Mas então quem faz o trabalho de transformar
                                              o parâI1letro String em uma referência real ao
                                              DataSource que todas as partes da aplicação
                                              possam compartilhar?
                                              Você não pode mesmo colocar este código no
                                              servlet, pois qual servlet você escolheria para ser
                                              Aquele Que Pesquisa No DataSource E O Armazena
                                              Em Um Atributo? Você gostaria mesmo de tentar
                                              garantir que um determinado servlet rodasse sempre
                                              primeiro? Pense nisso.




                                              EXERCITE SUA 1WENTE
                                              Como você solucionaria este problema?
                                              Como você conseguiria inicializar uma aplicação
                                              com um objeto? Considere que você precise da
                                              String parâmetro init do contexto, a fim de criar este
                                              objeto (imagine o exemplo do banco de dados).




164            5
Poxa, se ao menos existisse uma
  forma de ter algo como um método
  principal para minha aplicação toda.
   Algum código que sempre rodasse
  antes de QUAISQUER        servlets ou
                 JSPs ...

               o
               o




 o que ela realtMettte         quer é UtMlistetler
Ela quer escutar um evento de inicialização do contexto, de
forma que ela possa obter os parâmetros init do contexto e
rodar um código antes que o resto da aplicação possa servir
um cliente.

Ela precisa de algo que possa estar situado lá, esperando para
ser avisado que a aplicação foi iniciada.

Mas qual parte da aplicação poderia fazer esse trabalho? Você
não iria escolher um servlet - já que esta não é uma tarefa dele.

Não há nenhum problema com uma aplicação lava simples
standalone, pois você tem o mainOl Mas, se for com um
servlet, o que você faz?

Você precisa de algo diferente. Não um servlet ou lSP, mas
algum outro tipo de objeto lava cujo único propósito na vida seja
inicializar a aplicação (e, possivelmente, não inicializá-la também,
limpando os recursos ao perceber que a aplicação foi encerrada ...).




                                                        você está aqui ~   165
context listener




Ela quer Ult ServletCotttextListet1er                           r                     <: <:interfaee> >
Podemos criar uma classe separada, não
                                                                ~          ServletContextListener
um servlet ou JSP, que possa escutar os
dois eventos principais na vida de um                            eontextlnitialized(s,                                           _
ServletContext - a inicialização (criação) e a                   eontextDestroyed(s:rvletContextEvent)
destruição. Essa classe separada implementa                                            rvletContextEvent)
o javax.servlet.ServletContextListener.                           Javax.servlet S
                                                                                . ervletContextL· lstener                        J
Precisamos de um objeto à parte que possa:
  • Ser notificado quando      o contexto    é inicializado (a aplicação está
      sendo distribuída).

     • Conseguir os parâmetros init do contexto através do
       Serv letContext.

     • Usar o nome de lookup do parâmetro init para fazer uma conexão
       com o banco de dados.

     • Armazenar a conexão com o banco de dados como um atributo,
       para que todas as partes da aplicação possam acessá-la.

  • Ser notificado quando o contexto é destruído (a aplicação é retirada
      do ar ou cai).
     • Encerrar a conexão com o banco de dados.



                                                                                       f) Ils-fePlf!1'    JiJ CiJPI-feX+tJ

                                                                                       é s""'Y'les:      t"'Y'leJr;fi!PI-I-ati
                                                                                       Sel'lIle.fC6P1-k x+t-i's-kl1el'



   public     class    MyServletContextListener         implements    ServletContextListener


       public    void    contextlnitialized(ServletContextEvent                 event)          {
          l/código para inicializar a conexão com o banco                      de dados
          l/e armazená-la como um atributo do contexto
                                                                          l.sf..           '"
                                                                                   iltS SI!l6 4,S j
                                                                                                    m;VI4S    "'6   1,1"        '"
                                                                                  u •••
                                                                         <f.Vft
                                                                         (J        <ICe
                                                                                  •.   l'eceJ,e          A        rIT1CtJ.t:.t'JeS
                                                                                                                            .J

                                                                        v~ Sf!I'V1e.fC.·L xrive ",I-
                                                                                      <lI1"1f':
                                                                                                ~as eX"J,eJr;
       public    void    contextDestroyed(ServletContextEvent                 event)       {
            l/código    para   encerrar     a conexão   com o banco    de dados




166 capítulo 5
Tudo bem, eu tenho uma
  classe listener. O que eu faço
   agora? Onde a coloco? Quem
   a instancia? Como eu passo a
  aparecer nos eventos? Como o
listener especifica o atributo no
     ServletContext correto?


            o
             o




                                +   EXERCITE SUA :MENTE
                                    Qual é o mecanismo que você acha que é
                                    usado para fazer com que um listener seja
                                    parte de uma aplicação específica?

                                    Dica: como você informa ao Container sobre
                                    outros trechos da sua aplicação? Onde o
                                    Container pode encontrar seu listener?




                                                               você está   aqui..   151
usando um ServletContextListener



rufarial:   UtMServletCatttextListetler         sitMples

Agora nós iremos construir e executar um
ServletContextListener. Trata-se de uma simples classe de teste,
para que você veja como todas as partes funcionam juntas. Não
iremos usar o exemplo da conexão com o banco de dados, pois
você precisaria configurar um para fazê-Ia funcionar. Mas os
passos são os mesmos, independentemente do código que você
colocou nos métodos de callback do listener.

Neste exemplo, transformaremos um parâmetro init String
em um objeto real - um Dog. A tarefa do listener é conseguir o
parâmetro init do contexto para a raça do cão (Beagle, Poodle,
etc.) e usar esta String para construir um objeto Dog. O listener
insere o objeto Dog no atributo ServletContext, de forma que o
servlet possa recuperá-Io.

A questão é que agora o servlet tem acesso a um objeto
compartilhado da aplicação (neste caso o Dog), sem precisar
ler os parâmetros do contexto. Se o objeto compartilhado é um
                                                                         lJes.fe eJc(!~/{)J CfI/{)ctU"(!iI'I{)S
Dog ou uma conexão com o banco de dados, não importa. O
                                                                              ViI'I Cã., tl.f!I7.f.I'Ó JtI! ViI'I
importante é usar os parâmetros init para criar um único objeto
que todas as partes da aplicação compartilharão.                                Sel'vle.fC~#1hx.f..



Nosso exemplo Dog:
       •    O objeto listener pede ao objeto ServletContextEvent    uma referência para o ServletContext
            da aplicação.


       •    O listener usa esta referência para que o ServletContext consiga o parâmetro init do
            contexto para "breed", que é uma String que representa uma raça de cão.


       •    O listener usa a String da raça do cão para construir um objeto Dog.


       •    O listener usa a referência para o ServletContext para configurar o atributo Dog no
            Serv letContext.



       •    O servlet que faz o teste na aplicação recebe o objeto Dog do ServletContext e chama o
            método getBreed().




168 capítulo 5
atributos e liste"


Criat1do e usat1do o cotttext          Iistet1er
 Talvez você ainda esteja curioso para saber como o Container
 descobre e usa o listener ... Você configura um listener da mesma
forma que você informa ao Container sobre o resto da sua
 aplicação - através do Deployment Descriptor web.xml!



                                                                 fatél escutat 9sevent9S
o    Crie uma classe listener
                                                                 SetVletC9ntext7 escteva
               <<interfaee> >                                    uma classe l1stenel"
           ServletContextListener

  eontextlnitialized(ServletContextEvent)                        'jpe lmplemente               º
  eontextDestroyed(ServletContextEvent)                          Setvle:tC9ntextLlstenet.
                      Li"
                       •
                       •                                         c919'Lue-an9 dltet9l"19 WEB-
                       •


        MyServletContextListener                                 t~íclasses  e lnt9tme a9
  contextInitialized(ServletContextEvent)                        C9ntéllnel", c919célnd9 um
  contextDestroyed(Serv letContextEvent)
                                                                 element9.
                                                                  1              < l::.'tenel">n9
                                                                                     10



                                                                 Depl9)'ment              Descl"lpt9l".

e Coloque a classe em WEB-INF/classes
                                                  "'"'   /   /
                                       (íSff l1a6 e 6 uAJIC{)      'tljai" paN. 411deela p"de          1"1"   •••




                                          wf.I;-IAJFlcllA.sses      e flJifldel1+l'f! Jiflfll+as Ifl5tJ.l'es
                                            Ó   C"I1+atl1f.i" p60le pi"ÓCflN.1'pe1u clfJ,sses.
                                            ttl,lli,i"eJifl6Ssobi"e as oleJifllJ.isI" ctJ.p{+fllas6~re
                                                                                  P

                                      blS+i"l~flijãa)




e    Coloque um elemento <Iistener> no
     Deployment Descriptor web.xml
                                                                   UJifltJ.          plJ.r. Vãct; e'Jifl 3f1e
                                                                         Pf!1'5f/11+tJ.
          <listener>                                               p(J,rff d@bb el1+ra if} elel'i';f!I1+6
              <listener-class>
                   com.example. MyServletContextListener
                                                                   <:.l" +e
                                                                     fS ~l1ei".
                                                                                >7    íl
                                                                                      e          I1f/Jifl e'''''e
                                                                                                        e
                                                                                                                    I   ,,+.~
              </listener-class>                                    <:sel'vle+> t>{,I s/~/esil'!e",ff     aba/xi!
          </listener>
                                                                   .lã




                                                                                           você está     BUU! ••         169
tutoria I ServletContextUstener



Precisatltos   de três classes     e Utlt 1111
Para o nosso teste com o listener de contexto,
precisaremos escrever as classes e o arquivo web.
xml.
                                                                      <<interfaee> >
Para facilitar nosso teste, colocaremos todas as                  ServletContextListener
classes no mesmo pacote: eom.example                                         .L:::,.
                                                                                I
                                                                                I

o   O ServletContextListener
                                                                                I

                                                                MyServletContextListener
   MyServletContextListener.java
                                                         eontextlnitialized(ServletContextEvent)
   Esta classe implementa o ServletContextListener,      eontextDestroyed(ServletContextEvent)
   recebe os parâmetros init do contexto, cria o Dog
   e o configura como um atributo de contexto.




e   A classe atributo
                                                         Dog(string)
                                                                             Dog


   Dog.java                                              getBreedO
   A classe Dog é simplesmente uma classe Java
   simples. Sua função é ser o valor do atributo que
   o ServletContextListener instancia e configura no
   ServletContext para alimentar o servlet.




                                                                        <<interfaee> >
                                                                    ServletContextListener


e     O Servlet
                                                                          GenericServlet
    ListenerTester.java
    Esta classe estende o HttpServlet. Sua função
    é verificar se o listener funcionou através                            HttpServlet
    do recebimento do atributo Dog oriundo do
    contexto, chamando o getBreedO no Doge
    exibindo o resultado para a resposta (portanto, é
    isso que veremos no browser).
                                                        doGet(HttpServletRequest,HttpServletResponse)




170             5
atributos e listeners



Escrevetldo a classe listetter                                                     <<interfaee> >
                                                                              ServletContextListener
Ela funciona como qualquer outro tipo de listener que                           4'-
                                                                                 I
você já deve estar familiarizado, como os tratadores de                          I
eventos GUl Swing. Lembre-se, tudo que precisamos
                                                                MyServletContextListener
fazer é obter os parâmetros init do contexto para
descobrir a raça do cão, criar o objeto Dog e colocá-lo
dentro do contexto como atributo.                       eontextlnitialized(ServletContextEvent)
                                                                   eontextDestroyed(ServletContextEvent)




    paekage     eom.example;
                                              IlI!iflelVle~.f4 4j4V4Jf.serv1e.f.Serv1e-!-C4"iex.f!-lsie'fer
    import     javax.servlet.*;
                                                                                       ~
    publie     elass    MyServletContextListener          implements      ServletContextListener



       publie     void    contextInitiali.zed        (ServletContextEvent        event)     (

              ServletContext       se = event. getServletContext           (); ~altclflA        a   Servle-!-Ca"ffJf+
                                                                                    IA"eve".f".
              String    dogBreed    = se.getlnitParameter("breed");~
              Dog d = new Dog (dogBreed);<--              erl4 UIVI                US4" c()"iexfIJ            pfJ.NJ.
                                                                                                                    IJbier iJi
                                                .         'fava Da,;              parã..efra        I;'''.f
              se.setAttribute("dog",          d),~                 v
                                                          U.1'4a c()"ieX+a 1'41"4especilicfl.r UIVI .fribu.fa
                                                                                                  4
                                                          (UIVI '.1" "alVle!a!de.faJ Daj. A'jara; aufl"cs
                                                              1
                                                          .fl"ect,cs JfI. 4pli"cfJ.j';asel"ãa CIAj>4jeS receber
                                                                                                       Je
                                                          a V4/al" Ja fl.fl"l6u.fa (iJiDiJij)
      publie     void    contextDestroyed(ServletContextEvent                event)     (


         Ii     nada    a fazer    aqui   ~
                                                       lJ';fJ preciS41V1t;$ "fl.J4 fJ.3Ui. ) DfJj ~ã()pl"ectsfJ.
                                                                           Je            (
                                                       ser Illfl{>fJ••3UfJ.'fJfJ
                                                                   •           fJct>"ieJf.ffJ ierlVll;'a., slj'flli'cfJ.
                                                                               v4ll,;'alijfJ.I"J ·,;'clt,,;'JfJ a
                                                       3ue .ffJJ •• IAj>llc4jÃt>




                                                                                             você está aqui ~            171
o atributo c/ass



Escrevet1do a classe atributo (Uog)
Naturalmente, precisamos de uma classe Dog - a classe que                                         Dog
representa o objeto que armazenaremos no ServletContext,
depois de ler os parâmetros init do contexto.             Dog(string)
                                                          getBreedO

   package     com.example;

   public class Dog {                     Alada de especl'al 4~V". A-pel7fJ.S
      private String breed;               vltla classe Java sl"Ify>les




       public    String   getBreed()


             return   breed;   ""

                               Al6SSI.i     Sfrvle-f. recebel": 6])65 d6     clurhJ6            V.])65
                               3Vf!"      Its-h:~r   C617115Vl"4 C61tl1.i a+l"tbv+~)         et.41t'>A1":

                               " ltlé+ad65e-f.8I"eell!O       "6])65 e (;6f"4r:      111   1"4j4 174

                               resp'cs+a.,ftJ.1"4 3ve f6SS41t6S vê-/4         I7D   br6wser




f:     Eu achei que tivesse lido em algum lugar que os
atributos do servlet tinham que ser Serializáveis ...



1:     Pergunta interessante. Existem vários tipos diferentes de
atributos e se o atributo tem que ser Serializável só interessa aos
atributos Session. E apenas quando a aplicação está distribuída
em mais de uma JVM é que ele é realmente importante. Nós
falaremos mais sobre isso no capítulo das Sessões.
Não existe nenhuma necessidade técnica para que qualquer
atributo (incluindo os atributos Session) sejam Serializáveis,
embora você possa considerar criar todos os seus atributos
Serializáveis por padrão. A não ser que você tenha uma boa razão
para NÃO fazê-Ia.
Pense nisso: será que você está mesmo seguro de que ninguém
jamais vai querer usar aqueles objetos como argumentos ou retornar
valores como parte de uma chamada remota a um método? Você
 pode mesmo garantir que alguém que use esta classe (Oog, neste
caso) nunca rodará em um ambiente distribuído?
Então, embora tornar os atributos serializáveis não seja uma
exigência, você deveria sempre que pudesse.




 172 caoi'tu}o5
atributos    e lístenelS


Escrevet1do a classe servlet
Esta é a classe que testa o ServletContextListener.                                HtipServlet
Se estiver tudo funcionando corretamente no
momento em que o método doGetO do Servlet
rodar pela primeira vez, o Dog será esperado como
um atributo no ServletContext.                                                    ListenerTester


                                                             doGet(HttpServletRequest,HttpServletResponse)
   package     com.example;

   import    javax.servlet.*;
   import    javax.servlet.http.*;
   import    java.io.*;
                                                 Ai."" "e especta/ a-# aJlIl •••~el74S lI~
                                                 sel'v/el- C6/t1l1/t1
   public    class     ListenerTester      extends    HttpServlet

      public    void    doGet   (HttpServletRequest          request,       HttpServletResponse    response)
                                                               throws       IOException,   ServletException

         response.setContentType("text/html");
         PrintWriter   out = response.getWriter();

         out.println("test          context    attributes      set by listener<br>");



          out.println("<br>");                                                      ~
                                                                        .                lr.,.lIt 6!rk~6s     6
         Dog dog = (Dog) getServletContext(}                 .getAttr1bute("dog"};~U                   /
                         7                                                              //65 a-l-n.vf.s    d{J
                          :.. Ai';6 eSJlIf.ja 6 c:/CY/6f!                               SeI'VIe+e6~J.                   Se
          out. println ("Dog' s breed         is: " + dog. getBreed ());                 6   /ls+el7f,F' -IlII1Ci611(J(Jj
                                                               .p                        " !J65 VIJ.tes-l-al' alt
                                                     é
                         Se 4'56 17';6-IlIl1t:l611IJYj 1r~IJI JlIe                       IrAiríS    allf. () ~é+()ti()
                         tif.SC6bl""'e~6S •••Vfl.~6S recebel' lI/tI el7tJrhle            serv,i:e sr.;tl ct.a~tlti6
                         AillIlRs,irhl'íxcerl·t'1I7   se +e17-1-'U'hlfJSt.ahllJ.l'
                                                                       c                 pe/fJ. l'lm.etl"fI.ve;
                                                                                              p
                         65e-l-8reetiO      e l"Jã6t.6wer    l"Jel"Jf"y~
                                                                       !J65




                     o getAttributeO   retorna_
                   precisa fazer a conversao
                                                       un;.~~~~:;~:~Cê
                                                           .      "
                             O    orna uma String. Ou seja, voce
     Mas o getInitParameter
                    t    resposta o ge tAttributeO ' mas o retorno .
                               retd                             S do
     precisa conver er a             'buído diretamente a uma trmg.
     getlnitParameterO pode ser atrl      1 s códigos escritos noS exames que
     portanto, não seja iludi~o por aque e
      não usam uma tA "b t ("dog"l' '"
                     conversao:         ~              t:         1I
                                                       '('''fl.d6 ••
      Dog d = ctx.ge ttrl U e       /'
      (Considere ctx como um ServletContext.)



                                                                                             você está aqui       il>'    173
configurando um Iistener no DD



Escrevet1do O Peploytltettt Pescriptor
                                                                          Í-s-h é"       tU'SVt"l6     wd.J(~·J
                                                                                                              !'IU'6.
Agora, informamos ao Container que temos um
                                                                          es+tJ.   4p'tca{;6)        deJ1+,..1J   d6
listener para esta aplicação, usando o elemento       web.xml             dl"'e+:"'k~ wí8-IAlF
<listener>. Este elemento é simples - só precisa
do nome da classe. Só isso.

   <web-app      xmlns=''http://java.sun.com/xml/ns/j2ee''
        xmlns:xsi~''http://www.w3.org/2001/XMLSchema-instance''
        xsi:schemaLocation=''http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
        version="2.4">


      <servlet>
        <servlet-name>ListenerTester</servlet-name>
        <servlet-class>com.example.ListenerTester</servlet-class>
      </servlet>


      <servlet-mapping>
        <servlet-name>ListenerTester</servlet-name>
        <url-pattern>/ListenTest.do</url-pattern>

      </servlet-mapping>                                                                   '" ••"'",'i1t.f
                                                                                                i
                                                      Pl"ecisa",,,s Je          li'" !,((NA"',"

      <context-param>                                  dI> C6I'IffJ(.f6       !,41't1. ti. fJ.p'tCIJ.{;(J.
        <param-name>breed</param-name>
                                                       t>   lls.fe"e'"     p,..eósfJ.    Jele   plJ.f'tI.
        <param-value>Great       Dane</param-value>
                                                       CIJJ1S+f'lIt,..     6 b65
      </context-param>


      <listener>
        <listener-class>
              com.example.MyServletContextListener
        </listener-class>
      </listener>


    </web-app>




174 capítulo 5
atributos   e lísteners




             1'11'.9   e:x1stem

  YerhUntels Ídl9tétS

r:  Espera aí... como você está informando ao
Container que isso é um listener para os eventos
do ServletContext? Não parece ser um elemento
XML para o <Iistener-type>, ou algo que diga para
que tipo de evento serve este listener. Porém, eu
percebi que você tem um "ServetContextUstener"
como parte do nome da classe. É assim que o
Container entende? Pelo nome?


1: Não.   Não há nenhuma convenção de nomes.
Nós só fizemos assim para tornar mais óbvio o tipo
de classe que criamos. O Container descobre ao
inspecionar a classe e notar a presença da interface
listener (ou interfaces; um listener pode implementar
mais de uma interface listener).



r:   Isto significa que existem outros tipos de
listeners na API servlet?


I..: Sim, existem vários outros tipos de listeners que
 falaremos em um minuto.




                                                          você está aqui ~      175
compilando e distribuindo    o lísterner test


COtMpile e   distribua                                         L.eirJJI'f;"'Sf',   rubfj 1;veperhl7j4      40

                                                        ..;-   .rev welJspps fica 41;1./1·caA/4VItI CDltl a
                                                                                           (
Vamos fazer tudo funcionar. Eis os passos:                     SIIfJ.
                                                                    fl':'1"ifi. es+ro.Jw.fJ.,,(e Jll'el-f.I'Í4sJ



  o Compile as três classes                                       f       If I'fi.") ffJ.1'fJ.es.fa tJ.p'tca{i/J.
                                                                          ís-h Jtl'e.ff.I'It> Jeve es.f41'
                                                                          Jei'1.f1'6 JE) Ji'l'e.ff.I'It>
       Elas estão todas no mesmo pacote ...
                                                                          webàpfs       P(lJ 1;/II'IC4+



  e Crie uma nova aplicação no Tomcat
       • Crie um diretório chamado listenerTest
          e coloque-o dentro do diretório
          webapps do Tomcat.
       • Crie um diretório chamado WEB"
          INF e coloque-o dentro do diretório
          listenerTest.

       • Coloque o seu arquivo web.xml       nO
         diretório WEB·INF.
       • Crie um diretório de classes dentro do
         WEB-INF.
       • Crie uma estrutura de diretórios
          dentro das classes, que coincida com
          a estrutura do seu pacote: um diretório
          chamado com, que contém o exemplo.




  e    Copie seus três arquivos compilados
       para dentro da estrutura de diretórios
       da sua aplicação no Tomcat
         listenerTest/WEB-INF/classes/com/example/Dog.class
         listenerTest/WEB-INF/classeS/com/example/ListenerTester.class
         listenerTest/WEB-IN~/Classes/com/example/MyServletContextListener.class




  e Coloque o seu Deployment Descriptor web.xml
    no diretório WEB-INF desta aplicação.
         listenerTest/WEB-IN~/web.xml




  e    Distribua a aplicação, desligando e reiniciando
       o Tomcat.


 176            5
atributos   e Iitlatf•.    Q




VatBOS experitBetttar

Abra seu browser e vamos direto ao servlet. Nós não nos incomodamos
em fazer uma página HTML. Por isso, iremos acessar o servlet,
digitando a URL do mapeamento servlet no DD (ListenTest.do).




  A raça do cão é: Great Dane




rroubleshootit1g
Se você receber um NullPointerException, você não recebeu um Dog
do getAttributeO. Verifique o nome da String usado no setAttributeO e
certifique-se de que ele coincide com o nome da String que você está
usando no getAttributeO.

Verifique novamente seu web.xml e tenha certeza de que o <listener> está
registrado.

Tente olhar nos logs do servidor para descobrir se o listener está mesmo
sendo chamado.

Para complicar o máximo possível, nós atribuímos nomes sutilmente
diferentes. Queremos ter certeza de que você está atento a como estes
nomes são usados e quando dar a eles o mesmo nome. É difícil dizer
Como os nomes afetam sua aplicação.

Nome da classe Servlet: ListenerTester.class

Nome do diretório da aplicação: IistenerTest

URL padrão mapeada para o servlet: ListenTest.do




                                                                           você está aQui ~       177
atributos de sessão    X segurança   contra threads



A história cot1pleta ...

Eis o cenário desde o início (inicialização da aplicação) até o final (o
servlet rodando). Você verá no passo 11 que resumimos a inicialização do
servlet em um grande passo.

o   O Container lê o Deployment Descriptor
    para esta aplicação, inclusive os
                                                      e   O Container cria um novo
                                                          ServletContext, que todas as partes
    elementos <Iistener> e <context-param>.               da aplicação compartilharão.
                                                                           new


                                      web.xml
                                                                                              ServletContext



e   O Container cria um par de Strings nome/
    valor para cada parâmetro init do contexto.
                                                              e   O Container dá aos parâmetros
                                                                  nome/valor as referências do
    Suponha que tenhamos apenas um.                               ServletContext.


                       new




e   O Container cria uma
    nova instância da classe
                                            00 Container chama o método
                                                contextInitializedO         do listener, passando
    MyServletContextListener.                   em um novo ServletContextEvent. O objeto
                 new                            de evento tem uma referência para o
                                                ServletContext, então o código que trata o
                                                evento consegue obter o contexto através
                         instância de
                                                do evento e consegue obter o
 MyServletContextListener .c1ass                parâmetro init do contexto
                                                através do contexto.

                                                                                 ServletCon   extEvent
                                                                                           .,j,.
                                                          -   contextlnitialized(ServletContextEvent)

                                                                                                         listener


178 capítuío.5
atributos e Iistens8



A história cottlittua ..!

oo    listener solicita ao
    ServletContextEvent    uma referência
                                                    eo        listener
                                                           parâmetro
                                                                           solicita ao ServletContext
                                                                            init do contexto         "breed".
                                                                                                                   o


    para o ServletContext.

            r getServletContext~                                   ~ getInitParameter("breed")

 Iistener                     ServletContextEvent




o
                                                                                           •
    O listener usa o parâmetro init para            ~      O listener configura o Dog como um
    construir um novo objeto Dog.                          atributo no ServletContext.


                /new                                               _ setAttribute("dog",
                                                                                            '"
                                                                                                 d) -""

  listener                instância de Dog.c1ass
                                                        listener                                   ServletContext




CD O Container cria um novo Servlet (isto
    é, cria um novo ServletConfig       com
                                                    e      O servlet recebe uma solicitação e pede
                                                           ao ServletContext o atributo "dog".
    parâmetros      init, dá ao ServletConfig
    uma referência       para o ServletContext                         set Attribute(" dog")
    e chama o método initO do Servlet).
                                                    Servlet                                       ServletContext




                                                    •      O servlet chama o getBreedO                    no Dog
                                                           (e exibe-o no HttpResponse).


                                                                             getBreedO




                                                                                     você está aqui ~           179
outro Jisteners




      Acabo de pensar numa coisa ... já que
      os atributos    podem ser configurados
           através de um programa (ao
         contrário dos parâmetros init),
           eu posso escutar os eventos
           do atributo?   Como se alguém
         acrescentasse    ou substituísse o
                      Dog?

                      o
                      o




                                               Listeners: não só para os eventos do
                                               contexto ...
                                               Onde existe um momento do ciclo de vida,
                                               geralmente existe um listener para escutá-1o.
                                               Além dos eventos do contexto, você pode escutar
                                               eventos relacionados aos atributos do contexto,
                                               atributos e solicitações do servlet, e sessões HTTP
                                               e atributos da sessão.



                                                              o




                                                              lu. toda anão precisa saber: :·
                                                                  Você
                                                                         APllistener.
                                                                                            ·                          ·
                                                                                                                       ·
                                                     Com exceção do ServletContextListener,
                                                 você realmente não precisa memorizar os
                                                                                                                       ·
                                                                                                                       ·
                                                 métodos de cada interface do listener. Mas ...                        ·
                                                                                                                       ·
                                                                                                                       ·
                                                 você PRECISA conhecer os tipos de eventos                             ·
                                                                                                                       ·
                                                 que você pode escutar.
                                                                                                                       ·
                                                                                                                       ·
                                                                                                                       ·
                                                                                                                       ·
                                                                                                                       ·
                                                 Os objetivos do exame são claros: você
                                                 receberá um cenário (o trabalho de um                                 ·
                                                                                                                       ·
                                                                                                                       ·
                                                 desenvolvedor numa aplicação) e você                                  ·
                                                                                                                       ·
                                                 precisará decidir qual é o tipo certo do                              ·
                                                                                                                       ·
                                                                                                                       ·
                                                 listener, ou se é POSSÍVEL ser notificado
                                                 sobre esse evento do ciclo de vida.
                                                                                                                       ·
                                                                                                                       ·
                                                •...•...•........•.•.....•...............•...•...



                                                             N
                                                          "'I'Ma   'ala."elfllas   se./;rf, se,SSaf!S
                                                                                                 IV     f/.-n;:
                                                                                                            I_!.   a
                                                P":XtIVl6 C4,{.f1l16) pal'-h.".fa           l"Iãa se PI'f!6ClIpe
                                                        oA.              #'ti              "                 N
                                                se lIace' 4'-1"It!41"14a
                                                                       sabe         a 3l1f! e lIIrIa ses sa"
                                                1f"'t1Pali par 3l1e IIIJcê 1"1''-4
                                                                                 3l1f!I'e'1' sdel'          •••

180   capítulo 5
atributos   e lisrefUI


                          Escolha o listener
                          Correlacione o cenário da esquerda com a
                          interface do listener (no final da página) que
   E'){etclc19S
          J o             suporta tal objetivo. Use cada interface uma
                          única vez. (Sim, nós SABEMOS que ainda
                          não vimos essas. Veja como você consegue
                          descobrir apenas olhando os nomes. As
                          respostas começam nesta mesma página,
                          então não olhe!)


Cenário                                          Interface do Listener
Você quer saber se um atributo em um
contexto da aplicação foi adicionado,
removido ou substituído.


Você quer saber quantos usuários
concorrentes existem. Em outras palavras,
você quer rastrear as sessões ativas.

Você quer saber todas as vezes que uma
solicitação chegar, para então poder logá-Ias.


Você quer saber se um atributo da
solicitação foi adicionado, removido ou
substituído.

Você tem uma classe de atributo (uma
classe para um objeto que será colocado em
um atributo) e você quer que objetos deste
tipo sejam notificados quando eles forem
associados ou removidos de uma sessão.


Você quer saber quando um atributo de
sessão foi acrescentado, removido ou
substituído.




Selecione as interfaces abaixo.
Use cada listener apenas uma vez.

   HttpSessionAttributeListener                      Serv2etRequestListener

                          Ht~SessionBindingListener                        HttpSessionListener

           Serv2etContextAttributeListener                      Serv2etRequeStAttributeListeoer




                                                                                 você está aqui...     181
listeners mais comuns



           Os oito listetters

            Cenário                                    Interface do Listener                                Tipo de Evento
            Você quer saber se um atributo          jrequestlnitialized ServletRequestAttributeEvent
                                                            servleLhttp ServletContextAttributeEvent
                                                    attributeRemoved ServletContextEvent
                                                   jeontextInitialized HttpSessionEvent
                                  (vt,tJ+ó pal'a ó javax.servlet. ServletContextListener
                                                   javax.serv let. ServletContextAttributeListener
                                                    attributeAdded
                                                   sessionCreated ServletRequestAttributeListener
                                                    valueBoundleLhttp.HttpSessionListener
                                                      avax. serv let.http.HttpSessionActivationListener
                                                    sessionDidAetivateHttpSessionBindingEvent
                                                   javax.servlet.ServletRequestListener
                                                    sessionDestroyed ServletRequestEvent
                                                      avax.servleL
                                                   javax.servlet.http.HttpSessionBindingListener
                                                    requestDestroyed .HttpSessionAttributeListener
                                                     HHpSesstlJ"A-Hl'tl;u.f.eL,"s.f.e'JIU'
                                                    valueUnbound
                                                   sessionWillPassivate                                        'l+p5es s,,,,,,/Jrc·h-IIaft,,,,,,f.lle,../-
mpoe
 s         uma ()notificados quando eles (vóce attributeReplaeed
           capítulo.) sobre sessões espera CóJ>l espera 1IJ>1 AJÃ-oé 'JóJ>les!()
           foremsessão. ;jlle vóce no próximo es-l-a t'JCÓ'JSI"s.f.e"'"lCl"a
           detalhes e IJ          eu/,/a"ó
           eontextDestroyed ou removidos de
           sejam associados
           attributeReplaeed
                                                                                "e                        fJ·1f.                                             I.f
                  I            ~
       HHpSessI6'JA-HI'lI;II.f.e~ve~j.
          AIA-                                     ~
oto
 to
 ios
           Você quer saber quando
           Você quer saber todas as vezes




           182 capítulo 5
atributos   e liStel'lelS


o HttpSessiot1Jit1dit'gUstet1er
Você pode estar confuso sobre a diferença
entre um HttpSessionBindingListener   e um
HttpSessionAttributeListener. (Bem, não você, mas alguém
que trabalha contigo.)

Um HttpSessionAttributeListener     simples é apenas uma
classe que quer saber onde qualquer tipo de atributo foi
acrescentado, removido ou substituído em uma Sessão. Mas
oHttpSessionBindingListener     existe para que o atributo em
si possa descobrir quando ele foi adicionado ou removido
de uma Sessão.

   package      com.example;

   import      javax.servlet.http.*;

   public class Dog implements         HttpSessionBindingListener
      private String breed;

        public Dog(String breedJ
          this.breed~breed;



        public String getBreed()
          return breed;



        public void     valueBound(HttpSessionBindingEvent event) {
          Ii  código    para rodar agora que eu sei que estou em uma           sessão



       public void      valueUnbound(HttpSessionBindingEvent event) {
          Ii código     para rodar agora que eu sei que eu não faço mais
    sessão                                                                //     nparte
                                                                                     /I
                                                                                          de uma
                                                                                                   n
                                              íles v·/-;/tu", a patavNJ. nba(l"" e v"lIl:Iv,," para
                                                     n J            n                 n
    }
                                              tltjer   atllclimaila   e re"'l:IvtiJa"e .
                                                                    &li




                                                       com cada instância ativa representando as

f:    Tudo bem, eu entendi como funciona.
Eu entendi que o 009 (um atributo que será
                                                       informações - de nome, endereço, pedido, etc. -
                                                       de cada cliente. A informação real é armazenada
                                                       em um determinado banco de dados. Você
adicionado à sessão) quer saber quando ele             usa as informações do banco de dados para
está dentro ou fora de uma sessão. O que não           preencher os campos do objeto Cliente, mas
entendi é POR QUE.                                     a questão é como e quando você mantém o
                                                       registro do banco de dados sincronizado comai(

I:    Se você sabe algo sobre Entity beans ...
então pode imaginar esta capacidade como um
                                                       informação do Cliente? Você sabe que sempre
                                                       que um objeto Cliente for adicionado à sessão.
                                                       é hora de atualizar os campos do Cliente nos
"entity bean dos pobres". Se você não conhece          registros do banco de dados, com os dados deste
os entity beans, você deveria correr para a livraria   cliente. Então, o método valueBoundO é como
mais próxima e comprar dois exemplares do livro        um gatilho que diz: "Carregue-me com dados
Use a Cabeça! EJB (um para você e outro para           recentes do banco de dados ... só para garantir;
o seu amor, para que compartilhem momentos             caso algo tenha mudado desde a última vez. que
especiais discutindo sobre isso).                      fui utilizado." Por sua vez, o valueUnboundO diz:
Por enquanto, eis uma forma de pensar sobre            "Atualize o banco de dados com os valores dos
isso: imagine que o Oog é uma classe Cliente           campos do objeto Cliente."

                                                                                você está aqui..         183
talela do lístener



                     Relembrando os listeners
                     Faça o possível para preencher os espaços na tabela abaixo.
                     Tenha em mente que as interfaces do listener e os métodos
                     seguem um padrão consistente de nomes (a maioria).
                     As respostas estão no final do capítulo.




 Listeners de Atributos




 Outros listeners do ciclo
 de vida




 Métodos em todos os
 listeners de atributos
 (exceto binding listener)



 Eventos do ciclo de
 vida relacionados às
 sessões (exceto eventos
 relacionados aos
 atributos)

 Eventos do ciclo de
 vida relacionados às
 solicitações (exceto
 eventos relacionados aos
 atributos)

 Eventos do ciclo de vida
 relacionados ao contexto
 do servlet (exceto
 eventos relacionados aos
 atributos)


184
atributos    e listeners


o que él de fatol      UtM   atributo?
Nós vimos como o listener ServletContext criou o
objeto Dog (depois de conseguir o parâmetro init
do contexto) e foi capaz de inserir (configurar) o
Dog no ServletContext como um atributo, de for
que as outras partes da aplicação pudessem ter
acesso a ele. Antes disso, com o exemplo da cerv
nós vimos como o servlet foi capaz de inserir os
resultados da chamada para o modelo no objeto
(geralmente o HttpServletRequest) da Solicitaçã(
como um atributo (para que o JSP/view pudesse
conseguir o valor).

Um atributo é um objeto configurado (denominado
bound) em um dos três outros objetos daAPI
servlet - ServletContext, HttpServletRequest
(ou ServletRequest) e HttpSession. Você pode
considerá-Io simplesmente um par nome/valor
(onde o nome é uma String e o valor é um Objeto) el
uma variável da instância do mapeamento. Na verda
nós não sabemos - e nem nos importa - como isto é       5/lJehl ptJtle ver esh
implementado de verdade. Tudo que nos preocupa é        3lJa.tlf"6tle tl.yi'slJs?
escopo no qual o atributo existe. Em outras palavras,    5/lJthl patle receber
quem pode vê-Io e por quanto tempo ele vive.
                                                           e c411/ljvra.r 6S
                                                        lI.+rl!;lJ+6s?

       Um                    é C9m9      um

       9bjet9 ptes9 em um 'Luadt9
       de                AJ,buém 9 atlx9u
       n9 'Luadt9 pata 'Lue 9utt9S
        p9ssélm pe,b~19ç
        As ,btandes petb'unt{l,')sã9:
        'Luem tem ae(~S5,9 'Luadl"9
                         a9
        de aV1595e 'Luélnt9temp9
       ele petmaneee            lá? Em 9utl"aS
                       é
        pahtvtas, 'LuQ1 9 e5C9p9 d9
        éttl"lbut9?




                                                         você está aqui..           185
atributos   X parâmetros


Os atributos t1ão são parâlfletros!
Se você é um iniciante em servlets, talvez precise de mais tempo reforçando as diferenças entre
atributos e parâmetros. Mas saiba que quando elaboramos a prova, nós gastamos um pouquinho mais
de tempo para garantir que as questões que se referem a atributos e parâmetros sejam as mais confusas
possíveis. *


                                           Atributos                                             Parâmetros
 Tipos                 Application/context                                       Application/parâmetros       init do contexto
                       Request                                                   Parâmetros da solicitação
                       Session    AJ';IJ   1.: "If!."IJ.lIIVta+I""/;lI+IJ        Parâmetros init do servlet
                                  espec{ltclJ      para    (J   sel"vle+
                                  (/;as+o. lIsal" lIIVtIJ. al",-:'ve.l da
                                                         v                              AJ';IJ exi'sffltl   fal"M.,e+I"lJs
                                                                                        da ses s'iIJ/
                                  I~S+V,Ct()

 Método para           setAttribute(nome     da String, valor do Objeto)         Você NÃO PODE configurar os
 configuração                                                                    parâmetros init da Application e do
                                                                                 Servlet - eles são configurados no
                                                                                 DD, lembra? (Com os parâmetros da
                                                                                 Solicitação, você pode ajustar a query
                                                                                 String, mas é diferente.)


 Tipo de retorno       Objeto                                                    String

                                                                                    ~           bl'fJ."Ide dtlel"e"ljfJ.!




 Método para           ServletContext.getAtribute         (String name)          ServletContext.getAttribyte(String          name)
 obtenção

                                se eSJlIega     de 3ve     IJS
                                       develtl ser        cIJ"IlIel"-f-,(Jl)sJ
                                           dIJ I"e+IJI""IIJ     é 0fJe.+1)




*É verdade. Se nós fizéssemos uma prova simples e
objetiva, você não teria aquele orgulho e a sensação
de realização ao ser aprovado. Fazer um exame dificil
o suficiente para garantir que você precisaria comprar
um guia de estudo para passar na prova nunca, EM
ALGUM MOMENTO, passou pela nossa cabeça. Não
mesmo. Nós só estávamos pensando em você.


186      capítulo 5
atributos    e listeners


Os rrês Escopos: Cotttextol Solicitação e Sessão

                                 Atributos do Contexto



                 set




Context
Listener




                                                                                        JSP



                                 Atributos de Sessão




   servlet   A




           Acessível apenas para aqueles com acesso a um HttpSession      específico



                             Atributos de SOLICITAÇÃO



                       set                                             get




           Acessível apenas para aqueles com acesso a um ServletRequest      específico

                                                                       você está          ~    187
escopo atributos - exercicios



                       Escopo Atributo
                       Faça o melhor possível para preencher os espaços nesta tabela. Você
                       REALMENTE tem que entender o escopo atributo para o exame (e para o
                       mundo real), porque você tem que saber qual escopo é a melhor opção para
   B')(etclc195
           ~o          um determinado cenário. A resposta encontra-se algumas páginas à frente, mas
                       não vale olhar! Se você vai fazer o exame, confie em nós ... você deve fazer o
                       exercício sozinho, com o tempo necessário para pensar nas questões.



                                 Acessibilidade                           Escopo                       Para que serve
                                    (quem pode ver)                 (por quanto tempo vive)

 Contexto




 HttpSession




                           .



 Solicitação




               (Ai6+ti.: vacê deve levar      e"", cMstdertJ.{ilJ         4S i"lly>lic4f6es dI), c61e+4
               de 11"/(6
                       3ua"td6 1I6cê pe"tsfl.r        e"", esclJplJ ••• alju"ts   a+ribll+as          1"I'i1J
               serãlJ ct:Jle+fJ.das   a#         a
                                           311e IlpllctJ.{ilJ S~fI. deslJ..ftvada             <fJU
                                                                                                 /III(;I'+ti..
               AiãlJ   t.: PIlAdaPlIJeXIAJIleslJbre     fl'~e+t:J      ct:JJIlerf!Plci'"4J1lePl+1Jde
                                                                             j
                       ,                L_              .••.•
               /IIIeJll6rlà e/lll JIlePl"n:; JIl4S IIlJce deve se pl'ecaver)


188 capitulo 5
atributos e lísteners



A API Atributo

Os três escopos do atributo - contexto,           Object getAttribute(nome      da String)
solicitação e sessão - são tratados pelas         setAttribute(nome   da String, valor do Objeto)
interfaces ServletContext, ServletRequest
                                                  removeAttribute(nome      da String)
e HttpSession. Os métodos da API para
atributos são exatamente os mesmos em             Enumeration getAttributeNamesO
cada interface.




            Contexto                        Requerimento                           Sessão

           <<inteifaee> >                     <<inteifaee> >                    «interfaee>>
           ServletContext                     ServletReq uest                    HttpSession
getInitParameter(String)           getContextTypeO                    getAttribute(String)
getInitParameterNamesO             getP arameter(String)              setAttribute(String, Object)
                                   getAttribute(String)               removeAttribute(String)
getAttribute(String)               setAttribute(String, Object)       getAttributeNamesO
setAttribute(String, Object)       removeAttribute(String)
removeAttribute(String)            getAttributeNamesO                 setMaxInaetivelntervalO
getAttributeNamesO                 Ii MUITOS outros métodos ...       getIDO
                                                                      getLastAeeessedTimeO
getMajor VersionO                                                     Ii MUITOS outros métodos ...
getServerInfoO                                <<inteifaee> >
                                            HttpServletRequest
getReaIPath(String)
                                   getContextPathO
getResoureeAsStream(String)
                                   getCookiesO
getRequestDispateher(String)
                                   getHeader(String)
log(String)
Ii MUITOS outros métodos ...       getQueryStringO
                                   getSessionO
                                   Ii MUITOS outros métodos ...




                                                                              você está aqui..       189
attribute Sln'1ngieni9sS



o lado   negro dos atributos ...
Kim decide testar os atributos. Ele configura um atributo e,
imediatamente, recebe o valor do atributo e o mostra na resposta.
Seu doGetO se parece com o seguinte:

      public   void   doGet(HttpServletRequest            request, HttpServletResponse    response)
                                                               throws IOException,  ServletException

          response.setContentType(~text/html");
          PrintWriter   out ~ response.getWriter();

          out.println(~test        context   attributes<br>")";

          getServletContext()    .setAttribute(~foo",           ~22");
          getServletContext   () .setAttribute (~bar",          ~42");

          out.println (getServletContext          () .getAttribute(~foo"));
          out.println(getServletContext()            .getAttribute(~bar"));




Eis o que ele vê na primeira vez que o executa.
É exatamente o que ele esperava.




           teste os atributos do contexto
            22 42
                      íxa+a""e-rl-e"   Sve espera"""s".




190 capítulo 5
atributos    e lísterlefJi


Mas algo dá terrivelmente           errado ...
Na segunda vez que ele executa o comando, ele se choca ao ver:




   teste os atributos do contexto
   22 16
        I--. C"Ift" í.SS/} p"l"cp.l"laac""./-ecev???
              be ""t/e Vf!.16 esse 7(? Caiê " 2? ti



         +            EXERCITE SUA MENTE
                      Observe o código atentamente e imagine o que está
                      acontecendo. Você saberia explicar onde está o problema?

                      Você pode não ter informações suficientes para solucionar
                      o problema, por isso aqui vai outra dica: Kim colocou este
                      código em um servlet de teste que é parte de uma aplicação
                      teste bem maior. Ou seja, o servlet que possui o método
                      doGetO foi distribuído como parte de uma grande aplicação.

                      Agora você consegue descobrir?

                       Você saberia como ele poderia resolver isso?




                                                                              você está        aqui.      191
escopo do contexto   e thread-safe




              o
              ó




                                     o escopo do comexto •.• o é thread-safe!
                                                           ã

                                     Esse é o problema.
                                     Lembre-se, todos na aplicação têm acesso aos atributos do
                                     contexto, e isso significa vários servlets. E vários servlets
                                     significam que você pode ter várias threads, já que as solicitações
                                     estão sendo tratadas ao mesmo tempo, cada uma em uma thread
                                     separada. Isto acontece independentemente das solicitações
                                     estarem chegando para o mesmo servlet, ou não.




                                                                      ~ I
                                                                      ípa! OU+i"ó        sei"lIle+     ~Uf h,'j f'fJ.i"+e
                                                                      4Iftl. es.."a t<pllc4f4(J; i"ó4lfal'l4lfoe.." 1Ih1J.
                                                                           h
                                                                      +t.i"ffJ.4If Sff4i"441f4,
                                                                                      ."                         "
                                                                                              ".. f>c4IfecCl'lli;:;Vi"{J.i" <:l

                                                         ~            .l-d!Ju+.         !J__ .
                          Client C             í   i'sS<:l   ~4(J é +v4IftJ ••• tJ C(J~+llt~ei" p,,4Ife
                                               CíJli"i"f54i" tJV.f.I"fJ.+t.l"eb.4If pll1"4        tJSei"vle+ I-r;
                                               4 I'ÍfII 4Ifea+e~4Ifel" v.." +el"celNJ              clrel'l-h •••



192 capítulo 5
atributos       e listeners


o probletMa    etM eâtMera Iettta. ..
Eis o que aconteceu com o servlet de teste do Kim.


00 servlet "foo" com o valor "22". do
 contexto
            A configura o atributo                        80 servlet "bar" com o valor"42". do
                                                           contexto
                                                                      A configura o atributo




                                                                          _set~
Thread A                                                  Thread A
                                      String                                                                         String




e   A thread B torna-se a thread que está
    sendo executada (a thread A retorna
                                                          o       A thread A torna-se a thread que está
                                                                  sendo executada novamente e recebe o
    ao estado de Executável-mas-não-                              valor de "bar", copiando-o na resposta.
    Executando) e configura o atributo do
    contexto "bar" com o valor "16". (O 42
    agora já era.)



         _set~                                            Thread A
                                                                                                                    String

Thread B
                                        Stríng




                                                                                   í;r/--re as e+~~s          e""             ti
                                                                                   servle+    fJr    ctI"lij//I"IA ti V4/tlr
                                                                                le    bar e ti rec//pera,; 1)//+1"4


   getServletContext   ().setAttribute ("foo",           "22");     ~          ( -H.reu.JCIJ"lijUI"IA
                                                                                 4jã'" e JI) servle+                eiJ'l+r4 e'"
                                                                                                                     c,,'" //'"
   getServletContext()   .setAttribute("bar",            "42")'                                        ,_
           .                                         .            :,,,)          lia/ti: Jilere"ff.
   out .prlntln (getServletContext
   out.println(getServletContext()    () .getAttribute("bar"»;
                                         .getAttrlbute ( foo               );l. í,,-fu.a Juf.//4"1JtI ti servlel-            A
                                                                                                                              I
                                                                                   extbe " lia/til" Je b4r,) e1ej./íM
                                                                                   ""uJaJtI para        7t.




                                                                                             você está aqui...                     193
threads   e atributos    do contexto



Cotto tomattos        OS   atributos do
contexto thread-safe?
                                               É CLARO que eles não sincronizaram os
                                               métodos no ServletContext.      Puxa ... Isto
Vamos ouvir o que alguns desenvolvedores      significaria que toda chamada para obter
têm a dizer ...                               e configurar um atributo receberia toda a
                                              sobrecarga da sincronização. Que grande
                                            desperdício seria se você não fosse precisar
                                            disso. Não, proteger os atributos é problema
      Eu estou pensando que eu                 SEU ... não espere que a API irá ajudá-Io.
     podia sincronizar o método                     (Eu não posso acreditar que ela
    doGetO, mas isso não parece                           chegou a sugerir isto.)
    mesmo certo. Mas eu não sei
                                                                                    C>
          mais o que fazer.                                                          o

                    ()
                     o




194 cao!'tulo5
atributos e 1istenêf8




Sittcrottizar o lItétodo de serviço é ullta
PtSSIMA idéia

Tudo bem, então já sabemos que sincronizar o método
de serviço vai detonar a nossa capacidade de processo
simultâneo, mas protegerá a thread, certo? Dê uma olhada
neste código legítimo e verifique se ele evitaria o problema
que o Kim teve com o atributo do contexto sendo trocado
por outro servlet ...

   public synchronized      void   doGet(HttpServletRequest        request,       HttpServletResponse
   response)
                                                         throws    IOException,          ServletException

        response.setContentType(~text/html");
        PrintWriter   out ~ response.getWriter();

        out.println(~test      context   attributes<br>");

        getServletContext()     .setAttribute(~foo",      ~22");
        getServletContext()     .setAttribute(~bar",      ~42");

        out.println (getServletContext       () .getAttribute(~foo"»);
        out.println(getServletContext()         .getAttribute(~bar");




                                                                  o ave IItlcê Qct.a?      IS+6
                                                                  ctl"stt'itJ.t':   (I !>t'c!;leifltJ. tJ
                                                                                                     d
                                                                  k;,"",,? c!;serlle "tJvQifltPrf-e c
                                                                    ,                                  N
                                                                  C(ldijtl   t 0.$ fijVt'4S)   CiJ,Sc"ac
                                                                  -fe"t.a ctt'iejtJ..




                                                                                        você está aquí ••   195
não sincronizar       o método de serviço


Sittcrottizar     O    tltétodo de serviço ttão
protegerá Utltatributo do cotttexto!

Sincronizar o método de serviço significa que apenas uma
thread de cada vez em uma classe do servlet pode estar
rodando ... mas isto não impede outros servlets ou JSPs de
acessarem um atributo!

Sincronizar o método de serviço impediria outras threads
do mesmo servlet de acessar os atributos do contexto, mas
isto não fará qualquer coisa para interromper um servlet
completamente diferente.




                                                                                                                   ~   ~,
                                                                                                      X4.as lI<)ceI1tMlaNJ.
                                                                                                      #7aJaplv'a i'~eJi'1' tliS
                                                                                                      ()l.rr/t.O.5 sel'lIle.fs!
                                                                                                      I"Jepei"/Jel1fflltewH!          J.
                                                                                                      ",.é-!-cJtlJs ç/tesel'lIlf" e~
                                                                                                      tlJv.fI'IJS sel'vle-!-s eS-!-41

                              Client C                                                                SlI1CI'l:iI1i'~4JtJS
                                                                                                                         t'Jl/
                                                                                                      ç/i'$Sl:ijfJl/-!-l'tJs fl'ect.t!Js
                       c.....
                          V6ce
                      ..J(!
                                                              /J
                                  Si'#7Cl'tlJl1i'-;4r ~e-rtJJ/J ç/e sel'vljtIJJ jltlJce
                                                   tJ
                                                                                              .•••.
                                                                                                                N fi:"" il,ces SfJ tl.fJ~
                                                                                                      tl.pIl'CtJ.j4fJ
                                                                                                                    /";:0


                                                                                                      afl'lbl/.fas        ç/{J ctJl1ffxf.
                      Ir: IlI4.PfbI/t.              i/J   Ci/Ji"/.ftl.I""el'
                                                                          I.."tele 3f.1t.t13l/er
                      tJf.I.fl'/J ~fl..i/Jç/tJ       as i"//JjlU' stJltcl.f/lg';es 3l/E;
                      d.eJQl'ell tl.t!Jf!l'vle.f
                                       s                  A-. PaI'.ft1.n.foJ I"$.f/J IJe.A-
                      pl'<)feJel' 6S                          J6 c<)nffx.f<) Je sel'eW
                      QcessQ,«<)s P0l' WQ,t"$
                                            Je
                                                 6
                      f.I~4 ft.l'flJ.« 1'<)«4"'1016 ""é.f6Jó de sel'lItj"               016
                      Sel'vle.f A-.




196   capítulo 5
atributos e iísteners



Você MO precisa de UIM loek .,0 servlet ...

Você precisa do loek .,0 ootttexto!
A maneira típica para proteger o atributo do
contexto é sincronizar NO próprio objeto contexto.
Se todos que acessarem o contexto tiverem que                                         Pt4l'a tJS a.frlbfrl-tJs       «4
primeiro receber o lock no objeto contexto, você                                      C417+ex.fa; 174av.,. .«l.".f41'
terá garantido que apenas uma thread por vez
possa estar obtendo ou configurando o atributo do                                     "t1.«4 si"I7C1'4"lj4r       "4 SerlllffJ
contexto. Mas ... ainda existe um se aí. Só funciona se                               p6is tJlI.fI'U      pfJ.rffS     «4
todos os outros códigos que manipulam os mesmos
atributos do contexto TAMBÉM sincronizarem no                                         4p/'CfJ.jQtJ4''"11«4ser44 c4p.jes
                                                                                      «e aces SI'U' " C4,,-fex+4!
ServletContext. Se o código não solicitar o lock, ele
ainda é livre para alcançar os atributos do contexto.
Mas se você está projetando a aplicação, então você
pode decidir fazer com que todos solicitem o lock
antes de acessarem os atributos.

       public    void   doGet(HttpServletRequest              request, HttpServletResponse    response)
                                                           throws IOException,   ServletException    (

          response.setContentType("text/htrnl");
          PrintWriter   out = response.getWriter();

          out.println("test         context       attributes<br>");
                                                                                      Ajara    es.fa"'4s   I"ecde,,«a
                                                                                      a 14CI: «'''ffa   da CM-hx+4!!
                                                                                      1..s+fJ.é a "'4I7el"4      de pl"iJ-hjel'
          synchronized (getServletContext (» {
             getServletContext() .setAttribute("fo(~                  .   ~"es.fa«a                    «6 a+l"lbll+a
                                                                                                            ~ ".            «a
                getServletContext        () .setAttribute      ("bar",    "42");      C6,,-hX.f4.       ~ce      1746Õller

                out.println(getServletContext()                                   S.e."C/,,1"417"'f.e«( _
                                                               .getAttribute("foo)JJ;          J     +/,,;-S))
                out.println (getServletContext              () .getAttribute("bar"»;




J: 3ve -hJf1CS C IIJcl: dIJ 3ve lI"'tl Vej
es+aJf1óS ca"sfiJerlll7«6
                            clá"hx+c;
                                                    Ôlle
e"+l'e"'4S     "a bl6C4 SIi1CI"617lia«,,; IJS                                      Aguarde para ver muitos
1J.-/-"i"bV-i-4S«6 CM-hx+"     esl-al"Qa safo"as                                   códigos sobre segurança
                                                                                   contra threads
«e 6v-/-l'aS -/-/"I"f!!a«s a#                      da
                                  ÔVf!!S13.I"'al!Vlas
                                                                    No exame, você verá vários códigos
1;14c6 lf'I(Jf$ aV 1f'If!!"6S. Sall/as I $lof"11lc4
II •••                                     v                        mostrando estratégias diferentes para
  $1.l1/1Jle ôIJlJ.lõvel" aV+1"6 C6«ij6 óve                         criar atributos thread-safe. Você terá que
rAM.$z./Lt        IaS. sPlcl'a""ja{ã(J      176                     descobrir se o código funciona, dado um
Sf!!l"lIle-/-Cal7-hJc+    •                                         determinado objetivo. O fato de o código ser
li 4        I. I                   IV              •••
                                                                    legítimo (compila e roda) não significa que
J'VI.as es-rfJ. e a lf'Ielt.fJr IJPSIlIJôIJe I/fJce vai             resolverá o problema.
C(J"Sf!!iV'" pal"lJ. +IJI'''o.l'' as o.:.J.l"lbv+IJS «6
CIJ,,-hx-/-ó +t.reo.d- sale.



                                                                                                  você está aqui ~                197
atributos de sessão            e thread-safety


Os atributos de Sessão são thread-safe?
Pense um pouco.

Ainda não falamos sobre as sessões HTTP em detalhes (falaremos
no capítulo Sessões), mas você já sabe que uma sessão é um objeto
usado para manter o estado de conversação com um cliente. A
sessão persiste por várias solicitações do mesmo cliente. Mas ainda
estamos nos referindo a um único cliente.

Mas se é um cliente - e um único cliente só pode pertencer a
uma solicitação por vez -, isso automaticamente já não significa
que as sessões sejam thread-safe? Ou seja, mesmo que vários
servlets estejam envolvidos, seja qual for o momento, só haverá
uma solicitação de cada cliente ... então, apenas uma thread estará
rodando naquela sessão. Certo?




                                                                      get



                                                                            JSP View




Sólicl-l-"'jí!"   8
           n.f'~o.tl8
                      !   Servlet B



Embora ambos os servlets possam acessar os
atributos da Sessão em threads separadas, cada
thread pertence a uma única solicitação. Então,
parece seguro.

A não ser que ...

Você seria capaz de pensar numa situação em que
poderia existir mais de uma solicitação, no mesmo
momento, do mesmo cliente?
O que você acha? Os atributos de sessão são thread-
safe mesmo?




198 capitulo 5
atributos   e lísteners


                                                          Preste atenção em como.os nossos dois
o que é REAlMENrE verdade sobre os                        faixas-pretas discutem as questões sobre
atributos e a segura.,ça comra threads?                   como proteger o estado dos atributos contra
                                                          os problemas de multi-threading .


                                                                                 •
                                                                         ;. f,            .
                                                                                "l i j~;;o

                                                                          Ji'    :%,~-<       ~~ ~
                                                                                 •


Nós sabemos que os atributos de contexto
NÃO são seguros por natureza, pois todos
os trechos da aplicação podem acessar os
atributos de contexto a partir de qualquer            Sim, mestre. E eu sei que sincronizar o método
solicitação (leia-se, qualquer thread).               de serviço não é a solução, pois embora evite que
                                                      o servlet sirva a mais de uma solicitação por vez,
                                                      ele NÃO irá impedir que outros servlets e JSPs
                                                      na mesma aplicação acessem o contexto.



Muito bom. E sobre os atributos de Sessão. Eles
são seguros?                                          Sim, mestre. Eles servem para apenas um cliente e
                                                      as leis da fisica evitam que um cliente faça mais
                                                      de uma solicitação por vez.


Você tem muito o que aprender, gafanhoto. Você
não conhece a verdade sobre os atributos de sessão.
Medite sobre isto antes de perguntar novamente.
                                                      Mas mestre, eu tenho meditado e ainda não
                                                      sei como o cliente poderia ter mais de uma
                                                      solicitação ...
Você deve pensar além do Container.
Use a criatividade. Arrisque-se.
                                                      Muito sábio conselho, mestre! Eu entendi!
                                                      O cliente poderia abrir uma nova janela no
                                                      browser! Então o Container ainda poderá usar a
                                                      mesma sessão, embora venha de uma instância
                                                      diferente do browser?
Sim! O Container pode ver a solicitação da
segunda janela como se viesse da mesma sessão.
                                                      Logo, os atributos de Sessão não são thread-safe
                                                      e eles também devem ser protegidos. Meditarei
                                                      sobre esta questão ...
E como você protege estes atributos de sessão
contra o caos de várias threads?
Ótimo! Sim, mas sincronizar o quê?                    Ah ... Eu devo sincronizar a parte do meu código
                                                      que acessa os atributos de sessão. Do mesmo
                                                      jeito que fizemos para os atributos de contexto.

                                                      Eu devo sincronizar o HttpSession!


                                                                                     você está
sincronizar na sessão



Proteja os atributos de sessão
si.,crot'tiza.,do o HttpSessio.,

Observe a técnica que usamos para proteger os
atributos de contexto. O que nós fizemos?

Você pode fazer a mesma coisa com os atributos de
sessão, sincronizando o objeto HttpSession!

   public   void   doGet(HttpServletRequest      request, HttpServletResponse    response)
                                              throws IOException,   ServletException    {


       response.setContentType(~text/html")     ;
       PrintWriter   out = response.getWriter();

       out.println(~test    context attributes<br>");
       HttpSession   session = request.getSession();


                                                       lJes+a    ve")) It':s sl"ncI"IJltt")alYoas   ;t)   al(je+a
       synchronized(session)              {
            session.setAttribute(~foo",       ~22n);   H#pses     Si6ltJ PfJ.1"4
                                                                               PI"()+e5el" 6S
            session.setAttribute(~bar", ~42");         tJ.+d!JV+6S oie sessã6

            out.println(session.getAttribute(~foo"»;
            out.println(session.getAttribute(~bar"»          ;




        Nil9 ex1st~m
feth'untls         ldí'9tas


r:   Isto não seria um desperdício? Seria,
de fato, possível... que o cliente abrisse uma
                                                       r:  Não é ruim sincronizar código, já
                                                       que causaria muito overhead e afetaria o
nova janela no browser?                                processamento simultâneo?


1: Claro que sim. Certamente,  você mesmo já o        1: Você deve SEMPRE       pensar com cuidado
fez sem pensar duas vezes - abriu uma segunda          antes de sincronizar qualquer código, pois você está
janela porque estava cansado de esperar pela           certo - ocorrerá algum acréscimo no controle, na
 resposta da outra, ou porque você minimizou uma,
                                                       aquisição e na liberação de locks. Se você precisa
ou colocou a janela em lugar errado sem perceber,      de proteção, use o sincronismo, mas lembre-se da
etc. O fato é que você não pode arriscar quando        regra-padrão para o uso de locks: mantenha o lock
 precisar de segurança contra threads para as suas     o menor tempo possível para concluir sua tarefa!
variáveis de sessão. Você tem que saber que é          Em outras palavras, não sincronize aquele código
perfeitamente possível para um atributo do escopo      que não irá acessar o estado protegido. Faça com
sessão ser usado por mais de uma thread em um
                                                       que seu bloco sincronizado seja o menor possivel.
determinado momento.
                                                       Consiga o lock, entre, obtenha o que for preciso
                                                       e saia para que o lock possa ser liberado e outras
                                                       threads possam rodar o código.

200   capítulo 5
Sit1gleThreadModel é desigt1ado a
       proteger as variáveis de it1stât1cia                                        Stv strvle.f
                                                                                   tieve esfe"tier            "
       É isto que a especificação do servlet diz sobre a interface H-rrPServlef                               •••

       SingleThreadModel (ou STM):                                   ~
       f.'-sa parfe prl;,etpQI•••
              terá a garantia de que dois encadeamentos não {fromjavax.servlet}
                                     «interface»              HTTPServlet
do                                 SingleThreadMode,
              Assegura que os servlets lidem apenas             MyServlet
         de pool deimplementar essa interface, método
         serão executados simultaneamente livre.
             servlet instâncias do servlet no você
         pode nova do servlet. O um servletdo acesso a
         umservico solicitação a contêinere enviando
         cada assegurar isso sincronizando o servlet
     "'-                                                                .            ~.""Ifl.jServle+

           (


                                                                                             '''Y''e*lf"ftJ.         ;) SrM.J a
                                                                                                   !.~
                                                                                             Ctl""'T"l:/;,er dIA        Wtb i'raI
                                                                                             ti.sstjvrar            ave esfe sf!rvlef
           Mas COlMO cOt1têit1erda Web assegura
                   o
                                                                                             fe"t.fJ, ape"fJ,s alie          Ittlo,;' C"*1
       que o servlet obterá apet1as UIMa
                                                                                             lI*líl st:./lci'ftJ.jãl!Jtie     Ch.dfl.   vejo
       solicitação de cada vez?
       O revende dor do contêiner da Web tem uma opção. O contêiner pode manter um único servlet, mas
       colocar em fila cada solicitação e processar uma solicitação completamente antes de permitir que a
       próxima solicitação prossiga. Ou o contêiner pode criar um pool de instâncias do servlet e processar
       cada solicitação simultaneamente, um por instância do servlet.
           Qual estratégia STM você acha ser melhor?               Ettvie solicifa9Ões através de                           UtM     pool

                            Coloque em fila todas   •.. e <l c<l,,~"'el' da
                            as solicitações
                                                    Wd f."fl'f!5fraS         I.l          Request 1
                                                    (/*la   ,"'sf~Clf4."(j               J
               ~                 Re uestl

             C.a"4I'f.&vesf            é                                             /    ••.• ,,'2
                                                                                             "
             a"i';:'-<:>"I4"fI   ~ 11IfI.•••




                                                                                   //
                                 Request 2
                   ~

                                                                             k;-.}~"'"'"
                                                                                       3

                                                                      c.tJ."as(JI,CI'fagíI<:>       1I1J,i'   p41"tJ.
                                                                      v~a l"'sf~ci'tJ. sepal"fJ.da
                                                                                                 Ja
                                                                      ~es~tJ sel"vlef

                                                                                                                    você está
request queueing ou serviet poofing



Qual    éa   Ittelhor ilttplelttetttação    SfM1

Mais uma vez, devemos consultar nossos mestres. Os caras devem saber qual é a
melhor implementação STM. Iremos vê-Ios lutando para tomar uma decisão ...




       Coloque e'ft fila todas as solicitações          Ettvie as solicitações   através de U'ft pool


Colocar em fila as solicitações em um único
servlet faz mais sentido. Implementa claramente
o que os escritores da especificação pretendiam.
                                                     Mas mestre, o desempenho não sofrerá um
                                                     impacto? Certamente, colocar em fila cada soli-
                                                     citação impedirá que diversos usuários tenham
                                                     acesso ao mesmo servlet?
Sim, mas é o único modo de proteger as variáveis
de instância do servlet.
                                                     Mas mestre, o contêiner também pode criar um
                                                     pool de instâncias do servlet. Então, o contêi-
                                                     ner pode processar uma solicitação com uma
                                                     instância do servlet e outra solicitação com uma
                                                     segunda instância. Cada solicitação é lidada
                                                     paralelamente.
Ah, você vê profundamente no biscoito da sorte,
meu aluno, mas não vê como poderia ser perigosa
essa sorte ...
                                                     Você fala por charadas, mestre. O que poderia dar
                                                     errado, possivelmente, com a estratégia do pool?
A especificação do servlet define que uma única
declaração do servlet no descritor de distribuição
toma-se uma única instância do objeto durante
a execução, mas agora usando a interface STM,
essa definição não é mais válida. Você pode ima-
ginar uma situação onde ter diversas instâncias
do servlet falha?
                                                     Hmm, e se uma das variáveis de instância for
                                                     para registrar quantas solicitações foram proces-
                                                     sadas. A variável do contador teria diversas con-
                                                     tagens diferentes e nenhuma delas seria correta ...
                                                     apenas sua soma seria correta.
SIM! Você entrou profundamente no ardil que é
o pool de servlets. A semântica da definição de
"uma instância do servlet" é perdida. O servlet
perdeu a noção de realidade.


202     capítulo 5
atributos     e



retguntétS
          l'li'l9 exlst~m
                     Id'i9tétS


r:    Qual é o problema?
servlet é tão insípida?
                               Por que a especificação             do       ·.
                                                                            ·
                                                                            ·
                                                                                                 .........................

                                                                                                  Você não precisa
                                                                            ·
                                                                            ·                    conheceras
                                                                                                 estratégias STM de
1: Os escritores      da especificação queriam dar aos      :
                                                                                         contêiner para o exame.
revendedores      do contêiner a oportunidade de competirem:
entre si em termos de desempenho             e flexibilidade.               :         .    b        o SrM tenta protegI
                                                                            •Só preclsa sa er que                1
                                                                            :•as vanav eis da instância do serv et.
                                                                                    ., •
r:   Como sei qual estratégia        meu revendedor             usa?
                                                                             :                              •• ••••••••••
                                                                                                             .




1: Bem, felizmente está escrito em alguma parte da documentação para o contêiner
da Web. Se não, você deve encontrar em contato com ele e perguntar.



r:   Como a estratégia       STM mudará como escrevo                    o código   de meu servlet?


1: Se o contêiner usar uma estratégia de fila, então, a semântica de "uma instância
do servlet" ainda existirá e você. não precisará fazer nenhuma mudança no código. Mas
se o contêiner usar uma estratégia de. pool, então, a semântica de algumas variáveis de
instância poderá mudar. Por exemplo, se você tiver uma variável de instância que mantém
um "contador de solicitações", então, essa variável não poderá mais ser contada quando
diversas instâncias do servlet forem criadas no pool. Neste caso, você poderá escolher
tomar a variável do contador uma variável de classe.



Y: Mas as variáveis         da classe têm um encadeamento
seguro?


1: Não, não têm e o mecanismo      STM não ajuda
com as variáveis da classe. Sim, ele protege as
variáveis de instância contra o acesso simultâneo,
mas colocando no pool as diversas instâncias, a
semântica do servlet muda. E mais, o STM não ajuda
com os outros escopos da variável ou do atributo.
Você está sozinho ...
                                                                        Marque com um X as opções que NÃO são
                                                                        thread-safe. (Nos fizemos a primeira.)
r:   É bom usar o SingleThreadModel?
                                                                        ~    Atributos   do escopo contexto
                                                                        D    Atributos   do escopo sessão
1: Não, realmente.      É por isso que o STM foi                       D    Atributos   do escopo solicitação
desaprovado      na API do servlet!
                                                                        D    Variáveis   de instância no servlet
                                                                        D    Variáveis locais nos métodos de serviço
                     "'"    M.a.s lIacê .iiul4 preCiSo.                 D    Variáveis estáticas no servlet
                            saber   pfJ.ra   a   eXfJ.iJ'Ie.


                                                                                                  você está aoui •.      21
atributos request são thread-safe



Apenas os atributos da Solicita~ãoe as variáveis
locais são thread-safe!

E pronto! (Nós incluímos os parâmetros do método quando
dizemos "variáveis locais".) Todo o resto está sujeito à manipulação
por várias threads, a menos que você faça algo para evitar.

        NQ9   exJst~m
Terh'untels IdJ'9tél8

r:   Então as variáveis de instância não são
thread-safe?
                                                     r:   Mas se você não vai usar o
                                                     SingleThreadModel e nem sincroni~ar o
                                                     método de serviço, como você TORNA as
                                                     variáveis de instância thread-safe?
I:   Isso mesmo. Se você tem vários clientes
fazendo solicitações nesse servlet, significa
várias threads rodando o código desse servlet.       I: Não tem como. Observe     um servlet bem
E todas as threads possuem acesso às variáveis       escrito e pode ser que você não encontre
de instância do servlet, portanto, as variáveis de   nenhuma variável de instância. Pelo menos não
instância não são thread-safe.                       uma definitiva. (E sendo um programador Java,
                                                     você sabe que mesmo uma variável definitiva
                                                     ainda pode ser manipulada, a menos que ela seja
r:   Mas elas SERIAM thread-safe se você
implementasse o SingleThreadModel,   certo?
                                                     imutável.)
                                                      Então, não use variáveis de instância se você
                                                      precisar de segurança contra threads, pois as
                                                      threads para esse servlet podem sobrepor as
I: Sim, porque você nunca teria mais de              variáveis de instância.
uma thread para o servlet, então as variáveis
da instância seriam thread-safe. Mas é claro
que ninguém mais aceitaria você no clube dos
servlets novamente.
                                                     r:    Então, o que você DEVE usar se precisar
                                                      que várias instâncias do servlet compartilhem
                                                      algo?

r:   Eu só estava dando um exemplo. Como,
"se alguém FOI estúpido o suficiente para             I: Espera um pouco! Você disse "várias
implementar o SingleThreadModel. ..". Não que         instâncias do servlel". Nós sabemos que você não
eu já tenha feito isso. Mas, já que estamos           quis dizer isso, pois sempre haverá apenas UMA
apenas levantando hipóteses ... se eu tivesse         instância do servlet. Uma instância, muitas threads.
um amigo que, digamos, sincroni~asseo                 Se você quiser que todas as threads acessem
método de serviço, isso TAMBÉM não tornaria
                                                      um valor, decida qual estado do atributo faz mais
as variáveis de instância thread-safe?                sentido e armazene o valor nele. Há chance de
                                                      você resolver seus problemas de uma destas
                                                      duas maneiras:
I: Sim. Mas seu amigo seria um idiota. O
efeito de implementar o SingleThreadModel é               1) Declare a variável como uma variável local
quase o mesmo que sincronizar o método de                   no método de service, em vez de como
serviço. Ambos podem "arruinar" a aplicação sem             uma variável de instância.
proteger o estado da sessão e do atributo.
                                                         OU

                                                         2) Use um atributo no escopo mais apropriado.




204   capítulo 5
Atributos da Solicitação e Request dispatchittg
                                                                                      Cc,/c,3(1e6sdf4,J6S
Os atributos da solicitação fazem sentido quando
                                                                                      dt>~IJJeI6 ~6 esc6p6
você quiser que algum outro componente da
aplicação assuma o controle de toda a solicitação    II código em um doGet()             J
ou de parte dela. Nosso exemplo simples e            BeerExpert  be = new BeerExpert();
característico é uma aplicação MVC que inicia com    ArrayList  result = be.getBrands(c);
                                                                                      d4 SIJ,'iCi..fo'C'iilJ
                                                                                                       v.-
um servlet controlador, mas termina em uma view
JSP. O controlador comunica-se com o modelo e        request.setAttribute("styles",                    result);
obtém os dados que a YÍewnecessita para construir                         C6~Sijo'    (I~    dlSpo'..fct.el' par4
a resposta. Não há nenhuma razão para colocar os
dados em um contexto ou atributo de sessão, já
que só vale para esta solicitação. Desta forma, o    RequestDispatcher11. vlew
                                                                            view =   JSp' '--.
                                                                                         ~
                                                       request.getRequestDispatcher("result.
colocamos no escopo da solicitação.
                                                     jsp");
Então, como fazemos para que outra parte do
componente assuma a solicitação? Com um

                                                           t
                                                     view. forward (request,         response);
RequestDispatcher.
                                                               Jl,{4~de () JSP ass(llVIll"        o.   SlJllcl+~i;lJ
                                                               eJ aI. Si~ 11.3(11"
                                                                                eSh., .,s (Jt.;e..f.os
                                                               S6Ilcl+4j8.lJ   e JeesplJs+a.



o   O servlet Beer chama o método
    getBrandsO no modelo, que retorna
                                                     e    O servlet configura um atributo
                                                          para a Solicitação chamado "styles".
    com alguns dados de que a view precisa.               (Primeiro,   ele coloca o "Moose Drool"
                                                          em um ArrayList.)
                  GetBrands( )
                                                               setAttribute("styles",        results)
              ~   "Moose Drool"
                                  objeto Modelo




e   O servlet solicita ao HttpRequest um
    RequestDispatcher,   passando em um
                                                     e    O servlet chama o forwardO no
                                                          RequestDispatcher  para mandar o JSP
    caminho relativo      para a view JSP.                assumir a solicitação.            (Não mostrado:             o

       getRequestD ispatcher( uriTo View)                 JSP recebe a solicitação              encaminhada
                                                          e obtém o atributo          "styles"      do escopo
                                                          Solicitação.)
 Controller
                                       HttpRequest
                                                            forward(request       ,response)           ;;:)


                                                      Controller




                                                                                 você está
o Requestdispatcher



o RequestUispatcher            revelado
o RequestDispatcher possui apenas dois métodos
- forwardQ e includeQ. Ambos levam os objetos                                      <<interfaee> >
solicitação e resposta (os quais o componente que você
                                                                                 RequestDispatcher
está encaminhando precisará para terminar a tarefa).
Dos dois métodos, o forwardQ é de longe o mais                 forward(ServletRequest,          ServletResponse)
popular. É muito improvável que você use o método               include(ServletRequest,        ServletResponse)
inc1ude de um servlet controlador; porém, por debaixo
dos panos, o método include está sendo usado por JSPs
na ação-padrão ~sp:include> (que nós revisaremos
no capítulo 8). Existem duas formas de conseguirmos
um RequestDispatcher: através da solicitação ou do
contexto. Independentemente de onde ele venha, você
deve informar a ele para qual componente web você
está encaminhando a solicitação. Em outras palavras, o
servlet ou o JSP que assumirá o controle.


Obtendo o RequestDispatcher através de um ServletRequest
    RequestDispatcher       view    ~ request.getRequestDispatcher(~result.jsp");

O método getRequestDispatcherO no ServletRequest
usa um caminho String para o recurso o qual você
                                                              í    L'                .~
                                                                s-n,: e Vir! C41r!111t.(J
                                                                                       relo.+,vl:I
                                                                                                     .       . "" ,
                                                                                                         <,1:11:5'   "'a
                                                                                                                11.i1(J
está encaminhando a solicitação. Se o caminho                 l1ei11t.vlMo.
                                                                          barra (       u/"            íl1h{JJ
                                                                                        ) l"i11i'clo.l).
começar com uma barra ("/"),0 Container entende               l1esff C4SlJ (J Cl1l1+41"i11er 1'11ClIra e/i)
como "iniciar a partir da raiz desta aplicação"..                                           f>,          f>
Se o caminho NÃO iniciar com uma barra, ele é                 resvl+,:jSf> i11l1,eslMC IlISar IC5'cC ~(.Ie
                                                                               "
considerado como relativo à solicitação original.       fi. S6IiC{+4{;"     es-h-lIel' 1"i11sf,rl41fl..
                                                                                                      (lJf.s
Mas você pode tentar enganar o Container a olhar ~ raifJ.I'f:1M6S li J J tI
                  .     _              '.                I' ,                                 l.             • I
                                                                        ••1r!",ero.,,,,es S():TI't. ()S ca""I1"'''s
para fora da aphcaçao atual. Ou seja, so porque voce                                       I                 I
tem muitas " ..!..!..!", não significa que vá funcionar I'ela+llll),s e I),S luSares 165'C()S i11(JtJpll-ula
                                                                                                         c
se ele alcançar além da raiz da sua aplicação atual!          s(JIJI'f! bi's+rtIJu1f/4(J)

Obtendo o RequestDispatcher através de um ServletContext

                                                                                                         
    RequestDispatcher        view    = getServletContext()        .getRequestDispatcher(~/result.jsp");

Assim como o método equivalente no ServletRequest, este
método getRequestDispatcherQ usa um caminho String                        ~ce
                                                                                "bf.ví IJsar   fi.   barra   C{J'" (J
para o recurso o qual você está encaminhando a solicitação,
EXCETO se você não puder especificar um caminho relativo                  1M:+I:I41(J e+Jt.etpesl-btsf>t1.+cl.erO
                                                                                     S
ao recurso atual (aquele que recebe a solicitação). Isto                  4lIJ ServleiC()i11+elc+.
significa que você deve iniciar o caminho utilizando a barra!

Chamando o forward() no RequestDispatcher
    view. forward (request,         response);

Simples. O RequestDispatcher que você obteve através do
contexto ou da solicitação conhece o recurso que você está
encaminhando - o recurso (servlet, JSP) que você passou
como argumento para o getRequestDispatcherQ. Então, você
está dizendo: "Ei, RequestDispatcher, por favor encaminhe
esta solicitação para aquela coisa que eu disse anteriormente
(neste caso, um JSP), quando nos falamos pela primeira
vez. Eis a solicitação e a resposta, pois esta nova coisa vai
precisar delas para terminar de tratar a solicitação."
206 capj;tuJo 5
o que há de errado COilteste código?
o que você acha? O código deste RequestDispatcher   parece
que funcionará do jeito que você esperava?

   public   void   doGet(HttpServletRequest     request, HttpServletResponse    response)
                                                       throws IOException,   ServletException


        response.setContentType(~application/jarff);
        ServletContext    ctx ~ getServletContext();
        InputStream   is = ctx.getResourceAsStream(~bookCode.jarff);
        int read ~ o;
        byte[] bytes      new byte[1024];                                     St/ftmkfJ.   ót/E'
        OutputStream   os = response.getOutputStream();                       1"$+"   tt/"d""fJ,
        whi1e «(read ~ is.read(bytes))      !~ -1) {
            oS.write(bytes,   o, read);
        }
        os.flush();
        RequestDispatcher   view ~ request.getRequestDispatcher(~result.jspff);
        view. forward (request, response);
        os. close ();




Você vai receber Uilt ettorilte lIIegalStateExceptiott!


             Você não pode transferir
             a solicitação se você já
                                                 r:   Como você não falou sobre o método
                                                 includeO do RequestDispatcher?
             submeteu uma resposta!

  E por "cubmeteu uma resposta" e~tend~
  como, "enviou a resposta para o cliente .
                                                 1: Um dos motivos      é porque ele não está no
                                                 exame. Outro: nós já mencionamos que ele não é
  Observe o código novamente. O grande           muito usado na vida real. Porém, para satisfazer
  problema é:                                    a sua curiosidade, o método includeO envia a
                                                 solicitação para outro lugar (geralmente outro
   os .flush () ;                                servlet), para realizar alguma tarefa e então voltar
                                                 para o remetente! Em outras palavras, significa
   Esta é a linha que jaz com que a              que o includeO pede por ajuda no tratamento
   resposta seja enviada ao cliente e, ,neste    da solicitação, mas não chega a ser uma ajuda
   ponto esta respostajoi CONCLUIDA.             completa. É apenas uma transferência de controle
   TERMINADA. JÁ ERA. Possivelmente,             temporária, e não, permanente. Com o forwardO,
   você não poderá encaminha~ a          ."      você está dizendo: "É isso aí, eu não vou fazer
    solicitação neste estágio, pOIS.ela ja, e    mais nada para processar esta solicitação e esta
    história! Você já respondeu e ISSOso         resposta." Porém, com o includeO, você está
    acontece uma vez.                            dizendo: "Eu quero que outra pessoa faça algumas
                                                 coisas com a solicitação e/ou resposta, mas quando
                                                 ela terminar, eu mesmo quero acabar de tratar a
    Então, não seja iludido por. q~est~es
                                                 solicitação e a resposta (embora eu talvez queira
    do exame que enviam a solzcltaçao
    DEPOIS da resposta ter sido                  fazer outro include ou forward depois disso ...").
    enviada. O Container vai mostrar um
    IllegalStateException.


                                                                             você está
respostas do exercício iístener




                    Relembrando os Listeners
                                  RESPOSTAS
   ExetcÍd9S
 Listeners de atributos
                                   5erllle+it-e3ve s+A-#ri"bv..feLi's..fel1er
                                   5ervle+C~P1..fex+A-#rt!Jv+eLts+ePler
                                   H#p5es      siiJl1tJr#rt!Jv+eLts..fel1er



 Outros listeners do ciclo
 devida




 Métodos em todos os               a.ffrt!Jv+eA-Jt1etlO
 listeners de atributos            affrt!Jv+eit-ew.lJveJO
 (exceto binding listener)
                                   affrt!tv..feit-epI4cet10



 Eventos do ciclo de vida
                                                  N   I                  I
 relacionados às sessões
                                   tJl1Je a. segalJ e cr''"4tltA; IJ"'IJe
                                                                e       e
 (exceto eventos relaciona-
                                   ses siâ"'lCrea+eJO
 dos aos atributos) quando
 a sessão é criada e quando        ses st"ól1lJes+rlJjeJO
 ela é destruída



 Eventos do ciclo de
 vida relacionados às
 solicitações (exceto
 eventos relacionados aos
 atributos) quando a sessão
 é inicializada ou destruída



 Eventos do ciclo de vida
 relacionados ao contexto           wt.e"'l +t.e ceu'rf-ex+l's ,.",.+lalljeJ e.r Jes+re.jeJ
 do servlet (exceto eventos         CÓI1-hx+II'I,--I-l4't;f.JO
 relacionados aos atributos)
 quando o contexto é                ctJ~x+lJes+r~jeJO
 inicializado ou destruído


208   capj!tulo 5
atributos e Iísteners




                                               Escopo Atributo
                                                       RESPOSTAS



                                      é   des+rv{,J<l/elIi1'lIJ. vive)
                                                  Acessibilidade
                                                                              /
S1I4r14 variás
       as e
 lJ""Pru
                                                 que           em
                           C611+e1l.,(4 Se <ill';;clUll1dl.lN!.CflI'SCS
                                      Para!JadlJsEscopoc<J"Iex::es CÕ"'IIH!f'Sa
                                       N+,/ apel1IJ.sserveSesS4lJlIi1'la
                                              3ue'"aliviii" de dad4sJ de
                                         (por6S l1I'JiI'les .,(lslmclli. 114fJ
                                                I'r /;(J'" tempo
                                                 quanto tM!it>f't.rJ.
                                              CtliI'l4-h-..e-et,;+, l'I"btll.,(lJ..
                                                "P"ca]"6 I';;etvll'l.,(o
                                                 sel'vMIJi"
                                3t1e Sijl1l"1lcaIJ.CeSS6 as~tfJr'54seI'de <l
                                                .,(~4~.,./-ea <ilf.l
                                          4ptiC4í44jeSS46~ Sl""f'eS~~   sess46
                                              rela-h-vese+c f4t'~INJSvlfia
                                               f4t'Serv1e.fC6J?-h!X+j
                                          C~ (,I'" V,",,4.,(aseSSM.
                                                .,(esl-f'u!Ja re3l1ef'
                                              JAl!JI;s clltPJ+e, ti;;,
                                              .,(es+e 6Sve Sve de
                                              e-iI'laN; clle#l-h!j ~14
                                               1'itJ.6 +eit>f'IJ e
                                                d"
                                                tllWJ.
                                              Jt.eCIIf'SIJS .,(IJ. I.u:,kllp
                                              S6/iél+o.544, a
                                               PI'65I'4IWJ.iW
                                               46 /;a11C6.,(e   •
                                                            eJ?.,(eresI'Js
                 tA   4pllé,'i6   catrj Õ I,;;.f-el"a sel'vle+ .,(4 JSP
                                                           CIJ""PIJ.f'-I-t"It.eJ
                                          f;{v#J?per p4f'.f-e <!li
                                          f;{v4t311IY'




          Solicitação
                                                                                                                           Passar
                                                                                  I'r vlfia da Scll'cl+IJ.!j'ifJj
                                                                                  3l1e s'j"ltli(;a       a+: ti It",
                                                                                                                           S6/;l'e      4 ;;'4.,(tl() .,«)
                                                                                                N        /}
                                                                                  .,(IJ. xecujalJ dlJ ",erlJdó
                                                                                       e                                   c6"1+rlJlad4f'           pfJ.l'IJ. ti.
                                                                                  servlce()          .,(6 Servle+.         IlftW ••• 41/
                                                                                                                           (J8I+I'4 .,(t!d4
                                                                                  011S~4; .,(lIra~               a
                                                                                  Vlfia .,(a +t.I'ea.,(      (ptlt.l))     ptu'a ti                            de
                                          f/"el' d',el't
                                          s/!I'vle+s          tiS
                                                                                  3ve es+tver            +rtJ.+fJ.J?.,(4
                                                                                                                           €IJ/)   cll"eI1-h!.

                                          pat'1J. 61'1de a                        esh      s()llct+a{l4.
                                          Ié/' e"'lC41JlJ",t.a.,(1J,
                                                                 (,ISGl"ld"


                                                       s
                                          relacicl'lti.,(6S     ~

                                          S4Ilét+tUj'i"".




                                                                                                                                                  aqui ••           209
imã de geladeira - respostas dos exercícios


                                                       ~
                                                       Ímã de Gelcidelt'l
                                                       RESPOSTAS
                                                       (configurando um parâmetro de contexto no DD)




      !<web-app          ". >


         I <servlet>         I
            1---------------------1 . I BeerTest
             <servlet-name>           .                             </servlet-name>            I
                                                                                               .
            I   <servlet-class>             II-c-o-m-,w-l-·c-k-e-d-l-y-S-m-a-r-t-.B-e-e-rT-e-st-e--r
                                                                                        </servlet-class>
                                                                                                   11                   I

         I </ servlet> I

          I <context-param>                 I

                I <param-name>              I                      I </param-name>
                I <param-value>         I                           I </param-value>       I
          !</context-param>                 I


      !</web-app>1




                                                                        Não usados:

                                                                                                        </init-param>



                o <.t"r-l-pfJ.I"fJ.h> é (,ISfJ.tilJ             pal"~d;l"lJs   ,;"Y-
                ti6 sel"lIl&; "';6 tilJ CIJ,,+eX+6.                         e"c(m+l"fJ.
                " <:'1;,t.f-PfJ.1"41f!l>
                                    tie"+l"fi tie       (,111I


                <:.servle+>.                                                              [<servlet-param>     I
                A1';1>   exish Ifo.tiaPl4l"tc"ti(J     CI>III      <.servle+-pI4NJ.!!/I>.




210               5
fausa pata
                                            9 caté




1Usando um RequestDispatcher,      o uso de qual dos métodos pode nos levar a uma
  IllegalstateException?    (Escolha todas as que se aplicam.)
    DA. read
    DB. flush
    DC.write
    Dn.   getOutpuStream
    DE. getResourceAsStream



2 Quais  declarações sobre os parâmetros de inicialização do ServletContext     são verdadeiras?
  (Escolha todas as que se aplicam.)
    DA. Eles devem ser usados para dados que raramente mudam.
    DB. Eles devem ser usados para dados que freqüentemente mudam.
    De.   Eles podem ser acessados usando o ServletContext.     getParameter    () .
    Dn.   Eles podem ser acessados usando o ServletContext.     getIni tParameter      () .
    DE. Eles devem ser usados para dados que são específicos de um determinado servlet.
    DF. Eles devem ser usados para dados que servem para toda a aplicação.




                                                                               você está      aqui..   211
teste preparatório




3 Quais tipos definem os métodos            getAttribute   () e setAttribute   () ? (Escolha todas as que se
    aplicam.)
      elJ.Httpsession
      elB. ServletRequest
      OCo ServletResponse
      elD. ServletContext
      DE. ServletConfig
      elE    SessionConfig




4   Se um servlet for invocado usando-se o método forward ou include do RequestDispatcher,          quais
    métodos do objeto solicitação do servlet podem acessar os atributos da solicitação configurados
    pelo container? (Escolha todas as que se aplicam.)
      QJ. getCookies       ()
      DE.    getAttribute        ()
      elc.   getRequestPath           ()
      DD. getRequestAttribute              ()
      DE. getRequestDispatcher              ()




5' Quais chamadas oferecem informações sobre os parâmetros de inicialização que podem ser usados
    por toda a aplicação? (Escolha todas as que se aplicam.)
      DA     ServletConfig.getlnitParametersO
      D B. Serv letContext.getInitParametersO
      Dc.    ServletConfig.getlnitParameterNamesO
      uD.    ServletContext.getInitParameterNamesO
      DE. ServletConfig.getInitParameter(String)
      DE     ServletContext. getInitParameter(String)




212     capítulo 5
atributos    e listeners




6   Quais declarações sobre os listeners são verdadeiras? (Escolha todas as que se aplicam.)
     DA. O ServletResponseListener        pode ser usado para executar uma ação quando uma resposta
           do servlet foi enviada.

     DB. O HttpSessionListener       pode ser usado para executar uma ação quando der time-out no
           HttpSession.
     De.    O ServletContextListener        pode ser usado para executar uma ação quando o contexto do
           servlet estiver prestes a ser encerrado.
     DD. O ServletRequestAttributeListener       pode ser usado para executar uma ação quando um
         atributo tiver sido removido do ServletRequest.
     DE. O ServletContextAttributeListener          pode ser usado para executar uma ação quando
         o contexto do servlet tiver sido criado e estiver disponível para servir à sua primeira
         solicitação.




1   O que seria mais coerente de ser armazenado como atributo no escopo sessão?
     DA. A cópia do parâmetro de uma query que o usuário digitou.
     DB. O resultado de uma query ao banco de dados para ser retomado imediatamente ao usuário.
     De.    O objeto da conexão com o banco de dados usado por todos os componentes da aplicação.
     DD. Um objeto representando um usuário que acaba de se logar no sistema.
     DE. A cópia do parâmetro de inicialização recuperado de um objeto ServletContext.




                                                                               você está aqui     I!"   213
teste creparatório




8 Dado o código de um HttpServlet        válido que também foi registrado como um
  ServletRequestAttributeListener:
   10. pub1ic     void   doGet(HttpServletRequest     req,
                                                       HttpServ1etResponse   res)
   lI.               throws IOException,     ServletException   {
   12.       req.setAttribute(~a",   ~b");
   13.       req.setAttribute(~a", ~c");
   14.       req.removeAttribute(~a");
   15.   }
   16. public void attributeAdded(ServletRequestAttributeEvent        ev) {
   17.   System.out.print(~    A:" + ev.getName()   + ~->" + ev.getValue());
   18. }
   19. public void attributeRemoved(ServletRequestAttributeEvent        ev) {
   20.   System. out .print (~ M:" + ev. getName () + ~->" + ev. getValue ());
   2I. }
   22. public void attributeRep1aced(ServletRequestAttributeEvent        ev) {
   23.   System.out.print(~    P:" + ev.getName(}   + ~->" + ev.getValue());
   24.

  Qual dos logs é gerado?

      C)Pl.A:a->b P:a->b
      C)B. A:a->b M:a->c
      C)C. A:a->b P:a->b M:a->c
      C)D. A:a->b P:a->b P:a->null
      C)E.A:a->b M:a->b A:a->c M:a->c
      C)F.A:a->b M:a->b A:a->c P:a->null




9 Ao declararmos um listener no DD, quais subelementos do elemento <listener>       são necessários?
   (Escolha todas as que se aplicam.)
      CJPl.<description>
      OB. <listener-name>
      CJC. <listener-type>
      CJD.<listener-class>
      CJE. <servlet-mapping>




214    capítulo 5
atributos e físieners




10   Quais tipos de objetos podem armazenar atributos? (Escolha todas as que se aplicam.)
     01.   ServletConfig
     DB.    ServletResponse
     Oc.    RequestDispatcher
     OI>.HttpservletRequest
     OE.Httpsessioncontext




11 O que    é verdade? (Escolha todas as que se aplicam.)

     DA      Quando uma aplicação está prestes a ser encerrada, o pedido de notificação do listener não
            é garantido.
     OB. Quando um evento que aceita um listener ocorre, o pedido de chamada do listener não é
         previsível.
     Oe.    O container registra os listeners baseado nas declarações do deployment descriptor.
     DI>. 1penas o container pode invalidar uma sessão.




12  Quais declarações sobre o RequestDispatcher   são verdadeiras (quando verdadeiras, considere
  que o RequestDispatcher   não foi obtido via uma chamada ao getNamedDispatcher (»)? (Escolha
  todas as que se aplicam.)
     01.   O RequestDispatcher     pode ser usado para encaminhar uma solicitação a outro servlet.
     DE.     O único método na interface do RequestDispatcher     é o forward ().
     De.     OS parâmetros especificados na query string usada para criar o RequestDispatcher     não são
            encaminhados pelo método forward () .
     DI>. O servlet para o qual uma solicitação é encaminhada pode acessar a query string original,
         chamando o getQueryString () no HttpServletRequest.
     DE. O servlet para o qual uma solicitação é encaminhada pode acessar a query string
         original, chamando o getAttribute("javax.servlet.forward.query_stringU)         no
         ServletRequest.



                                                                               você está          ~   215
teste preparatório




13    Qual é a maneira recomendada para lidarmos com segurança de servlets e threads?


      DA. Fazer com que o código do servlet estenda ThreadSafeServlet.
      DB. Fazer com que o servlet implemente o SingleThreadMode1.
      Dc.   Logar todas as chamadas dos métodos.
      DD. Usar exclusivamente variáveis locais, e se você tiver que usar as variáveis de instância,
          sincronizar o acesso a elas.



14    Dados os seguintes métodos:
  - ggetCookies
  - getContexPath
  - getAttribute
  Coincida os métodos acima com as seguintes classes ou interfaces. Note que cada método pode ser
  usado mais de uma vez.



     HttpSession

     ServletContext


     HttpServletRequest




15    O que é verdadeiro sobre a interface RequestDispatcher?    (Escolha tudo que se aplica.)


      DA. De seus dois métodos, forward( ) é usado com mais freqüência.
      DB.   Seus métodos têm os seguintes argumentos: recurso, solicitação e resposta.
      De.    Dependendo da classe cujo método cria um RequestDispatcher,      o caminho para o recurso
            a ser enviado mudará.

      DD. Independentemente da classe cujo método cria um RequestDispatcher,         o caminho para o
          recurso a ser enviado NÃO mudará.

      DE.    Se seu servlet chamar RequestDispatcher.forward, poderá enviar sua própria resposta para
            o cliente antes, mas não depois da chamada de envio.




216                5
atributos       e listeners




                                                    Pausa pata
                                                    o caté
                                   'R~-~5



1Usando um RequestDispatcher,             o uso de qual dos métodos pode nos levar a uma
  IllegalStateException?           (Escolha todas as que se aplicam.)
    DA. read
    litl"B. flush
    litl"c. write                               lJlj<j(4
                                                       IlIeiafS+a-hf.xce,-h..,,,
                                                                ,    ti                    é
                                                                                          ti catlsada o
                                                                                                      'l.tla"da tllj<ja
                                                                                                                    ,
                                                res,as+tJ.j4       lat     Calj<je+M4 ,41"4 a ette,,+e             (6 lj<je+fJdfJ
    DD. getOutpuStream
                                                Iftlst. 14; tsstJJ       e vacê -h"+4 14;U'          tllj<j   lanli4rd,
    DE. getResourceAsStream




2 Quais  declarações sobre os parâmetros de inicialização do ServletContext                      são verdadeiras?
  (Escolha todas as que se aplicam.)
    litl"A. Eles devem ser usados para dados que raramente mudam.
    DB. Eles devem ser usados para dados que freqüentemente mudam.
    Dc.    Eles podem ser acessados usando o ServletContext.getParameter().
    litl"D. Eles podem ser acessados usando o ServletContext.                  getlni tParameter         () .
    DE. Eles devem ser usados para dados que são específicos de um determinado servlet.
    litl"F. Eles devem ser usados para dados que servem para toda a aplicação.


          A-    a'fã"   $ es+:   'Í7CQN'e.f4.J>(Jr'!JtlfQS'4r~e+ras
                                             f                                    'Í7t+   da Serllfe+Caw!-ex+
            ,    N
              sa" 'M(JS "4 /,(JNJ.lj<j
          Sii:J                  f
                                                 /I i              '
                                                                   e
                                              tl t..(J/I'f"f'fJ,IÍ7er';'icta't"f;tJ.dc.
          A- c'f';c     C es+: lÍ7cCI'I"e.fl; PIJI"3ve es-h Ir!:+IJd(J ,,'ia ex,"s-h.
                        í
          A- af>S';(J es+: 'Í7cal"l"e.fl;f>IJI"1Jtle s~ ei'u"s+e Vir! ól6e+a Sel"lIfe+CIJ,,-hx+                     ,aI"
          apfif:4s';a.




                                                                                               você está                  '"   217
teste preparatório




3 Quais tipos definem os métodos                 getAttribute        () e setAttribute            () ? (Escolha todas as que se
    aplicam.)
      I,;?   A. HttpSession
      I,;?   B. ServletRequest
      OCo ServletResponse
      I,;?   D. ServletContext

      DE. ServletConfig
      DF.sessionconfig




4   Se um servlet for invocado usando-se o método forward ou include do RequestDispatcher,          quais
    métodos do objeto solicitação do servlet podem acessar os atributos da solicitação configurados
    pelo container? (Escolha todas as que se aplicam.)
      DA. getCookies            ()
      I,;?   B. getAttribute        ()
      De. getRequestPath()
      OD. getRequestAttribute                  ()
      DE. getRequestDispatcher                  ()

                        -    Ir IJpjãlJ     8 apl"ese1'l.ffl.   " "",é.fiJiJiJ CM'l"e.ftl.       C,,"'" ele; vlJcê plJJe fl.cesstJ.1"

                             IJS 1J..fI",1;v.fIJS pl"ee"ct.MlJs        iJlJ CI:m.fo.ll1el"jfl.llf1.x.sel"lIlff./lJl"wtJ.I'J.x.xx           e
                            jfl.vfl.x.se I"vle-J-.,;'c/vde.X.xxx.

                        -    Irs     iJpj6eS C e lJ se I"elel'el/ll fi. l/IIé-I-iJiJiJS~ve "ãiJ exi's.fel/ll.



5 Quais chamadas      oferecem informações sobre os parâmetros de inicialização que podem ser usados
    por toda a aplicação? (Escolha todas as que se aplicam.)
      DA. ServletConfig.getlnitParametersO
      DB. ServletContext. getInitParametersO
                                                                                Irs   iJPj6es Ir e 8 es.fãlJ ,;,clJl"I'ehs;
      Dc.        ServletConfig.getInitParameterNamesO
                                                                               piJl"~ve es.fes          l/IIé.fiJJiJS PJãlJexts.fel/ll.
      I,;?   D. ServletContext.get1nitParameterNamesO                     -    Irs   iJpj6eS C e f. es.fQiJ ';'C6I"1'fffl.S;
      DE.       Serv letConfig. getlnitParameter( String)                      plJl"iVe      iJlel"ecel/ll fJ.ceSSIJfl.iJS
                                                                                      l(.    i                           ,..;
      I,;?   F. ServletContext.getInitParameter(String)                       pfl.l'fI."'te-rl"lJs   iJe ';'lci'fI.'i';fl.jfl.lJ espec,llclJS
                                                                               iJ6 sel"vle.f.


218 capítulo 5
atributos          e Iísteners



6   Quais declarações sobre os listeners são verdadeiras? (Escolha todas as que se aplicam.)

                                                                                                             (5el"vle.f.     V2.,   ti; p~. 80)
     DA. O ServletResponseListener                           pode ser usado para executar uma ação quando uma resposta
            do servlet foi enviada.

     fil E. O HttpSessionListener                      pode ser usado para executar uma ação quando der time-out no
           HttpSession.
     fil c. O ServletContextListener         pode ser usado para executar uma ação quando o contexto do
            servlet estiver prestes a ser encerrado.
     fil D. O ServletRequestAttributeListener        pode ser usado para executar uma ação quando um
            atributo tiver sido removido do ServletRequest.
     DE.     O ServletContextAttributeListener         pode ser usado para executar uma ação quando
            o contexto do servlet tiver sido criado e estiver disponível para servir à sua primeira
            solicitação.


               If   iJp{ãiJ    If   es-/-: ii'lcIJl"l"e-/-a; PiJl"1Jve ,,'i.iJ se I"elel"e                a v~a 'i1hl"iace              diJ
               5el"vle-l-/t.espiJ"seL.i"sh"lel"                  •

               If   iJPf'i.lJ f. es-l-: ,i1cIJl't'e-l-tl; plJl"'/;ve vsal":altifJs Vlti 5el"vle.f.CfJ"hx-/-L,"sh"lf!1"
               pal"ti. es-l-e pl"fJp:Sl-l-IJ.




1   ODA. seria mais coerente de ser uma query que o usuário digitou.
     que A cópia do parâmetro de armazenado como atributo no escopo sessão? V
                                                                     (5el"vle-l-                                              2..,IJ I'fAj'
                                                                                                                                    J   ,          S"8J
      DE.    O resultado de uma query ao banco de dados para ser retomado imediatamente ao usuário.
      Dc. O objeto           da conexão com o banco de dados usado por todos os componentes da aplicação.
      fil D. Um     objeto representando um usuário que acaba de se logar no sistema.
      DE. A cópia       do parâmetro de inicialização recuperado de um objeto ServletContext.



                    - If      fJPf'i.fJ   If    es-/-: li1CiJl"l"e-l-a; I'fJl"'/;fle   IJ   pal"M"e+l"fJ         de Vlti4 ~Vff!l"j      é
                      5el"alltie,,-I-e ltial"s flsadiJ ptt.NJ. I"eali,al"                 Vltit.lfJPff!I"t.lf'i.fJ.

                       If     fJPf'i.fJ   8 es-l-:     'i1CIJl"I"e-/-a;pIJI"3f1e -I-af dtJ.da 5ff!I"lJ.fltif!I'rh          é l'ltiedta-/-fl./I!e,,+e
                       l"e-l-al""ItJ.JfJ iJfI tJ.1"1tifl.je'llJ.JfJ eSCIJpfJSIJIi'ci"-I-af'i.fJ.
                                                                   '14

                        A. IJPftJ.aC es-rtJ. li1CIJI"I"e-r~ p41"'/;ve 9tJ.3ve '1aIJ e especIllcIJ
                       1"f
                               ".        I'            - 1-             '".         /        ,                                 de VItiIJ.
                       Jehl"lti/i1lJ.JIJ. sess'i.tJ.> ele Jevel"i"IJ. seI" IJ.1"1titt.je'llJ.JIJ esclJf"
                                                                                                 /'Ia                             CI)i'1+ex-l-fJ.

                       If     fJPj'i.l)   í    es-/-: li1ClJl"l"e-l-~ plJl"'/;ve fJSptJ.I"M"e.f.1"6S J6 CM+eX-l-iJ Sf!I"VIe.f.
                       Jevel"lalti es .. l"
                                        h              '16 6tje-l-6 5el"vle-I-C61'1+ex-l-.




                                                                                                                         você está aQui..             219
teste preparatório




8 Dado o código de um HttpServlet       válido que também foi registrado como um
  ServletRequestAttributeListener:
   10. pub1ic     void   doGet(HttpServletRequest       req,
                                                                   (.sel"v'dv2..~p~. 799-2.00)
                                                          HttpServletResponse       res)
   1l.               throws IOException,       ServletException    {
   12.       req.setAttribute(~a",     ~b");
   13.       req.setAttribute(~a"r     "e")i
   14.       req.removeAttribute(~a");
   15.   }
   16. pub1ic void attributeAdded(ServletRequestAttributeEvent      ev) {
   17.   System.out.print(~  A:" + ev.getName()    + ~->" + ev.getVa1ue());
   18. }
   19. pub1ic void attributeRemoved(Serv1etRequestAttributeEvent      ev) (
   20.   System.out.print(~  M:" + ev.getName()    + ~->" + ev.getValue());
   2l. }
   22. public void attributeReplaced(ServletRequestAttributeEvent       ev) (
   23.   System.out.print(~  P:" + ev.getName()    + ~->" + ev.getVa1ue());
   24.

  Qual dos logs é gerado?                              Pe5aJ,i,f"a! tJ lt1é-!-~J"5e#altle l"e-f.iJl"J'lf4.
                                                                                                        "
                                                       vs.l~1" IJrlJr'Z/;tJ da 1J.-!-l"iÍ1l1-!-" es-h tal'
                                                                                             se
     DA. A:a->b P:a->b                                 slIbhl-tlida.
     DB. A:a->b M:a->c
     ~e.A:a->b       P:a->b M:a->c
     DD. A:a->b P:a->b P:a->null
     DE.A:a->b       M:a->b A:a->c M:a->c
     DF.A:a->b       M:a->b A:a->c P:a->null




9 Ao declararmos um listener no DD, quais subelementos do elemento <listener>                  são necessários?
   (Escolha todas as que se aplicam.)
     DA. <description>
     DB. <listener-name>
     De. <listener-type>
     ~D.<listener-class>                                                             I     I
                                          O stl/;elelt1eJ'l-!-"<.lfs+enerclass">     e " uAJ'ZCO elelt1en-l-"
     DE. <servlet-mapping>
                                          ,i,di'spens:vel   d6 elelt1f!n';'" <.Ii's+enel'">.




220 capituio 5
atributos    e !ísteners




10   Quais tipos de objetos podem armazenar atributos? (Escolha todas as que se aplicam.)
     [J1.servletConfig
     OB. ServletResponse
     De.      RequestDispatcher
     Iit? D. HttpServletRequest

     [JE. HttpSessionContext                                                     fJ(j"t-a: Os óV+-l'óS Jóis '/-'j>(;S

                                                                                 I'elel"e~s       lJ.ó   sel"vle+- 3ve PI}Je'hII
                                                                                 al"IfIa-;eJ7lJ.1'
                                                                                                tJ.+-I"rbv+-ós sã., tJ
                                                                                 ##pSess/()J7       e 6 Sel"vle..j.Ctil1fflf--l.



11 O que      é verdade? (Escolha todas as que se aplicam.)                         (Sel"vle-l-   ·i2..~p~s.            87 tJ.
     DA       Quando uma aplicação está prestes a ser encerrada,;;                     IJrs aF{;es A- e         8
                                                                                                            es+';e
             pedido de notificação do listener não é garantido.                        ,;,cóI"I"e+as;póI"3ve 6 ctm+tJ.I;,er
     DE.      Quando um evento que aceita um listener ocorre, o                        VS4 ó lJb pal"a Jeh;,tt' li.
             pedido de chamada do listener não é previsível.                           I}t'Jelfl Je J76+,"Ii'ca{itJpal"a tJS
     Iit?   c. O container       registra os listeners baseado nas                     li'sffJ7et's      t'f!!5iS+t'IJ.d()s.
              declarações do deployment descriptor.                                     lJr cp{ió lJ es+: t#1CfJt't'ef-t4;
     DD.1penas          o container pode invalidar uma sessão.                        ptir'lpe Vht set'vlef- pade ii1Vt4IMlJ.r
                                                                                                               ti
                                                                                       vlfla ses s';tJ VStJ.#1Jó /iVlé-I-(jdlJ
                                                                                        H.f..i.p.5eSSi'611.,;'VQ.lidtJ.+eo.


12  Quais declarações sobre o RequestDispatcher   são verdadeiras (quando verdadeiras, considere
  que o RequestDispatcher   não foi obtido via uma chamada ao getNamedDispatcher ())? (Escolha

  todas as que se aplicam.)                                                                   (.5erll Ie-r 112..[J / J P"5.
                                                                                                         J               r

     Iit? 1. O RequestDispatcher             pode ser usado para encaminhar uma solicitação a outro servlet.
     DE.       O único método na interface do RequestDispatcher                      é o forward ().
     De.       OS parâmetros especificados na query string usada para criar o RequestDispatcher                                 não são
              encaminhados pelo método forward () .
     DD. O servlet para o qual uma solicitação é encaminhada pode acessar a query string original,
         chamando o getQueryString    () no HttpServletRequest.
     Iit? E. O servlet para o qual uma solicitação é encaminhada pode acessar a query string
              original, chamando o getAttribute               ("javax.servlet.         forward.query_string")              no
              ServletRequest.
            lJr 6p{i6   8 es+:      I;'COl"I"ef-s.,;
                                                  p(jr~ve tJ.,;,fft'lo.ce        +tJ.lflb~IfI P/JSSi/i' Vif if~+/JJo ,;'c/vJe.

            lJr 6PS';ÓC es+: i'l'1c(jt't'e+-4;pórói/e eSffs          PQ.t';""ef-t'tJs sel"â'/Jel'1caif,;,t.ad6S I'l'f!s+e C4StJ.
     - lJr lJPjâ'/J b ~ ti1ctJrl"e+o.P/JI"f/,'f!!es se IfI~+tJdtJt'e+Ct'I1Q.Q. s+t'l;'5 de cO'lsvl-/-a '10 pQ.Jt'ão
            uJeL   o. parl-tt'    dtJ Jee'/;vf!s-l-btspa-l-ct.et'.

                                                                                                         você está aqui ~          221
teste prepaíBtório




13   Qual é a maneira recomendada para lidarmos com segurança de servlets e threads?

                                                                                         ú!speciflcll.gíió       d6 Se"'lIle.f;           p:.,.        2.7)
     DA. Fazer com que o código do servlet estenda ThreadSafeServlet.
     DE. Fazer com que o servlet implemente o SingleThreadMode1.
     Dc.        Logar todas as chamadas dos métodos.
     12' D.     Usar exclusivamente variáveis locais, e se você tiver que usar as variáveis de instância,
               sincronizar o acesso a elas.

              - IJrs lJ/,f6es lJr e     8 síilJ tm::6f'N!.ffl.S        plJt''!re   IJ   rt.,..ell.dSo.feSe,..vle.f               ",íi/J
              exts-h    ",a Se,..ille.f. IJrPI       e   IJ   Sl"'5IeFt."'efJ.JMlJdel         é tiesap,../JiladlJ         ",4 vet'síi/J
              2..'-1 e ",íi.,   ,..ec6J/11eJ'1dll.d.,.


14   Dados os seguintes métodos:
  - ggetCookies
  - getContexPath
  - getAttribute
  Coincida os métodos acima com as seguintes classes ou interfaces. Note que cada método pode ser
  usado mais de uma vez.

     HttpSession                        '"5tt/lf:f.r:!:~~h.
                                                         ...
     ServletContext                     ...j.t:I:ft.H:r.fhl.f.e..o.           .5~~.'J.-k~fP.~f1.:.
                                                                                                .
     HttpServletRequest                 o ••   1-t:ft..~~!:,,!:~          . ..J.~ft.Hr.(~.I!.-k ....

                                 AJes-h ~6J'1.f6J "'ealJ/lleJ'1.f.eJ'1íiIJ  deve havet' J/IIf!.J/lla"")ll.jíi6 fl.SS,M. C6J/11<::1
                                 1Jtl4is m.e.ft:iJlJs fa,..tam. Sf!.",.f.,fÁlJem. cadll. esccfc.



15   O que é verdadeiro sobre a interface RequestDispatcher?                                 (Escolha tudo que se aplica.)


      12' A.    De seus dois métodos, forward( ) é usado com mais
               freqüência.                                                                                                                         I
      DE.       Seus métodos têm os seguintes argumentos: recurso,
                                                                                                      - Df}íi.,        8: 6 t'ectlt'sõ             e

               solicitação e resposta.                                                                espec'-ficlt.JlJ             '16 m.cl'iflePl.f-óda

      lllJ C . D epen d en d o dI' c asse cUJometo d o cna um
      1:""7                     a               .        .            C"','"4jíi., d., .,Qie.f6.
                                                                                         v
            RequestDispatcher, o caminho para o recurso a ser enviado
            mudará.
                                                                                                             - Dffíi.,           ~: se set/ set'lIle.f
      DD. RequestDispatcher,
           Independentemente                   da caminho para o recurso aum enviado
                                               o classe cujo método cria ser                                 t/sa,..     I
                                                                                                                       t/1iO'l   j!!./); I7t1P1ca
                                                                                                                                                        I
          NÃO mudará.                                                                                     f'6tie,..a         el7l1''"4,.. StliJ,

      DE.       Se seu servlet chamar RequestDispatcher.forward,      poderá    ,..eSf'6s.fa.
               enviar sua própria resposta para o cliente antes, mas não depois
               da chamada de envio.

222 capítufo 5
6 betenclétment9 da sessã9

                Estado de conversação




Os servidores web não têm memória curta. Assim que eles lhe
enviam uma resposta, eles esquecem quem você é. Na próxima
vez que você fizer uma solicitação, eles não o reconhecerão.
Em outras palavras, eles não se recordam do que você solicitou
no passado e nem do que eles enviaram como resposta. Nada.
Algumas vezes isso é bom. Porém, algumas vezes você precisa
manter o estado de conversação com o cliente durante várias
solicitações. Um carrinho de compras não funcionaria se o usuário
tivesse que escolher seus produtos e finalizar a compra de uma
única vez. Você vai encontrar uma solução extremamente
simples na API Servlet.




                                                                    você está aquí ;.   223
objetivos do exame oficial da Sun




                                &12
                                      06jctiV~f
                                      54;




G-eret1cialtettto de Sessão                         Notas sobre a Abrangência:
                                                     Todos os quatro objetivos do exame sobre
                                                     gerenciamento da sessão são completamente
4.1 Escrever o código do servlet para                cobertos neste capítulo (embora alguns destes
    armazenar os objetos dentro de um objeto         tópicos tenham sido falados no capítulo
    sessão e restaurar os objetos a partir de um     anterior). Este capítulo é a sua única chance
    objeto sessão.                                   para aprender e memorizar estes assuntos;
                                                     portanto, vá com calma:

4.2 Dada uma situação,    descrever as APls
    usadas para acessar   o objeto sessão,
    explicar quando ele   foi criado, descrever os
    mecanismos usados     para destruí-Io e quando
    ele foi destruido.



4.3 Utilizando os listeners da sessão, escrever o
    código para responder a um evento quando
    um objeto é adicionado a uma sessão;
    escrever o código para responder a um
    evento quando um objeto sessão migra de
    uma VM para outra.


4.4 Dada uma situação, descrever qual o
    mecanismo de gerenciamento da sessão o
    Container pode empregar, como os cookies
    podem ser usados para gerenciar as sessões,
    como a reescrita de URL pode ser útil no
    gerenciamento das sessões e escrever o código
    do servlet para executar a reescrita de URL.




224 capitulo 6
gerenciamento                da sessiD




       Eu quero que a aplicação da cerveja
        tenha uma conversa bidirecional
       com o cliente ... não seria legal se o
      usuário respondesse a uma pergunta,
          e a aplicação respondesse com
         uma nova pergunta, baseada nas
               respostas anteriores?


                            o
                            o




                                                         Kilt quer ltattter a cotwersação específica
                                                         COlto cliettte durattte as várias solicitações
                                                         Agora, a lógica do negócio no modelo checa o parâmetro
                                                         que vem da solicitação e devolve uma resposta (o
                                                         conselho). Ninguém na aplicação se lembra de nada que
                                                         tenha ficado com este cliente antes da solicitação atual.

                                                          o que ele tem AGORA:
                                                         public class BeerExpert   {
                                                            public ArrayList  getBrands(String color)
                                                               ArrayList brands = new ArrayList();

                                                                      brands.add(~Jack    Amber");
                                                                   if brands.add(~Red
                                                                        (color.equals(~amber"))
                                                                                         Moose");  {                                  ~


                                                                       else   {                                                        II

                                                                       brands.add(~Gout             Stout");
                                                                       brands.add(~Jail             Pale Ale");                         

                                                                   return     brands;      /IJ:Sct.ecalJ'tCSe~1'6t/e

                                                                                  ~        e~I'4il4       <Cor)   e tl&61veIM.6S        4
                                                                                      ~    resf~           I,""'l~           rela'i4" ti4S

                                                                                               ".   ;
                                                                                           ~C4S(1.10 3t1f p6SstlflJ
                                                                                           "146 e      c6#'Ise!l.t:ll>'Ul·   ~tlfla c6r).
                                                                                                                               <fi            ís-k
                 ,
                           ,   /       L
D IJ'tctielc (a ICjtCa tic $1e56c1(;)'n:"1J't
ave tiesccbrtr
                                        ".


                      se "'a 1~/erlJ'taS4C
                                                          O que ele QUER:
                                                          public class BeerExpert     {
                                                             public NextResponse     getAdvice(String  answer)                                  {
svltete,,-h    fara     la;er   VlJ4
                                                                  li
                                                                   Processar a resposta do cliente
reC6IJ'te#'/ti«S4e(ev s!ia., tiar « tilca                 procurando   em TODAS as
II~IJ.{)J e case #'/4Ct.'Ea., ele +e •• Jve                     Ilrespostas   anteriores   dele, assim como na
                ,               J           /             resposta da
e#'/vlÍlr a fr6X1'lM,apel'5(1'Tr"a 0.6 (lSVar,6.
                                                                Ilsolicitação   atual. Se houver informação
                                                          suficiente,
                                                                Ilretornar  o conselho final, ou então,
                                                          retornar a próxima pergunta
                                                              }


                   SVp6ltka ôve a classe AJex1-Jeesf6ltse (ltc4psv1e                      <3   fl':Xi"IYII.l           <t    seI' eXi!J,i/.
                  p41'4 <3 vsv:l'tt.         e 4~1.l ôve ,'l'Jd'jv( se es+e       é ()Ctmse'&.1J               IJVav.fl'Q. fel'~

                                                                                                           você está          aqui..          225
conversação com cliente



Ueve funcionar        COtMOutMa conversa        NORMAL ...
                                                                    Drinque com guarda-chuva
                                                                    vermelho? Oooooh, isso é
                                 Cara, eu estou numa festa
                                                                RUIM. Foi bom você ter ligado ...
                                aqui em Joe's beach e estou
                                                                 deixe-me perguntar uma coisa:
                                  segurando, literalmente,
                                                                primeiro, você quer escura, bock
                                  um drinque com um lindo                    ou clara?
                               guarda-chuva vermelho ... você
                               precisa trazer cerveja para cá                D
                                           AGORA!                            o
                                            O
                                             o
        o
        Q




            oCl




            ia.
 226              6
gerenciamento   da ~



COtMO pode tMotlÍtorar as respostas
     ele                                             do eliettte?
o projeto  do Rim só funcionará se ele puder acompanhar
tudo que o cliente já tenha dito durante a conversa, e não
apenas a resposta da solicitação atual. Ele precisa do
servlet para conseguir os parâmetros da solicitação. que
representam as opções do cliente e salvá-Ios em algum
lugar. Cada vez que o cliente responde uma pergunta,
o mecanismo de conselhos usa todas as respostas
anteriores dele para retomar ou uma outra pergunta, ou a
recomendação final.
Quais são as opções?



Usar um enterprise javabean stateful session
Claro, ele poderia fazer isso. Ele poderia transformar seu
servlet em um cliente para um bean stateful session, e toda
vez que uma solicitação chegasse, ele poderia localizar
este bean. Daria um certo trabalho, mas sim, você pode
certamente usar um bean stateful session para armazenar
um estado de conversação.
Mas isto geraria muito tráfego. Mataria a aplicação! Além
disso, o provedor de hospedagem do Rim não tem um
servidor J2EE completo com um Container EJB. Ele tem
                                                                 o 9bJet9   BttpSess'I9n
um Tomcat (um Container web) e só.                               p9de mélnter 9 estéld9 de
                                                                 C9nv'erSélyã9durante várIas
                                                                 s91'lc1tlyges d9 mesm9
Usar um banco de dados
                                                                 cl1ente.
Isto também funcionaria. O provedor dele permite acesso
ao MySQL; portanto, ele poderia fazer isto. Ele poderia
escrever os dados do cliente em um banco de dados ... mas        Em 9uttélS pélIélv'tQ,'5.
                                                                                        ele
isto impacta a performance de runtime, da mesma forma
que o enterprise bean o faria, talvez até mais. E muito mais
                                                                 pers'Iste p9t umél sessã9
                                                                        v
do que ele precisa.                                              Intelrél C9m um detetm'Inéld9
                                                                 clIente.
Usar um HttpSession                                              f9dem9s     usâ-19
Mas você já para manter Nós podemos usar um objeto
HttpSession sabia disso. o estado de conversação durante         gUqtdm tUd9 que recel~m9s
                                                                              .v
várias solicitações. Ou seja, para uma sessão inteira com este
cliente.
                                                                 d9 clIente em t9dQ,':lélS
(De fato, o Rim ainda teria que usar um HttpSession,
mesmo que ele escolhesse outra opção, como um banco de
                                                              S91lCltaygeS ~.,ueele         taz
dados ou uma sessão bean, pois se o cliente é um browser, dutélnte
ele ainda teria que fazer coincidir um cliente específico com
um banco de dados específico, ou a ID do session bean.
Como você verá neste capítulo, o HttpSession cuida desta
identificação.)

                                                                               você está
sessões em ação



Co",o as sessões funciona",



o   Diane seleciona "Escura"
    e c1icano botão submit.
                               o Container envia a solicitação
                               para uma nova thread do
                                                                   A thread BeerApp encontra
                                                                   a sessão associada a Diane e
                               servlet BeerApp.                    guarda a sua escolha ("Escura")
                                                                   como um atributo na sessão.

                                                                   SetAtributeO




                    o servlet executa a sua lógica (inclusive chama o modelo)
                    e retorna uma resposta ... neste caso, uma outra pergunta:
                    "Qual é a variação do preço?"




e   Diane lê a nova pergunta
    na página, seleciona
    "Cara" e pressiona o
                                                           A thread BeerApp
                                                           encontra a sessão
    botão submit.        O Containerenvia a solicitação    associada à Diane e
                         para uma nova thread do           armazena a Suanova       Mesmo cliente
                                                                                    Mesmo servlet
                         servlet BeerApp.                  escolha ("Cara") como
                                                           um atributo na sessão.   Solicitação diferente
                                                                                    Thread diferente
                                                                                    Mesma sessão

                                                       / Set AtributeO




228 capítulo 6
gerenciamento     da


o                   Oservlet roda sua lógica
                    (inclusive chama o modelo) e
                    retorno uma resposta ... neste
                    caso, uma outra pergunta.




Nesse meio tempo, imagine que OUTRO cliente vai para o site de cerveja.,
    A sessão de Diane ainda              o Container envia a          A thread BeerApp inicia uma
    está ativa, mas enquanto             solicitação de Terri         nova Sessão para Terrí e chama
    isso, Terri seleciona "Clara"        para uma nova thread         o setAttributeO para armazena
    e pressiona o botão submit.          no servlet BeerApp.          a sua escolha ("Clara").




                                                                                      Cliente diferente
                                                                                      Mesmo servlet
                                                                                      Solicitação diferente
                                                                                      Thread diferente
                                                                                      Sessão diferente


                        IJ,tS       svel'tllõs   ôve as l'eSp6s+as
                        da. 1€1'I'l e da. blal7e se ",rs+vN:", •••

                        p61'+a.17+6;cada vIIa precisa. dõ sev
                        õtje+õ S(f!ss;'õSeparfJ.dõ.




                                                                              você está aqui ~            22
identificando   o clíente



UtIt probletlta ... COtltOO Contaitter vai saber                                Como o Container
quetlt   éo   cliettte1                                                        reconhecerá que é a
                                                                               Diane e não a Terri?
o protocolo HTTP usa conexões stateless. O browser do                          O HTTP é stateless,
cliente faz uma conexão para o servidor, envia a solicitação,                      portanto, cada
obtém a resposta e fecha a conexão. Ou seja, a conexão                        solicitação é uma nova
                                                                                      conexão ...
existe apenas para uma única solicitação/resposta.
Devido à conexão não persistir, o Container não reconhece
que o cliente que fez a segunda solicitação é o mesmo de
                                                                                     o
                                                                                     a
uma solicitação anterior. Para o Container, cada solicitação
é de um novo cliente.
                                                 Eu sinto muito, mas
                                                  não me lembro de
                                                você. Tenho certeza
                                               que nós dividimos bons
                                                momentos juntos, mas
                                              teremos que recomeçar.

                                                           ()
                                                            o
                o
                tJ




                 Nã9 ex1st~m
         feth'untas ldl9tas
r:   Por que o Container não pode
simplesmente usar o endereço IP do cliente? É
                                                       r:   Que tal as informações  de segurança?
                                                       Se o usuário está logado e a conexão é segura
parte da solicitação, certo?                           (HTTPS), o Container sabe EXATAMENTE
                                                       quem é o cliente, certo?

1: Ah, o Container pode obter o endereço      IP da
solicitação, mas isso identifica exclusivamente o      1: Sim, se o usuário  está logado e a conexão
cliente? Se você está em uma rede IP local, você       é segura, o Container pode identificar o cliente
tem um único endereço IP, mas há chances de que        e associá·lo a uma sessão. Mas isto é um
ele não seja reconhecido externamente. Para o          grande "se". A maioria dos bons webdesigners
servidor, seu endereço IP é o endereço do roteador;    diz: "Não force o usuário a fazer login até que seja
logo, você tem o mesmo endereço IP que todo            realmente necessário, e não troque a segurança
mundo tem na sua rede! Então o IP não ajudaria!        (HTTPS) enquanto não for realmente preciso." Se
Você teria o mesmo problema: os itens do carrinho      os seus usuários estão só navegando, mesmo
do Jim poderiam ir parar no carrinho do Pradeep        que estejam só colocando artigos no carrinho de
e vice-versa. Então não, o endereço IP não é           compras, você talvez não queira a sobrecarga
uma solução que identifique exclusivamente um          (para você ou eles) de tê·los autenticados no
determinado cliente na internet.                       sistema até que decidam finalizar a compra! Por
                                                       isso, precisamos de um mecanismo que crie
                                                       um Iink entre um cliente e uma sessão que não
                                                       requeira autenticação segura. (Entraremos em
                                                       detalhes sobre segurança no ... espere por ele ...
                                                       capítulo de Segurança.)

230 capítulo 6
gerencíamento   da sessãc



o cliettte   precisa deutta única session lU
A idéia é simples: na primeira solicitação do cliente, o Container
gera uma única session ID e a devolve para o cliente juntamente
com a resposta. O cliente envia de volta a session ID com cada
solicitação subseqüente. O Container verifica o ID, encontra a
sessão correspondente e a associa à solicitação.



                                            Sim, mas eu não guardo o estado das
                                             solicitações e não me lembrarei de
                                             você. Por isso, estou te dando uma
                                              única session ID. Você DEVE me
                                              devolvê-Ia toda vez que fizer uma
                                            solicitação e eu saberei quem é você




             o
              Cl


                    •    solicitação , "ale", ID n-42
                                                  o




                                                        container




                                                                                      você está
alegria dos cookies




        Como o Cliente e o Container trocam as
        informações da Session lO?

       De alguma fonua, o Container tem que entregar a session ID para o
       cliente como parte da resposta. Por sua vez, o cliente tem que devolver
       a session ID como parte da solicitação. A maneira mais simples e
       comum para essa troca de infonuações é através de cookies.
      Cooldes
                                                       n,
                                    f) H Se-l-c.lJIJl:te e apel1l1.S                        I.
                                                                                        FoI/rrl'''      Aqui está o seu
                                                                                                        cookie com uma
                                    t.eatiel' e"vl'4tic             114   I'f!SPOS';"4.
                                                                                                        session ID dentro ...
                          HTTP/1.1 ?~O0EKSSIONIO=OAAB6C80E415
                          Set·Cookle. JS
                          Content-Type:         text/html
                          Content-Length:         3t 2003 03:25:40        GMT
                          SelVer: Apache-Coyote/1.1
                          Connection:     close


                          <html>




                         "Có/;J:,"e"      é VI/f! IJV';"I'IJ t.eatier
                                        J>;tJ   petittllJ

                                                                                                      Tudo bem, aqui está
                      POST     /select/selectBeerTaste               2 .d o HTTP/1.1                 o cookie com a minha
                      Host: www.wickedlysmart.com                                                         solicitação


                      User-Agent:      Mozilla/5.0              _   AAB6C8DE415
                      Cookie: JSESSIONID-O                             ..
                                    r tion/xml                       apphcatlonl
                      Accept: text/xml,ap~           I:~    9 text/~lain;q=o.8,video/x-
                      xhtml+xml,textlhtml,q-
                      mng,image/png,image/Jpeg,lmage
                                             .. '.                        / 9 if'q=O.2,*I*;q=O.1
                                                                                 ,
                      Accept-Language:             en-us, en·q-O 5
                                                             ,-.
                      Accept-Encoding:            gzip,defiate




232 capítulo 6
gerencíamento                    da sessão



A tMelhor parte: o Container faz quase todo o
trabalho do cooldel
Você tem que informar ao Container que você quer criar ou usar
uma sessão, mas é o Container que gera a session ID, criando um
novo objeto Cookie, inserindo a session ID dentro do cookie e
configurando o cookie como parte da resposta. E nas solicitações
subseqüentes, o Container recebe a session ID de um cookie da
solicitação, compara-a com uma sessão existente e associa essa
sessão com a solicitação atual.




HttpSession      session     request.getSession(}


É isso aÍ. Em algum lugar do seu método
você solicita uma sessão e as demais tarefas
acontecem automaticamente.
Você   não   cria o novo objeto HttpSession.
Você   não   gera a session ID exclusiva.
Você   não   cria o novo objeto Cookie.
Você   não   associa a session ID com o cookie.
Você não configura o Cookie na resposta (sob o
header Set-Cookie).
Todo o trabalho do cookie acontece nos
bastidores.


Obtendo a sessão ID da SOLICITAÇÃO:

HttpSession      session   = request.getSession()                     I              .          ()   ~.,.f.Jt.11'"       CD,,/:."e
                                                       ; ~   () Wle.f"JIJ          f(;.I·1i.         fJ              I
                                                                          . !J) (e CDl'l'e/4c"()"II.-11J
Parece familiar? Sim, é exatamente o mesmo método            sessllJI'I.....            h"./-e> é"
usado para gerar a session ID e o cookíe para a respostat    IJ.   11W1fJ.   sf!S S4"          ;;~~A-Jt.      11'"   C04/:.1e•••.

                .     -              I.
IF (a solicitacão inclui um cookie da session lD)
    encontrar a sessao que se corre aCIona com a
                                                     ID
                                                                             .! í ~~~ vi.
                                                              Wles",D flJ.l'J)1J.
                                                              Sf!SSliJI'I'
                                                                               •
                                                                                   . ...
                                                                                      •.
                                                                                  ( ",1101'4 VDCe fDS S4
                                                                                                                          "C4
                                                                                                                         •••.
                                                                   4 seSSIDYi      e                       ,)
ELSE IF (não existe nenhum cookie session                                     'H         l1e IJ I;,.IM'",e •
ID or não existe no momento nenhuma sessão                         SDI,.c,..f41' I.l seSS41J Z
correlacionada à session ID)
    criar nova sessão
Todo o trabalho do cookie acontece nos bastidores.




                                                                                               você está
hecando par1 uma nova sessão



: se eu quiser saber se a sessão já existia ou
;oi eriada agora?
~oa pergunta. O método de solicitação-padrão,
~etSessionO, retoma uma sessão independentemente de
~xistir uma sessão anterior. Já que você sempre obtém uma
nstância HtlpSession daquele método, o único jeito de
;aber se a sessão é nova seria perguntando a ela.

   public void doGet(HttpServletRequest           request, HttpServletResponse response)
                                                     throws IOException, ServletException

        respons~. setContentType ("text/ht~l") ;
        PrlntWrlter out = response.getWrlter();                       () 5e.-I-.:5essií:mO seilPlf>l"e re-/-lJl"n4
                                                                                   N               •••••N
        out.println ("test session attributes<br>");                  V;1I14sessa6 ••• ;1I1asV4ce niló ftJJe

        HttpSession session = request.        getSession
                                                             V::--.
                                                              () ;
                                                                                    f             N
                                                                      0.1'1";11141" e vll>la sessa6 "(JVil) a
                                                                                 se
                                                                      ;1I1en4S!ve v6cê per5vnff          a ela.

        if    (SeSsion.isNeW(~                                       () tsAJewO    re.flJl"nQ, ClJII>I
                                                                                                     vel"JaJei'ra

              out.println ("This is a new session. ");               se   6 c/te,,+e Q,1Í7Jfi. l"eSp4nJef.l
                                                                                            "ãlJ
             else {                                                  ca;1l1es.f-e Sesst4"    ZÔ.
              out.println("Welcome back!");




Y:    Você obtém uma sessão chamando o
                                                           Os métodos que tratam o evento, definidos
                                                           pelas ínterfaces do Iistener relacionados
request.getSessionO, mas esse é o único
jeito de consegui-Ia? Não podemos usar o                   às sessões, recebem um argumento do
ServletContext?                                            tipo HUpSessionEvent, ou sua subclasse,
                                                           HUpSessionBindingEvent.     E o HUpSessionEvent
                                                           têrn um método getSessionOl
1:     Você obtém uma sessão através do                   Então, se você implementa alguma das
objeto response porque - adivinha - a sessão é             quatro interfaces lístener relacionadas às
identificada pela solicitação. Quando você chama           sessões (falaremos sobre esse assunto mais
o getSessionO no Container você está dizendo:              adiante neste capítulo), você pode acessar a
"Eu quero uma sessão para ESTE cliente ... ou a            sessão através dos métodos de callback que
sessão que coincide com a session ID enviada               tratam o evento. Por exemplo, este código
pelo cliente, ou uma nova. Mas, em ambos os                é de uma classe que implementa a interface
casos, a sessão é para o cliente associado com             HUpSessionListener:
esta solicitação."
Mas existe um outro jeito de você conseguir a                 public void
sessão ... através de um objeto evento da sessão.             sessionCreated(HttpSessionEvent
Lembre-se, uma classe listener não é um servlet ou            event) {
um JSP - é apenas uma classe que quer conhecer                            HttpSession       session =     evento
os eventos. Por exemplo, o listener pode ser um
                                                              getSession () ;
atributo tentando descobrir quando ele (o objeto
atributo) foi adicionado ou removido de uma sessão.
                                                                          Ii   evento que segura o código



234              6
gerencíamento              da sessão



E   se eu quiser APENAS uifta sessão pré-existettte?

Você pode se deparar com uma situação na qual o servlet quer usar
apenas uma sessão já criada. Pode não fazer sentido para o servlet
responsável pelo checkout, por exemplo, iniciar uma nova sessão.
Então, existe um método sobrecarregado getSession (booleano)
apenas para esse propósito. Se você não quer criar uma sessão
nova, chame o getSession (false) e você obterá ou um HttpSession
nulo, ou um já existente.
O código abaixo chama o getSession (false) e verifica se o valor
retomado foi nulo. Se/ai nulo, o código exibe uma mensagem e
então cria uma nova sessão.

     public   void doGet(HttpServletRequest    request,        HttpServletResponse                            response)
     throws   IOException,  ServletException   {
                                                                   {)      N      N                                             I
                                                                   nJ,sS(V' /4Is(J sl;,,/'I1"(;4                          ó II';é.+IJJa
         response.setContentType(~text/htrnl");_J ();
         PrintWri ter out = response. getWri ter                    rer6r,,4        ViJI';tJ.
                                                                                                    N._           J_
                                                                                                seSS46 pre-exls-n:~              J_


         out. println (~test sessions<br>");                        6V ~/tl.J C4S6"';,6 t,~4 ~11;"lIiltla St!SS'i6

                        session
                                                     ~              aSS6Cl'aJtJ.
                                                                               a            em c1t"ePrh.
         HttpSession               request.getSession(false);
                                                                                                                             I
                                                                 fJr3vt  ,,:S paJell';6S +es-f-ar
         if    (session=null).                   .               exts-/-ta VII';tJ. ess';,(J
                                                                                  s
               out.println(~no  seSSlon was avallable");
               out.println (~rnaking one ... ");                 paJra6N.       J    I 11.
                                                                               tvfhv'Crr
                                                                                      •



              else {                                             resv     .,.a"l6 I1V           <:)   •


               out.println(~there  was a session!");
               session ~ request.getSession();  ~                         I'    J               !.,)
                                                          A-3vt '",:s SA-$íM,tJS
                                                                           N
                                                                                                       alie
                                                          vII';a l7(Jva ses S/t,6.




r: o   código acima não é simplesmente
uma forma ineficiente e tola de fazer a mesma
                                                         r:  Então, parece que o getSession(true) é
                                                         eX;atamente o mesmo que o getSessionO ...
coisa da página anterior? No fim das contas,
você acabou criando uma nova sessão.
                                                         I:  Acertou novamente. A versão-padrão é uma
                                                         conveniência para aquelas ocasiões em que você
I:   Você está certo. O código acima é apenas
para testar como funcionam as duas versões do
                                                         sabe que quer uma sessão nova ou existente. A
                                                         versão que leva um booleano é útil quando você
getSessionO . No mundo real, a única vez que             sabe que não quer uma nova sessão, ou quando
você pode querer usar o getSession (false) é             a decisão de se criar uma nova versão acontece
quando você NÃO quer criar uma sessão nova.              no runtime (e você está passando uma variável
Se o seu objetivo for criar uma sessão nova e            no método getSession(algum 800Ieano».
ainda assim, responder de forma diferente se
você sabe que ela é uma sessão nova (e não
uma que já exista), use o método getSessionO
padrão e pergunte à sessão se ela está usando
agora o método isNewO do HttpSession.



                                                                                                      você está
quando os cookies falham




                                                  Você~        criar as sessões lfteslftO
                                                 quatldo o clietlte tlão aceitar os cookies,
                                                 Iftas dará Ulftpouco Iftais de trabalho ...
                                                Não concordamos que alguém com metade do
                                                cérebro desative os cookies. Na verdade, a maioria
                                                dos browsers já tem cookies habilitados e tudo é
                                                maravilhoso. Mas não há garantias.

                                                Se sua aplicação depende das sessões, você precisa
                                                de um modo diferente para o cliente e o Container
                                               trocarem informações sobre a session ID. Sorte para
                                              você, pois o Container sabe como tratar um cliente
                                              que reCUSaum cookie, mas isto requer um pouco
                                              mais de esforço da SUaparte.

                                              Se Você usar o código da sessão da página anterior
                                              ~ chamando o getSessionO na solicitação ~ o
                                              Container tenta Usar os cOokies. Se os cookies não
                                              estiverem habilitados, significa que o cliente nUnca
                                             se juntará à sessão. Ou seja, o método isNewo da
                                             sessão se111preretórna verdadeiro.




                                 O cliente COI1"l hea
                                                     cookie$ desabilitados
                                 irá ignorar os Os·ders "Set-Cookie" da

                                 resposta                   , N receberá nenhuma
                                           .     . kies voce nao          .    .
                   Se um cliente não acertar :o~a ou' sirene soará para mforma-
                        ão Nenhuma campam .. .           ma sessão para este
                   'f::~qu~ a sua ''':.'ta'',ad;ou~;~~er que o clien,eignora
                   cliente falh~u. ~a~:::k:~a~      um cookie comRL s~s:;~:~~e
                                                                  ..· a
                   a sua tentatlva e .. ..' •rO·.· eescreve a U ,s ~       .     .
                              'd"go se voce N/1. r ,        7TOVA sessao (rsto e,
                   No seu co l. ,             t . nara uma lV'        .,    h ar
                   uma que. sem r.e re °Z' t. ~~erdadeiro" uma so ler
                   o get&",ionO sem~r~:: nunca dev.olve
                                 ..'P.                        quaudv "7,ce,':u,;;;;
                                                                                 que
                   o isNewvri header O c coa kie daseSSlOn ID .
                      .
                   tenha um ne l,i do rene
                                    a/o                  .


236     6
gerenciamento                da sessão



Reescrita de URl.: utlta alterttativa

Se o cliente não aceitar cookies, você pode usar
a reescrita de URL como uma segunda opção.
Supondo que você faça a sua parte corretamente, a
reescrita de URL sempre funcionará - o cliente não                                                                              "   "d=1234567
se importa com o que está acontecendo e não faz                                                          ;isess,on'
nada para impedir. Lembre-se de que o objetivo é
que o cliente e o Container troquem informações
sobre a session ID. Trocar cookies é a maneira mais
simples de compartilhar session IDs. Mas se você
não puder colocar uma ID num cookie, onde você o
colocará? A reescrita de URL carrega a session ID
que está no cookie e a encaixa bem no final de cada
URL que a aplicação recebe.
Imagine uma página em que todos os links tenham
um pouco de informação extra (a session ID)
direcionada para o final da URL. Quando o usuário
clicar naquele link "melhorado", a solicitação vai
para o Container com aquele bit extra no final, e o
Container simplesmente retira a parte extra da URL
e a usa para encontrar a sessão correspondente.




                 HTTP/1.1 200 OK                                                                    .      z"h         1M
                                  397                                   AJ,'ciAI'141r10S sf!.Ssu,n
                                                                                       4l                        !I
                 Content-Length:       3 03'25-40 GMT                  I'f'" ~                                        'li A f
                 Date: Wed, 19 Nov 200
                 server:Apache-COyotel1.1
                                           .'                           J", I'A -IA "" as U/t.{...s ntl
                                                                       "' •• "1"v"'.....
                                                                                                          rrr
                                                                                                           I L
                                                                                                            fVl.'-l)IIf.
                                                                                                            I
                 Connection: close                                     titlltllllf!.IrIOS ;:01rl0 /t.espOS-r4.
                 <html>                                                           ~,
                   <body>                     . k dlysmart.comlBeerTest.dO;jSeSSIOmd-O
                    <a href.=''http://WWW.w1c    e
                       c1ick me
                     <Ia>
                   </body>
                  </html>
                                                                     Resposta HTTP




                                                                                   A- sessl,U"I
                                                                                                 ,.. /I
                                                                                                        Ib 1/01-1-4 ;:0""'0
                                                                                                                  /I
                                                                                                                                     11""'4


                                                                                   1;'!6rW4fj4ó          ex-l-ro.              ,;,serltia nó ";'0./



                                   GET 1BeerTest c1'-
                                   HTTPi1.1
                                                           .
                                                                   I       ,
                                                 . o,JSeSSlOnid=OAAB6C8DE415
                                                                              !    "ti. vJ(.{... "4 S6IlCl-l-tJ.jãó. (() p6n-1-ire-
                                                                 v/riu/ti. e espec/!lc6
                                                                                    /                                       fie !drlc41'1-n:.J
                                                                                                                                           i._



                                   Host:     WWW.wickedrysmart.com
                                   User-Agent:     MOZiJla/5.0
                                   Accept:    textlxmJ,apPlication
                                  html;q~O.9,teXtlpl.. am,q~O.8,vldeo/x_'
                                  -.             .       .. _    /xml,apPlication/xhtm/+xml  ,t extl
                                  JPeg,lmage/glf:q~O.2, '/*;q~O.1         mng,lrnage/png,imagel
                                  Accept-Langu         .
                                  A                age. en-Us,en;q~O.5
                                    ceePt-EncOding: 9Zip,deflate

                                                             Resposta HTIP


                                                                                                                           você está
reescrevendo      a URL


A reescrita de URI. Só etttra em cetla se os cookies
falharem e Só se você matldar a resposta codificar a URI.
Se os cookies não funcionarem, o Container recorre à reescrita de URL, porém
só se você tiver feito o trabalho extra de codificar todas as URLs que você
enviará na resposta. Se você quiser que o Container fique configurado por padrão
para usar os cookies primeiro, com a reescrita de URL apenas em último caso,
você pode relaxar. É exatamente assim que ele funciona (exceto na primeira
vez, mas chegaremos lá num minuto). Mas se você não codificar as suas URLs
explicitamente - e o cliente não aceitar cookies -, você não precisa usar as
sessões. Se você codificar mesmo as suas URLs, o Container primeiro tentará
usar os cookies para o gerenciamento da sessão e recorrerá à reescrita de URL
apenas se a técnica do cookie falhar.

   public      void   doGet(HttpServletRequest         request,     HttpServletResponse          response)
                                                                                   throws        IOException
            response.setContentType("text/html")          ;

            PrintWriter
            HttpSession   out ~ response.getWriter();
                          session = request. getSession           (); ~            J._              N
                                                                               tJb-n::t' Vit4 seSSfJ,t)

            out.println("<html><body>");
            out.println ("<a href="" + response.encodeURL("/BeerTest.do")                       + "">click   me</
   a>/f);
            out.println("</body></html>");                      ~               í
                                                               4 1i1ltJt'itfJ.s'io eX+r4   Ja ses siim
                                                 IlJ   ptU'fi. eS+4 UJe.L.




r:   Espere um momento ... como o Container
SABE que os cookies não estão funcionando?
                                                              1: session 10 dose o Container não conse~uir
                                                              uma
                                                                   Lembre-se,
                                                                                cliente, ele nem SABERA
E em que ponto o Container decide usar a                      que esta é a próxima solicitação daquele cliente.
reescrita de URL?                                             O Container não tem como saber que ele
                                                              tentou os cookies da última vez e que eles não
                                                              funcionaram. Lembre-se, a ÚNICA forma de o
1: Um Container    burro de verdade não se                   Container reconhecer que ele já viu tal cliente
                                                              antes é se o cliente enviar uma session 10!
preocupa se os cookies estão funcionando ou
não - ele vai sempre tentar enviar o cookie E                 Então, quando o Container percebe que você
fazer uma reescrita de URL toda vez, mesmo que                chamou o request.getSessionO, ele entende que
os cookies estejam funcionando. Mas eis como                  precisa iniciar uma nova sessão com este cliente.
um Container decente trata isso:                              Ele envia a resposta com um header "Set-Cookie"
Quando o Container vê uma chamada para o                      para a session 10, e esta, anexada à URL (supondo
getSessionO sem que tenha recebido a session                  que você usou o response.encodeURL()).
10 com a solicitação do cliente, ele sabe que                 Agora imagine a próxima solicitação deste
deve tentar iniciar uma nova sessão com o                     cliente. Ela terá a session 10 anexada à URL da
cliente. Até aqui, o Container não sabe se os                 solicitação, mas se o cliente aceitar cookies, a
cookies funcionarão, mas com esta primeira                    solicitação TAMBÉM terá um cookie session 10.
resposta enviada ao cliente, ele tenta os cookies             Quando o servlet chama o request.getSessionO,
e a reescrita de URL.                                         o Container lê a session 10 para a solicitação,
                                                              encontra a sessão e pensa consigo, "Este cliente

r:   Por que ele não pode tentar os cookies
primeiro ... e fazer a reescrita de URL na
                                                              aceita cookies, então posso ignorar as chamadas
                                                              response.encodeURLO.       Na resposta, vou enviar
                                                              um cookie, pois eu sei que ele funciona. E não há
próxima resposta, caso não consiga receber                    nenhuma necessidade de uma reescrita de URL,
um cookie?                                                    por isso, eu nem me preocupo ..."


238     capítulo 6
gerencíamento       da sessão



A reescrita de URL funciona            COIft   o sendRedirectU
Você pode encontrar uma situação em que você queira redirecionar a
solicitação para uma URL diferente, e ainda assim usar uma sessão.
Existe um método para escrever uma URL especial para isso:

   response.encodeRedirectURL(~/BeerTest.do")



f:    E quanto a todas as minhas páginas HTML
estáticas ... elas estão cheias de Iinks <a href>. Como eu
faço reescrita de URL nessas páginas estáticas?
                                                                 J.   teescdta de UIL é
                                                                           ? "
1: Você não faz! A única maneira     de usar a reescrita de     aut9mélfica...
URL é se TODAS as páginas que são parte de uma sessão
forem dinâmicas! Você não pode fazer um hard-code das            Y9ce c9d'itlc9u suas UILs.
session 10s, obviamente, visto que o 10 não existe até
o momento da execução. Então, se você depende das
sessões, você precisa da reescrita de URL como uma
                                                                VOCÊ tem ~ue t9dat
estratégia alternativa. E já que você precisa da reescrita      t9das as suas UILs élttavés
de URL, você tem que gerar dinamicamente as URLs
na resposta HTML! O que significa que você teria que
processar o HTML no runtime.
                                                                 d9 mét9d9 de                       9bjet9
Sim, esta é uma que~tão de performance. Portanto, você_
deve pensar com carinho sobre os lugares onde as sessoes
                                                                 tesp9:'!ta - enc9deUItL() 9U
s~~ importa~tes para a sua aplicação - e se elas são
cntlcas ou simplesmente boas.
                                                                 enc9deIted'itectUItL() - e 9
                                                                 C9nta1netté:Z
f:  Você disse que para usarmos a reescrita de URL,
as páginas devem ser dinâmicas. Portanto, quer dizer
que eu posso fazer isso com os JSPs?


1: Sim! Você pode criar uma reescrita    de URL em um
JSP. Existe até uma tag JSTL bem simples que faz isso
                                                                                        -o da URLé
facilmente, <c:URL>, que você verá quando chegar no
                                                                            A codificaça Resposta!
capítulo que trata das tags customizadas.                                   tratada peta


f:    A reescrita de URL é específica por fabricante?
                                                               encode URLO e a go
                                                                                      e o método
                                                               Não se esqueç~ dei qUque você chame: nO seu
                                                                                         onse! roce nao o
                                                                                              TT.    A


                                                                    .
                                                                objeto  HttpServletResp nem no seu contexto
                                                                                  . -
1:     Sim, a reescrita de URL é específica por fabricante. O chama na sOliclta?aoLembre_se de que o
                                                                        objeto sessao. _ d URL é todo
Tomcat usa o ponto-e-vírgula ";" para anexar a informação        oU no
                                                                   rocesSo d e codijicaçao a
extra à URL. Outro fabricante talvez use uma vírgula ou          p      .   d à resposta.
algo diferente. E enquanto o Tomcat adiciona "jsessionid="        relacwna o
na URL reescrita, outro fabricante pode anexar apenas
a session 10 em si. A questão é, aquilo que o Container
usa como separador é reconhecido por ele quando uma
solicitação chega. Então, quando o Container encontra
um separador que ele usa (ou seja, o separador que ele
adicionou durante a reescrita de URL), ele sabe que tudo o
que vem depois é "informação extra" que ele mesmo colocou
lá. Em outras palavras, o Container sabe como reconhecer e
analisar o material extra que ele (o Container) anexou à URL.

                                                                                    você está            ~   239
gerencíando sessão




                      Não seja enganado com o parâmetro da solicitação
                      "jsessionid" ou o header "JSESSIONID".

      VOCÊ não deve jamais usar o "jsessionid". Se você encontrar um parâmetro de solicitação "jsessionid",
      alguém está fazendo algo errado. Você nunca deveria ver algo assim:

         String sessionID = request.getParameter(~js

      E você não deveria ver um header customizado       "jsessionid"     em uma solicitação ou resposta:

         POST Iselect/selectBeerTaste.do          HTTP/l.l
         User-       ent:    Mozilla/5.0

          JSE         ID: OAAB6C8DE415     f--                     :5YI';e-se 3ve s~a V~ "faJet'!
      Aliás, o   úNIco lugar em que um "jsessionid" deve ficar é dentro de um header cookie:
         POST /select/selectBeerTaste.do          HTTP/l.l
         User-Agent: Mozilla/5.0                                     '_
         Cookie: JSESSIONID=OAAB6C8DE415~                IS+6    es+aeet'+6;       ""as 174611'1.]1'1.1'61'8I'leslfl.t'J.
                                                                                                       si
      Ou anexado no final de uma URL como "informação           extra'"                   () I'f!Su!.f.aJ6 J4 l"eesct'/-+lI. «e
         ,                                                                ,               lJ/t.L. (você h~!Jélfl.   17a'<1   deve

         POST /select/selectBeerTaste.               j
                                                do; sessionid=OAAB6C8DE415 ~              la5el" /'S+O).




                               Pootos de bala
                            • A reescrita de URL adici          '
                            as URLs no HTML que v o?a a seSSlOnID no final de todas
                                                     oce eSCreve na resposta.

                        • A session ID retoma              r'
                        "extra" no final da URLcoml·a
                                                so IClÍa a,
                                                    ..sOdlcltaÇãOcomo informação

                        • A reescrita de URL Ocorrerá auto     '
                          não funcionarem com o di . t . • matIca~ente se os cookies
                          explicitamente todas as U~ e, mas V?Ce tem que codificar
                                                      s que voce escrever,

                       • Para codificar uma URL h
                       encodeURL( uma s'·tnng). ., c ame tesponse.
                            oUt.print1n(~<a href='.
                             + response,enco4eURL(~/
                             + ~'> I'               BeerTest,4o"}
                                   c lck me</a>");


                      • Não existe forma de con .'                  ,
                        automática nas SuasPág::~=a           reescnta de URL
                        das sessões você deve usar·     . ,~as. Logo, se você depende
                                   ,                as pagmas geradas dinamicamente,


240              6
gerenciamento          da sessão




                                       Livrat'ldo-se das sessões
                                       A cliente entra, inicia uma sessão, muda de idéia e
                                       sai do site. Ou a cliente entra, inicia uma sessão e seu
                                       browser trava. Ou a cliente entra, inicia uma sessão e a
                                       finaliza fazendo uma compra (check-out do carrinho de
                                       compras). Ou o computador dela trava. Seja o que/oro

                                       A questão é que os objetos da sessão usam recursos.
                                       Você não quer que as sessões fiquem lá além do tempo
                                       necessário. Lembre-se, o protocolo HTTP não tem
                                       nenhum mecanismo que informe ao servidor que a cliente
                                       já foi. (Em termos de aplicação distribuída, para aqueles
                                        que estão familiarizados, não há nenhum leasing.)*

                                       Mas como o Container (ou você) sabe que a cliente
                                       foi embora? Como o Container sabe que o browser da
                                       cliente travou? Como o Container sabe que é seguro
                                       destruir uma sessão?



(íle 3ver
"1a
"
             II./lAl'dal'
              fJ"
  -n.e S,•.s ca"'" PIU:".f.e
" li";,, ba.f.e" ,.)
                            eSfp'ylJ
      si/a ."a~i/I"'a p4ra vjatl41'
                              "         +
                                       Quais seriam as estratégias que você (e o Container)
                                       usariam para gerenciar o número de sessões e eliminar
                                       as desnecessárias? Quais são algumas das maneiras
                                       possíveis que o Container poderia saber que uma sessão
                                       não é mais necessária?

                                       Pense um pouco e dê uma olhada na API HttpSession
                                       algumas páginas adiante para conseguir algumas dicas.




                                       "Algumas aplicações distribuídas usam o leasing como forma do
                                       servidor saber que a cliente se foi. A cliente recebe um lease do
                                       servidor e deve renová-Io em intervalos específicos, informando ao
                                       servidor que ela ainda está lá. Se o lease da cliente expirar, o servidor
                                       sabe que pode destruir qualquer    recurso que mantinha    para a cliente .

                                                                                 você está             ."    241
sessões abandonadas




CotttO queretttos que ele futtciotte ...
Gostaríamos que o Container reconhecesse quando uma
sessão ficasse inativa por muito tempo e a destruísse.
É claro que teríamos que brigar com o Container para
que ele soubesse o que "muito tempo" realmente quer
dizer. Vinte minutos é muito tempo? Uma hora? Um
dia? (Talvez exista uma maneira de informarmos ao
Container o que é "muito tempo".)


o   Diane seleciona "Escura"
    e c1ica no botão submit.
                                     o Container    envia a
                                     solicitação para uma nova
                                                                           o  Container cria uma nova
                                                                           sessão, ID nº 343. O cookie
                                     thread do servlet BeerApp.            "JSESSIONID"      é enviado de
                                                                           volta para Diane na resposta
                                                                           (não exibido).




                                Web Container




8     Diane desaparece
      misteriosamente.
                              O Container faz o que qualquer Container
                              faria em seu tempo vago (embora
                                                                                A sessão iniciada por
                                                                                Diane ainda está lá...
                              provavelmente haja um monte de clientes           esperando ... abandonada.
                              a serem atendidos).




                               Web Container




e     Diane não retorna.
      Os minutos passam ...
                                O Container     checa o estado da sessão
                                nº 343 e descobre que nenhuma
                                solicitação chegou com aquela session
                                                                            O Container
                                                                            é muito
                                                                                          diz "20 minutos
                                                                                      tempo. Ela não
                                                                            voltou.", e destrói a pobre e
                                ID durante 20 minutos.                      abandonada sessão.




                               Web Container




242    capítulo6
gerenciamento        da sessão



A itrterface flttpSessiot1
                                                                 .       <<interface>>
Tudo com o que você se preocupa quando chama o                  Javux.servlethttp Ri
getSessionO é que você receba uma instância de uma          Ob.                      . ttpSession
classe que implemente a interface HtlpSession. É           lo;:ect getAttribute(String)
                                                               g getCreationTi
tarefa do Container criar a implementação.
                                                           String getIdO        llneO
Uma vez que você consegue uma sessão, o que você          long getLastAcc             .
podejazer com ela?                                        int getMaxIna .essedTllneO
Na maioria das vezes, você usará as sessões para         ServletC         ctzveIntervalO
                                                             .     ontext getSer 1<
receber e configurar os atributos do escopo sessão.      vozd invalidateO          v etContexto
Mas tem mais, é claro. Veja se você consegue            bO~leanisNewo
descobrir sozinho alguns dos métodos mais               Vozdr.
                                                               enzoveAttrib           "
importantes. (As respostas estão na próxima página,     void setAttr"b       ute(Strzng)
                                                           "        z ute(Strin O"
então não vire!)                                       void setMaxIn " g, bJect)
                                                      /; alguns Outro  actz~eInterval(int)
                                                                      os Inetodos




         Âpºnte seU lápIS
                                  o que   ele faz         Para que você o usaria



 getCreation TimeO




 getLastAccessedTimeO




 setMaxlnactivelntervalO




 getMaxlnactivelntervalO




 invalidateO




                                                                        você está           ••. 243
métodos HttpSessíon



       Os prit'lcipais tttétodos HttpSessiot'l
       Você já conhece os métodos para atributos (getAttributeO,
       setAttributeO, removeAttribute()), mas aqui estão alguns dos mais
       importantes de que você pode precisar na sua aplicação (e que
       podem cair na prova).

                                            o que   ele faz                  Para que você o usaria
                                      recebeu uma
                                 tempo.passado,osque permitir acertasremovidos
                                      permitido quernesta
                                      que você primeira
                                 existedecidirpelaentre asqueSOUBER e-mail
                                      criada
                                 ultrapassemcomreduzirperíodopodeserimporta.o A a
                                 háclientePoraderestringirdaqueforamclienteperder
                                 perguntando umaquandovocêclientesejareciclada
                                 sessãodecidirexemplo,vocêosessão depois de uma
                                 pela Retomavez pode quantosessão.julgar "Uma
                                 dasobjeto Você determinadopara dizer:
                                 Para última clienteatributossessão. VocêID feito
                                 do invalidate eduração sessão.cliente Esta éantes
                                         mais que, você
                                 para armazenadosele emcompra oouOude saído
                                 podesuapodeumo sem vaiaenviarádeum se encerrada,
                                 tempodescobrirsecertoumasicasotempo sessõesa
                                 tenhaContainer,oumas invalidada.períodoIoga).
                                 nenhuma sessão sessão.exemplo, tempo que
                                 validade. tempo,seja isso inativa tenha usá-Io
                                 instância sessão. sessão, umainda tenha
                                 que matar sessãoinativo podenos uma
                                 o muito finalizamomento cliente possui, quanto
                                 Descobrir
                                 peloformassolicitação queoquantidade podesessões
                                 estejafazer da na esta nestanãoVocêsemque não
                                 invalidateO permanecerretomar.
                                 O determinar por usá-Io sessionacessou
                                         um significa
                                         terminou uma
                                 depois inativoum (por
                                         que         se
                                                      caso               usar
a do
os,
te     vez logado, seu servidor.
       para completar este formulário ..." IO minutos
       paradas no você tem exatamente
o




                                                                     SUA

                                     Agora que você já conhece estes métodos, você consegue definir
                                     uma estratégia que elimine as sessões abandonadas?


       244 capítulo 6
gerencíamento              da sessão



                                         Cot1figurat1do             O   titMeout da sessão
    Você não pode estar falando
                                         Boas notícias: não é você que vai acompanhar isto. Está vendo
    sério ... então quer dizer que
     eu tenho que acompanhar a
                                         aqueles métodos acima? Você não tem que usá-Ios para se livrar das
    atividade da sessão e que eu         sessões mortas (inativas). O Container pode fazer isto para você.
    tenho que matar as sessões
  inativas? O Container não pode
               fazer isso?
                                         Três formas de matar uma sessão:
                                         ~ Por timeout
                  D
                  o                      ~ Você chama o invalidateO no objeto sessão
                                         ~ A aplicação cai (trava ou não é distribuída)



                                     o   Configurando              o timeout da sessão no DO
                                         Configurar o timeout no DD tem quase o mesmo efeito que
                                         chamar o setMaxInactiveIntervalO em cada sessão que é criada.

                                                                  () 7'> es+:      elJ 1J/~(,rfIJs.1.le ;:/lj 3l1E'se
                                         <web-app           ...> (J cllE'l1+e l1'liIJ   fljer       l1el1t.lIlJ4 s(Jlict+4S'li1J
                                           <servlet>                    I           N      "Tr.          1         I_;t
                                                                  l1es'T'/J.S(!!S SiM eJt I';> Jtll1l1"T'IJ$j1J4rt'-4.
                                            </servlet>
                                          <session-config>       -l,
                                             <session-timeout>lS</session-timeout>
                                           </session-config>
                                         </web-app>



                                     e   Configurando              o timeout para uma sessão específica
                                         Se você quiser alterar o valor do session-timeout para uma
                                         instância de sessão específica (sem afetar a duração do timeout
                                         em nenhuma sessão da aplicação):



                                         session.setMaxlnactivelnterval(20*60);


                                                "
                                               :5:     #.   st'ssã(J 114
                                                                                 () ar/t/ll>lel1+tJ
                                                                                                      "
                                                lia!        11
                                                             iJcê ct.aJtQ       u-fa     (:'11>I



             Os timeouts no DD
             estão em MINUTOS!
                                                     !.     I.
                                                 Jt'e'T(J;:/ (J e I             "tjer     ~lIe se       tJ

                                                  e-fa;:/a.                      l1el1l.t/lI>I#.

                                                                                 II>IIi1l1+6S;
Eis aqui uma enorme incon!istênci~
que devemos prestar atençao ... voce
especifica timeouts no DD usando
MINUTOS, mas se você configura: um
timeout programático, você especifica
 em SEGUNDOS!




                                                                                                     você está aqui ~           245
exercício do intervalo da sessão


              ~
 ;; ~;;   q   Imã de GeladeIra          Especifiqu~ no DD e
   ~                                    programatlcamente, que uma
          . sessão deve ser destruí da, se ela não receber nenhuma
            solicitação por 20 minutos. Nós colocamos o primeiro ímã no
            servlet para você e é possível que você nem use todos.

                         o O




                                             ;nactive-interva1>
                                        <max-~
                                                                 </session-con




-Servlet-----------------------------
public    void    doGet(HttpServletRequest    request,        HttpServletResponse    response)
                                                                                throws IOException




I HttpSession     I




                                                       getServletContext()
                                                                                 ao
                                                                                 .getSession();



                                                 setMaxlnact'
                                                   .         lvelnterval(




                                        [setTimeout(
                                         _                ]                          i   12000    D~
                                                                                                   L-:.=J

                                             I request   .     []                 ,etSmionTimeout
                                                                     I-se-S-S-i-o-n-II                (   !




246 e8pJ'fulo 6
gerencíamento    da sessão




SEJA 9 C91lta1ne,t

            Cada um d9S c9dlg9s abaI)(9
            t91 te,tltad9 de, um BttpSe,ty'le,t
                    c9mpI1ad9. Se,u ttaba.1h9 ~
                     pe,nsat C9m9 9 C9ntaIne,t
                    e, de,te,tmlnat 9 'lpe, y'aI
                  aC9nte,Ce,t'Luand9 cada
            um de,ste,s se,ty'le,ts t9t chamad9
            duas y'e,ze-spe,19 me,sm9 clle,nte,.
            De,scte,y'a 9 'Lue,aC9nte,Ce,na
            pdme,lta e, na se,gunda y'e,z 'Lue,9
            me,sm9 clIe,nte, ace,ssa 9 se,ty'le,t.


  ~PUbliC    void   doGet(HttpServletRequest   request,   HttpServletResponse     response)
                                                                         throws   IOException
            response.setContentType(~text/htrnl");
            PrintWriter   out = response.getWriter();
            HttpSession   session ~ request.getSession();
            session.setAttribute(~foo",     ~42");
            session.setAttribute(~bar",     ~420");
            session.invalidate()   ;
            String foo = (String) session.getAttribute(~foo");
            out~println(~Foo:    ~ + foo);




  ~PUbliC    void   doGet(HttpServletRequest   request,   HttpServletResponse     response)
                                                                         throws   IOException
             response.setContentType(~text/htrnl");
             PrintWriter   out ~ response.getWriter();
             HttpSession   session ~ request.getSession();
             session.setAttribute(~foo",     ~42");
             session.setMaxlnactivelnterval(O);
             String foo = (String) session.getAttribute(~foo");
             if (session.isNew())     {
                out.println(~This    is a new session.");
               else {
                  out.println(~Welcorne   back!");



             out.println(~Foo:   ~ + foo);




                                                                        você está        •.     247
respostas dos exercícíos


                ~                                      Especifique no DD e programaticamente, que uma
                Imã de G-elítdeltít                    sessão deve ser destruída, se ela não receber nenhuma
                                                       solicitação por 20 minutos.
                lesp9staB




   I <web-app   ...> I
                                                     Leliflbre-sf?.J ., +i"lifle"v-f-~.,   blJ ~

        I <session-con        g> I             ~especi'flcI4IÁ"        f!1ifl   Il.{ItJfJro's.

                I
                <session-timeout>             I~       </session-timeout>


        I <I session-con       g>    I

   I </web-app> I




~Servlet---·--- -------------------------
   public    void   doGet(HttpServletRequest              request,       HttpServletResponse       response)
                                                                                        throws     IOException




            [ HttpSession       11   session    I   [J   request. getSession            ();



            lsession.     I   setMaxlnactivelnterval(             [1200     I~
                    LeJM.f,re-se;        .,
                    e.sped/lctJ.lÁlIJ elifl




248 CBtJ,'tulo 6
gerenciamento              da sessão




     SBJA 9 C9l1tél1net
     Iesp9st:ls




o   public   void    doGet(HttpServletRequest

        response.setContentType(~text/html");
                                                     request,   HttpServletResponse
                                                                             throws
                                                                                                 response)
                                                                                               IOException

        PrintWriter   out = response.getWriter();
        HttpSession   session ~ request.getSession();
        session. setAttribute       ("foa", "42") i
        session.setAttribute(~bar",           ~420");
        session.invalidate()   ;

        String       foo =
                                       <'
                             (String)sesslon.ge~~~ribute(~foo");

        out.println(~Foo:         ~ + foo);
                                                                         ~
        Resultado: ocorrerá uma exceção de                  ><r! M.Vt.f.4 -I-I!./'de pa/'I!. ct.l!.tfP,a/'ó
        runtime (lllegaIStateException), porque
        você não pode ter um atributo DEPOIS                5e+A'ff/'lbvhÜ               114Sf!S Sã6PÓ/'1JVf!
        que uma sessão já tenha sido invalidada.            f!14j: FoI



    public    void    doGet(HttpServletRequest       request,   HttpServletResponse               response)
                                                                             throws             IOException
        response.setContentType(~text/html");
        PrintWriter   out = response.getWriter();

        HttpSession   session ~ request.getSession();              A-3Vl es-h.*t6S         161"5411d6 v*t
        session.setAttribute(~foo",     ~42");
        session.setMaxlnactivelnterval(O);
                                                                   -A""eóv-I-    IJ-d.pIl}ro        dI/.

                                                        ~       .•••seSSã6Jf>61$ eS+4*t.:)s dl;f!l1da:
                                                                   -A""e(w-l- depill'$ de ()
                                                                   de 1;'tJ.-A··.lldl/.de.
        if     (session.isNew(»)     {
              out.println(~This      i~
             else {
               out. println (~Welcome     back!");                                              p"de      Ct.QtfP,fU'
                                                                                                                    ó
        }                                                                         Ai.                                ""
        out. println (~Foo: ~ + session. getAttribute            (~foo") ) ; ts      ew();tfP,      VtfP,aSf:SSQó
                                                                                        3Vfjt~f"l iÍ'IVo.lldt!.dl!..
                                                                           /1;r+"11.f.4;      esh:"          tfP,estfP,,,
        Resultado: ocorrerá uma exceção de                                                         I"



        runtime (lllegaIStateException), porque                              pr"b1e.tfP,fJ. a cadljtl
                                                                                          d                  fJ.C/~fJ.
                                                                                                                    •••
        você não pode chamar o isNewO na sessão                                 ••• '" póde ct.atfP,fJ.rf!s-n:;
                                                                           V.:)cf 114IJ                      1_-
        DEPOIS que ela tenha sido invalidada.                                    tfP,:+t>dó f,l)j V,l)j4 sfssã.,
        Configurar o intervalo máximo de
                                                                                                        1i?lIalldadfJ..
        inatividade em O significa que a sessão vai
        expirar e ser invalidada imediatamente!


                                                                                  você está aqui..                 249
custon cookies



Posso usar cookies para outras coisas, ou

eles são apeKas para sessões?
Ainda que os cookies tenham sido originalmente
desenvolvidos para ajudar no suporte do estado da
sessão, você pode usar cookies customizados para
outras tarefas. Lembre-se, um cookie nada mais é
do que um pequeno pedaço de dados (um par String
nome/valor) trocado entre o cliente e o servidor. O
servidor envia o cookie para o cliente e este retoma
                                                          yT9cê p9de usétt 95 c99kles péttét
o cookie quando fizer uma nova solicitação.              tt9Cétt 9S pq.tes de Stt'lnb n9me!
Uma coisa legal dos cookies é que o usuário não
se envolve - esta troca é automática (supondo que        Yét19tentte 9 setYld9t e 9 cl1ente.
o cliente tenha habilitado cookies, naturalmente).
                                                          O sety'id9t enYIa 9 c99kIe ét9
Por padrão, um cookie vive somente enquanto
dura uma sessão; uma vez que o cliente fecha
o browser, o cookie desaparece. É assim que
                                                          clIente, Cjye 9 enVIa de Y9ltétem
o cookie "JSESSIONID" funciona. Mas você
                                                          cétda S911c1taçã9 subse<tiiente.
pode mandar um cookie permanecer mesmo
DEPOIS que o browser éfechado.                            Os c99kles da sessà.9 S9mem
 Dessa forma, a sua aplicação ainda pode obter a
 informação do cookie, mesmo que a sessão com             <tuand9 9 6t9Wset d9 clIente é
 o cliente já tenha sido finalizada há muito tempo.       encettad9, mas V9ce rODE dIzet
 Imagine que o Kim queira mostrar o nome do
 usuário cada vez que ele retome ao site da cerveja.                                                                  n9
 Então, ele configura o cookie na primeira vez que
 recebe o nome do cliente, e se obtiver o cookie de       clIente                            dep915 ~.:ueele
 volta com uma solicitação, ele sabe que não tem
 que pedir o nome de novo. E não importa se o
                                                          tecLat seu
 cliente simplesmente reiniciou o browser ou esteve
fora por uma semana!

                                                        ~~~.~lect~selectBeerTaste2.do               HTTPll 1
                                                             .   w.W1Ckedlysmart.com                       .
                                                        User-Agent: Mozi11a/5.0
                                                       Cookie: username==TomasH' h
                                                    Accept· textl 1         .       Irsc
HTTP/l.l 200 OK
Set-Cookie: usernaroe-
                      _ToroasHirsch                 ht 1· ~      Xli ,apphcation/xml a              r .
                                                   ]P'm ,q-O.9,textlplaiu·q==o 8,VI'd eo/x mn .
                                                    .            .        ,.            ,pp IcatlOn/xhtml+xml ,textl
 Content-Type: text!htm1                                 eg,Image/glf;q==O.2,   *1*;q==O.1      -      g,lmage/png,imagel
            L gth. 397                                 Accept-Langu
                                                                age: en-us,en;q==O.5
 Content- en      .  200303:25:40       GMT
 Date: Wed, 19 Nov                                 Accept-Eucoding: gzip,deflate
 Server.t' Anache-Coyote/l.1
        .
  Connection: close

  <htrol>
                                                                        r
                                                             () c/tf!,,-h e"ll/tl    15.f-.,   de   V.,/.f-o..
   <lhtrol>


                              
     () Si!I'ViflM' i!"Vltl i5.f-., ,l'lmeil'''.


250 capítulo 6
gerencíamento            da sessão



Usando cooldes         COtH    a API Servlet
Você pode obter headers relacionados ao cook:ie através da
solicitação e da resposta HTTP, mas você não deve. Tudo
o que você precisa fazer com os cook:ies foi encapsulado
naAPI Servlet em três classes: HttpServletRequest,
HttpServletResponse e Cook:ie.



                                                                                              javax.servlet. http. Cookie
             <<inteJjaee> >                                                            Cookie(String, String)
                http HttpServletRequest
 javax.servlet.     .                                                                       ~tring getDomainO
                                                                                            znt getMaxAgeO
 getcontextPathO                                   < <interfaee> >
                                                                                            String getNameO
 getCookiesO                         javax.servlet. http.HttpServletResponse
   etHeader(String)                                                                        String getPathO
  g QueryString()            addCookieO                                                    boolean getSecureO
  get                        addHeaderO                                                    String getValueO
  getSession(),                    J   d'
      VIraS mais metodos ... eneoueRe zreetURLO                                          vo~dsetDomain(String)
  Ii M                       sendErrorO                                                 vozd 'se!" Á Age(znt)
                                                                                                           .
                                                                                           •     olV1GX
                             setStatusO
                                                                                        vO~d setPath(String)
                             Ii MUITOS mais métodos ...
                                                                                        vOldsetValue(String)
                                                                                       Ii alguns outros métodos



Criando um novo cookie
                                                                           o CIJPls+rf.l"1-6r        ClJoUe leva lIlrl
   Cookie     cookie   = new Cookie(~usernameH,             name);~        .sI .              I ,
                                                                             .,..r1Pl5P1itJlrle{VafitJr.
Configurando      o tempo que um cookie permanecerá                        no cliente
   cookie. setMaxAge (30*60);
                                         ,
                                             .                             O se+A4.axA'fif!:
                                                                                          <J
                                                                                                       Jetl'P1it/itJ elrl
                                                                                                       I
                                                                           ~f.btJlJJ)O.s.        {) caJi5tJ Ji;:

Enviando o cookie ao cliente                                                 perlrlaPleg4        Vt"lItJ PltJcliePlh
                                                                                       'l1:                        11
   response.addCookie(cookie);
                                                                          f'i'U'   30'1f'O        s'!!5l1P1Jas
                                                                           IrlI'P1l1+as). CaPlt~lIral"            a IrlQX
Recebendo       o{s) cookie{s) da solicitação               do cliente f'4Nl.      -1ta;        CIJIrl 6 3l1e     6 Co66kte
   Cookie [] cookies         = request. getCookies ();                     Jesapl1.reja         Ôll4P1JIJitJ
    for Cookiei = O; i = cookies.length;
        (int    cookie < cookies[i];                    i++)    {          tec~ar.~r+I1.PI+o6JSe

         if   (cookie. getName ().equals (~usernameH) )                    ;;'fJ.1rl4r tJ 5e-1-1A.axIf9e()          PlIJc6IfJkte
               String userName = cookie.getValue();                            Ll.5f..5.s~olJ~J)
                                                                                       I
                                                                                                             tJ

               out.println(~Hello   ~ + userName);
               break;                                                      r,!!Cder4       Je




                  !J';IJ ~: " 1Itt:+"JIJ 5e-H:.IJt:J/:.te(S+rtPl5)'"    ve.cê s:' pe.Je tJ~hr

                  c"o/:.tes elltt lIlItt arr,    CIJIJ/:.tee vócê hr:   1l1e ta;er     lIlItt IlJtJp
                  PIe.arr,      p4ra    ePlC6P1+r4r alpe1e 3l1e voee SlIer.

                                                                                                 você está aqui..             251
exemplo cookie



Exettplo sittples de utt eoolde eustottizado
Imagine que o Kim deseje criar um formulário que peça ao usuário
para enviar o seu nome. O formulário chama um servlet que recebe
o parâmetro usemame da solicitação e usa este valor para criar um
cookie na resposta.
Na próxima vez que o usuário fizer uma solicitação em
QUALQUER servlet nesta aplicação, o cookie retoma com a
solicitação (supondo que o cookie ainda esteja vivo, baseando-se
no valor maxAge dele). Quando um servlet na aplicação vê este
cookie, ele pode colocar o nome do usuário em uma resposta
gerada dinamicamente, e a lógica do negócio sabe que não tem que
pedir ao usuário que digite o seu nome novamente.

 Este cbe~go~ uma versão fie ese     slmpln~~~~
                                                 ~~i'?~"d')~
 acabamos de descrever.


 o servlet       que cria e CONFIGURA o cookie
     import   javax.servlet.*;
     import   javax.servlet.http.*;
     import   java.io.*;

     public   class    CookieTest     extends      HttpServlet        {

        public    void   doPost(HttpServletRequest               request, HttpServletResponse    response)
                                                                    throws IOException,   ServletException


              response. setContentType          ("text/html") ;                                 itecebe     (} /7t}/MetJlJ vsv:l'l{j

              String   name   = request. getParameter            ("username") ;        V        f!J1Vlo.tJ"J16161'W1vl:l'ia.

              Cookie   cookie    = new Cookie ("username",                name); <--Cl'tfll.       VNoJ16V6 c<tJfjl:le~lIe       F

                                                                                           o.I'WIlJ.jf!/7IJ. /7iJWletJ" lISVfl.l'i'eJ.
                                                                                                           <>

              cookie.setMaxAge(30*60);                       I
                                           '"      Malfrff.No"     (;41JMe 11lVfJJ1(j
                                                                    30   W11;'V+4S.
                                                                                A-tJlci'6/7fl. .o C()lJl:te Ct'JWlIJ     t.eatJel' tJe
              response. addCookie      (cookie) ;    <f:--_____                             J
                                                                                l'esft'Js-ra,   /I .se.,...-l.-M/tae.
                                                                                                        J J'I      •

              RequestDispatcher        view     = request.getRequestDispatcher("cookieresult.jSP");

              view. forward (request,           response);                                                 ~
                              Pel'W1,--h: 3l1e lIWI J.sP crie IJ. I               tJe l'eSft:lS.f-lJ. •   .-I

   o JSP que cria a view               a partir deste servlet                                        ,
           1 b d
      <htm >< o y>
       <a href=" checkcookie        .do">click
                                                              1útJt:IbeWl. c!al'lJ,
                                                                        J._'"      I '"
                                                    here</ a> Cli.l'aCTf:l'ls-ri'ctJ.S tJe
                                                                                                   J
                                                                                             t.a J1atJlJ.
                                                                                                1-P /71's
                                                                                                          Ct)No
                                                                                                          SÓ).W1tJ.S
                                                                                                                          I
                                                                                                                       I'MS
      </body></html>                                          t:ltJi'Q.If'lt:lS
                                                                             5U'4f' VIf'IIJ. lJ.ltJae'lf'IlJrML.
                                                                                            S                           tJe lIlf'I
                                                              Sff'V1dj         IJ.t;,tJa~ve S~lJ. J)í.s-rí    .f-ailJ'lf3.J1i.".()
                                                              h-ft:l tJe es-fQI'W1tJS eJ1Calf'll;,t.4J1tJ<ii     paf'a lIlf'I

                                                                  J.sP J1';' If'IlIJ, IJ.ctJ;,/~tJf'tJJifJ ;/.0 c(J(J/::ie.()
                                                                  ClJlJ/::'-ejfl es-fo. ;,Q. f'(SPlJs.f1J. 116iIJ'It)/I!;el1-fIJlf'l
                                                                                                                               e
                                                                  3tJe    4   SlJli'cl-flJ.j';C : eI1ClJ.iIJ'It;,t.a;/a J.sP. ••
                                                                                                                      41J


   252 capítulo 6
gerenciamento                  da sessão



 ExetMplo de UtM coolde custotMizado,                                cottlit1uação ...
 o servlet          que RECEBE o cookie
       import       javax.servlet          *.
       ~mport       javax.servlet:h~tP.*;
       lmport       ]ava.io.*;

       public       class   CheckCookie            extends        HttpServlet     (

          public       void     doGet(HttpServletRequest                  request, HttpServletResponse    response)
                                                                           throws IOException,   ServletException


                response.setContentType(~text/html")     .
                PrlntWrlter   out = response.getWriter();'

                Cookie [] cookies               ~ request. getCookies           (); ~ecebe       6S uM/t:.tes       da Sf:Jliêt-l-at/ti6.
                if    ( cookies !~ null) {
                      for (int i ~ O' . <          .
                               . _     ,l    cookles.length;     i++)
                         Cookle cookie = cookies[i];
                         lf (cookie getNa
                                 .    .     me
                                               ()
                                                  .equals{~username"))                       I
                             Strlng userN
                                    .
                                                _       .
                                           ame - cookle. getVal ue () .
                             out.prlntln(~Hello      ~ + userName)'     '~
                                                                                         i .___               J       '
                                                                                                           t.!-rl'illltS dli
                                                                                                               •
                             break;                                 ,da                               ca4/l:le I'l'ilJCill'tlPlJtJ
                                                                                                       illJ'i ClJtJkl'e cl..fJ,IJ'ifJ.JiIJ
                                                                                                                      If'
                                                                                                    IISI!I'Pl41J'ie         •   Se   ele

                                                                                                  I!PlClíPl-l-I'RdtJ)IJb-l-ePlt.a a
                                                                                                  val61' e extb4-t}.



                                                                                Não confunda Cookies
                                                                                com headers!

                                                                  Quando você adiciona um header em uma resposta, você
                                                                  passa as Strings nome e valor como argumentos:

                                                                  response.addHeader(~foo",       ~bar");
                o



 .

 ·
 :
  ..
       ;t
 .=~lQ'o
 · "
 I
                       ......
                                '"
           saber i;DCê não precisa
           do cookie.
                              os
                        os me't ..•
                               Ouos
                                     "0

                                       I
                                    •. •
                                       :
                                          00 00 00 000.




                                                              .
                                                                  Mas quando você adiciona um Cookie em uma resposta,
                                                                  você passa um objeto Cookie. Você configura o nome do
                                                                  Cookie e o valor no construtor Cookie.

                                                                   Cookie cookie = new Cookie(~name",                 name);
                                                                   response.addCookie(cookie);
 •p                                                           •
  • ara a prova ,nao
  :                 voce' - te .               :
                                               •
  • memorizar cad                  ra que      •                   E lembre-se também de que existem o método setHeader()
  • I
  :                  a um dos me'to d os na •  :
  • c asse cooki e, masdev       '             •                   e o addHeader() (o addHeader adiciona um novo
 : os métodos de sol"
 •                     lCltaç era conhecer •
                               -              :                    valor a um header existente, caso exista, e o setHeader
 : para obter e adi .         ao e resposta:                       troca o valor existente). Porém, NÃO existe um método
 : 10cê tamb'     d czonar Cookies.           :                    setCookie(). Existe apenas o addCookie()!
:             em eve conh                    :
• construtor C.
•                ookie e'      ecer o        •
                                             •
: getMaxAgeO           ., IOS metodos        :
:..........       e set1V1axAgeO.
            .....•••••...                    :
                                   .•••...........
                                                          .
                                                          :

                                                                                                       você está
momentos do ciclo da vida da sessão



Os prittcipais 'ltO'ltetrtos de U'lt HttpSessiott
Os momentos mais importantes na vida de um objeto
HttpSession:


A sessão    é criada     ou destruída.



                   new
                                                                              invalidate




Os atributos da sessão são adicionados, removidos ou substituídos por outras
partes da aplicação.


                                                           removeAttributeO




A sessão torna-se passiva em uma VM e                  é ativada     em outra dentro de uma
aplicação distribuída.




            VMl
              prepare-se
                                                                                     Agora
              para mudar
                                                                                    eu tenho
                                                                                      você.
                                         A-    sessã"
                                                                                               Container A-2
                                                  de
                                         IOIÍj /'tI.    1/1010.
 Container A-l
                                         V,(,{ptU'4
                                         "tr!-f'o..



254   capítuío 6
gerenciamento      da sessão



Eventos do ciclo de vida da sessão


Momento                                                          Tipo de Evento e Listener
Ciclo de vida
   A sessão foi criada                                                 HtipSessionEvent
   Quando o Container cria uma sessão pela primeira vez.
   Neste momento, a sessão ainda é considerada nova (em
   outras palavras, o cliente ainda não enviou uma solicitação
   com uma session ID).

   A sessão foi destruída

   Quando o Container invalida uma sessão (porque houve um
   timeout da sessão, ou alguma parte da aplicação chamou o
                                                                              ~ Y
                                                                                 ,
                                                                              ~, ...•..



   seu método invalidate()).

Atributos
   Um atributo foi adicionado
                                                                   HttpSessionBindingEvent
   Quando alguma parte da aplicação chama o setAttributeO
   na sessão.

   Um atributo foi removido




                                                                                 ,
   Quando alguma parte da aplicação chama o
   removeAttributeO na sessão.
                                                                              ~ ...
                                                                              ~.'.:
                                                                                 V
   Um atributo foi substituído                                    HttpSessionAttributeListener
   Quando alguma parte da aplicação chama o setAttributeO
   na sessão e o nome do atributo já esteja associado a ela.

 Migração
   A sessão está a ponto de se tornar passiva

   Quando o Container está prestes a migrar (mudar) a sessão           HtipSessionEvent
   para uma VM diferente. E chamado antes de a sessão ser
   movida, de forma que os atributos tenham a chance de se
   preparar para a migração.




                                                                                  ,
   A sessão foi ativada

   Quando o Container acaba de migrar (mudar) a sessão para
   uma VM diferente. É chamado antes que qualquer outra
                                                                  HttpSessionAttributeListener
   parte da aplicação possa chamar o getAttributeO na sessão,
   para que os atributos recém-movidos possam se preparar
   para o acesso.




                                                                          você está         ~    255
HttpSessionBíndingListener



Não se esque~ado HttpSessiot'Jit'dit'gListet'er
Os eventos da página anterior são para os
momentos principais na vida da sessão. Mas o
HttpSessionBindingListener   é para os momentos mais
importantes na vida de um atributo sessão. Lembre-se do
capítulo 5, onde nós vimos como você pode usá-Io ~ se, por
exemplo, o seu atributo quer saber quando ele é adicionado
a uma sessão, para que ele possa sincronizar-se com o
banco de dados em questão (e atualizar o banco de dados
quando for removido de uma sessão). Veja abaixo uma
pequena revisão do capítulo anterior:
                                                                                                                o
                                                                                                                O
                                                                   I'          I1CIJ+e    illVI!X,
                                                    liS-n;i'ler l?s-rlí.nf>P
                                                        1_                               '"
   package     com.example;                            II.K p.
                                               serv1e-r,
   import     javax.servlet.httP.*;~

   public class Dog implements         HttpSessionBindingListener
      private String breed;

       public Dog(String breed)
         this.breed=breed;



       public String getBreed()
         return breed;
                                                                                                        U'fl        U
                                                                                          /} fo,lavt'4 !7,#Ji'lt     Si5l'1l';:tCfl
                                                                                          alie 4'Jllé,.. kbICItJA]()1I
       public void     valueBound (HttpSessionBindingEvent event)                        {es+e 4-1-"l/;u-I-c. e,.. U"'<'l sess«lJ.
         Ii  código    a ser executado agora que eu sei que estou                         numa       sessão



       public void valueUnbound(HttpSessionBindingEvent  event) {
         Ii  código a ser executado agora que eu sei que não faço mais                                  parte       da sessão




                           V-NÃO      configura todos os
                             oce              . d" g no DO'
                           listeners session bm m         .
                       o            o a classe Dog aqui) implementa
    Se uma classe a!rz~uto (com . o Container chama os callbacks
    o HttpSessionBmdmgLrste;el,        dO e valueUnboundO) quando
    que tratam eventos (value o,undo nada ou removida de uma
                                        o



    uma instância dessa classe e a IClO
     sessão. É isso. E funciona.             .       d
           .     - vale ara os outros lzsteners e
     Mas Isto NAO         p    o    O HttpSessionListenere   o
     sessão da págin~ ante~lOr. devem ser registrados no DD,
      HttpSessionAttrlbuteLrstener,             -es em si diferentemente
                 I     - relacionados as sesso            '
      visto que ~ es s~od'IVI u aI localizado na sessão.
      de um atributo m      "d




256 capítuio 6
gerenCÍamento da sessão



A tltigração da sessão
Lembra no capítulo anterior que nós falamos brevemente sobre aplicações
distribuídas, onde os pedaços da aplicação poderiam ser replicados por
vários de nós na rede? Em um ambiente de clusters, o Container pode
fazer um balanceamento de carga, recebendo as solicitações dos clientes
e enviando-as para as NMs (que podem estar, ou não, em máquinas
diferentes, mas isso não é relevante para nós). O fato é que a aplicação
está em diversos lugares.
Isso significa que cada vez que o mesmo cliente faz uma solicitação, esta
pode acabar indo para uma instância diferente do mesmo servlet. Ou seja,
a solicitação A para o Servlet A pode acontecer numa VM, e a solicitação
B para o Servlet A pode ir parar numa outra VM. Então a questão é, o que
acontece com os componentes como o ServletContext, ServletConfig e
objetos HtlpSession?
Resposta simples, implicações importantes:
Apenas os objetos HttpSession (e seus atributos) são movidos de uma
VM para outra.
Existe apenas um ServletContext por VM. Existe um único ServletConfig
por servlet, por VM.
Mas existe apenas um objeto HttpServlet para uma determinada session
ID por aplicação, independentemente de em quantas VMs a aplicação
esteja distribuída.



A aplicação Cerveja distribuída etlt duas VMs



       VM 1                                                                        ~"
 Aplicação Cerveja
                                                                                   PI';""'iJ .5e1",11~~
                                                                                   eo.m!JósóS
                                                                                   opliCQ{ióc~1f,,(/.1tt!             yltt!
                                                                 ,y;;.psesSO~ .5eI'VI~;d-,

                                                                                   1iid")/((cef-"" ~SSi<>i'l;
                                                                                   esh. dyplic(I.Jt; i'IfJ, tJ(r/-1'{I.    V~



        VM2                                                                 Alt:rh;     es-IJ -fvJi'J diA Ilcf1.dt;
                                                                                                                  I'lt;
  Aplicação Cerveja
                                                                            Sejtl'1dó                                Z:l   óS
                                                                            IJÚ'     'Cs
                                                                               y sess:ks         e((I~1tt! ebl
                                                                            Dpei'IfJ.SM.1Y5QI' ebl a!;tlbl d(I.Ji'J
                                                                                     1/
                                                                            ~n+D. I} ~SJtt!fJ.sesslóJ'l I!J
                                                                            parQ GlJtt!fJ. dml'l>V~a dGlf1.S
                                                                            AlI/AlCI} ~ce           ebl opliC"ffi"
                                                                                                            ~
                                                                            tJ.ó~sJtt!fJ.h""f>6.




                                                                                    você está aqui...                       257
migração da sessão



A t1igração da sessão et1 ação
A forma como os fabricantes de servidores lidam com
c1ustering e distribuição de aplicações web varia. Não há
nada na especificação J2EE que obrigue um fornecedor a
dar suporte a aplicações distribuídas. Mas a figura abaixo
nos dá uma idéia interessante de como isso funciona.
O fundamental é que, enquanto que as outras partes da
aplicação são replicadas em cada nóNM, os objetos sessão
são movidos. E isto é garantido. Logo, se o fornecedor
realmente suporta aplicações distribuídas, o Container é
requerido para migrar as sessões através das VMs. E isso
inclui migrar os atributos da sessão também.

o   Diane seleciona "Clara" e
    c1icano botão submit.
                                                        o Container cria uma nova sessão, ID n2.343.
                                                        O cookie "JSESSIONID é devolvido para
                                                        Diane na resposta (não mostrado).
                        o servidor  de balanceamento
                        de carga decide enviar a
                        solicitação para o Container
                        A-i na VM Um.




                     Servidor/Container de
                     balanceamento de carga




e   Diane seleciona "Amarga" e
    c1icano botão submit. Sua
                                     Desta vez, o servidor
                                     de balanceamento de
                                                                      O Container recebe a
                                                                      solicitação, verifica a session
    solicitação também inclui o      carga decide enviar              ID e percebe que a sessão está
    "JSESSIONID" n2.343.             a solicitação para o             em uma outra VM, a VM Um!
                                     Container A-2 na VM
                                     Dois.




                                                                 o
                                                                  o



                          Servidor/Container de
                          balanceamento de carga             Container A-2




258 capítulo 6
gerenciamento   da sessão



e   A sessão n9.343 migra da VM Um para a VM
     Dois. Ou seja, ela não existe mais na VM Um,
    já que ela se mudou para a VM Dois.


    Esta migração significa que a sessão se tornou            VM 1
    passiva na VM Um e foi ativada na VM Dois.




                                                             Container   A-1




                          Servidor/Container        de
                          balanceamento    de carga            VM 2




                                                          Container A-1




                                                     O Container cria uma nova thread para o Servlet
                                                     A e associa a nova solicitação à sessão recém-
                                                     movida n9.343.


                                                     A nova solicitação de Diane é enviada para a
                                                     thread e todos saem felizes. Diane não tem idéia
                                                     do que aconteceu (exceto pelo breve atrasol
                                                     latência na espera da migração da sessão).




                      Servidor/Container       de
                      balanceamento    de carga




                                                                                  você está      lt-   259
HttpSessionActivationListener



o HttpSessiottAetivatioKListmer deixa os
atributos protrtos para a graKde tMUdaKça
                                        ...                           Este Iistener é tão parecido com um
                                                                       atributo, que eu consigo descobrir
Já que épossível migrar um HttpSession de uma VM para outra,
                                                                     quando eu estou para Ser movido para
os desenvolvedores da especificação pensaram que seria legal        uma nova VM como parte de uma sessão,
se alguém se preocupasse em dizer aos atributos dentro das          e posso ter certeza de que as variáveis
sessões que eles também estão prestes a mudar. Dessa forma, os         da minha instância estão prontas ...
atributos podem garantir que sobreviverão à mudança.
Se todos os seus atributos são objetos Serializáveis de
verdade, que não se importam onde eles serão colocados,                      o
você talvez nunca use este listener. Aliás, imaginamos que                    a
95,324% de todas as aplicações nunca usem este listener.
Mas ele está lá caso você precise. Seu uso mais provável é
dar aos atributos uma chance de preparar as variáveis da sua
instância para a Serialização.


A migração     da sessão e a Serialização
Agora fica meio confuso ...
Um Container é exigido para a migração dos
atributos Serializáveis (o qual assume que todas
as variáveis da instância dentro do atributo ou são
                                                                     <<interface> >
Serializáveis, ou são nulas).
Mas um Container não é exigido para usar a                   HttpSessionActivationListener
Serialização para migrar o objeto HttpSession!
O que isto significa para você? Simples:               sess~onDi~ctivate(HttpSesSionEventj
garanta que os tipos das suas classes de              seSSlOn WiJIPassivate(HttpSessionEventj
atributos sejam Serializáveis e você nunca
terá que se preocupar com isso. Mas se
eles não forem Serializáveis (em virtude
de uma das variáveis da instância do
objeto atributo não ser Serializável), faça
com que a classe do seu objeto atributo implemente o
HttpSessionActivationListener     e use os callbacks ativação!
passividade para contornar o problema.



                o Container não é REQUERIDO para usarmos a Serialização, por isso
                não há nenhuma garantia de que o readObject() e o writeObject()
                serão chamados no atributo Serializável ou em uma das variáveis da
                sua instância!

  Se você está familiarizado com a Serialização, você sabe que uma classe que implementa esse
  recurso também pode escolher implementar um método writeObjectO, chamado pela VM sempre
  que um objeto for serializado, e um método readObjectO, chamado quando ocorrer o inverso. Um
  objeto Serializável pode usar estes métodos para, por exemplo, configurar nulos os campos não-
  Serializáveis durante a Serialização (writeObjectO), e então restaurar os campos quando ocorrer o
  processo inverso (readObjectO). (Se você NÃO estáfamiliarizado com os detalhes da Serialização,
  não se preocupe.) Mas os métodos não serão, necessariamente, chamados durante a migração da
  sessão! Portanto, se você precisa salvar e restaurar o estado da variável da instância no seu atributo,
  use o HttpSessionActivationListener e use os dois eventos de callbacks (sessionDidActivateO e
  sessionWillPassivateO), assim como você usaria o readObjectO e o writeObjectO.


260 capítulo 6
gerencíamento                  da sessão



Exeiflplos de listcmer
Nas duas páginas a seguir, preste atenção nos tipos do objeto
evento e se o listener é também uma classe atributo.

o contador      da sessão

Este listener permite que você acompanhe a quantidade de sessões
ativas na aplicação. Muito simples.

   package com.example;
   import javax.servlet.http.*;

   public     class    BeerSessionCounter   implements     HttpSessionListener              {

       static    private    int activeSessions;                  ~s';"a classe se;,,: ;/i's';"rtbll{Ja          e",
                                                                 wí6-IIJFlclasses                C<l""<l   ';"<lJ4s as
                                                                 611';";"IJ.S
                                                                            classes       da   apftclJ.{i<l)'IJ.;"1J.
       public static int getActiveSessions()             { ~     óve ';"ó;/ós 6,s ,se;"lIfe';"s e 4S 611+;"4S
           return activeSessions;                                cllJ.sses /l.ssts-/-e,,-/-es P6SSIJ.'" acessa;"
                                                                 es-/-e "'~';"6J6.




        public voíd sessionCreated(HttpSessionEvent
             activeSessíons++;                                  event)      {~        
                                                                                      ,I
                                                                          fshs        ""'fff)JI)S          Cfl.l"l"e541r<   Vir<

                                                                          H++,Ses          slt:'l'Jíve"./-.
       publíc void sessionDestroyed(HttpSessionEvent             event)      {~
           actíveSessions--;




Configurando o Iistener no DD
   <web-app     ...>

       <listener>
         <listener-class>
            com.example.BeerSessionCounter
         </listener-class>
       </listener>
    </web-app>




                                                                                          você está aqui ~                  261
atributo de sessão listener



Exettplos de Iistet1er


o Listener Attribute                                                         ís+e 'ts+el'/el" usa V"" I'IlJ""f!
Este listener permite rastrear cada vez que algum atributo é                 I';;Ci:>I'!Sts+el'l+el<j>esal"/e ser
                                                                                                -         '         u""
acrescentado, removido ou substituído em uma sessão.



                                                                                   /
                                                                             'ts+eller IJrHt'lbil+e)   recebe iI""
                                                                             wewf-i:>8'-1'1'/'';;3_
   package com.example;
   import javax.servlet.http.*;

   public   class   BeerAttributeListener          implements     HttpSessiOnAttributeListener

        public    void   attributeAdded(HttpSessionBindingEvent                event}    (




              String name       event. getValue ()       j
              Obj ect value == event. getName (); "7.. O HHpSessianílle,,-I- Wf!"-!-".
                                                       ,JieSf!"ca,Jie"iIes+eva!,,/' per""r+e a lI<lcê
                                                                "11i:>""e"
                                                                         e           ,/<la-!-I'lbu+" óue

              System.out.println{"Attribute            added:    " + name    + ": " + value);



       public void attributeRemoved(HttpSessionBindingEvent                     event}       (
            String name = event.getName();
            Object value ~ event.getValue{);
            System.out.println("Attribute    removed: " + name                 + ". " + value);



       public void attributeReplaced(HttpSessionBindingEvent                      event}         (
            String name = event.getName();
            Object value ~ event.getValue();
            System.out.println("Attribute    replaced: " + name                 + ". " + value);




Configurando o listener no DD
   <web-app      ...>

       <listener>
         <listener-class>
            com.example.BeerAttributeListener
         </listener-class>
       </listener>
     </web-app>
                                                                r:   Ei, onde você está exibindo? Onde
                                                                entra o System.out na aplicação?


                                                                Jt: Para onde     quer que o Container decida
                                                                enviá-Io (que você pode ou não configurar).
                                                                Em outras palavras, um lugar determinado pelo
                                                                fabricante, geralmente um arquivo de log. O
                                                                Tomcat coloca a saída em tomcaUlogs/catalina.
                                                                log. Você terá que ler a documentação do seu
                                                                servidor para descobrir o que o seu Container
                                                                faz com a saída-padrão.



262 capítulo 6
ExetMplos de listmer
A classe atributo (escutando eventos que afetam o IT)
Este listener permite que um atributo acompanhe os eventos que
possam ser importantes para o próprio atributo - quando ele é
acrescentado ou removido de uma sessão e quando a sessão migra
de uma VM para outra.

   package com.example;
   import javax.servlet.http.*;
   import java.io.*;

   public       class   Dog implements   HttpSessionBindingListener,
                                         HttpSessionActivatiOnListener,Serializable
      private String breed;
      Ii  imagine outras variáveis da instância,               incluindo
      Ii algumas que não sejam Serializáveis

      Ii    imagine      o construtor    e outros   métodos   get e set

      public void valueBound(HttpSessionBindingEvent  event)
           Ii
            código a ser executado agora que sei que estou em uma



      public void valueUnbound(HttpSessionBindingEvent  event) {
           Ii
            código a ser executado agora que sei que não faço mais               parte   da
   sessão



      public       void sessionWillPassivate(HttpSessionEvent   event)
           Ii     código para obter meus campos não-Serializáveis    em um
           Ii     que possa sobreviver   à mudança para uma nova VM


      public void sessionDidActivate(HttpSessionEvent      event) {
         Ii código para restaurar meus campos ... para refazer tudo
   tenha feito
        Ii no      sessionWillPassivate()
                                                                             o qco oc OãO:--'~
                                                                               tLve"l.f.tJsde fl.f.lV4{i4
                                                                               do. sess';tJ (~t!s
                                                                               abstt've        as
                                                                               ~:.f.(,jd{)s CfJ.t't'e54" u.
                                                                               H#p.:5es slt:mtLve",.f).




                                                                               você está
sessão listeners



     Os Listetters relaciottados à Sessão

                                                   ?                                      classe
     Cenário                    attributeRemoved s1t,,,A-Hrt/;l/-/-eíve.,.f atributo classe i1ei1t.v~
                                   O
                                sessionDidActivate
                                attributeAdded
                                sessionCreated Iistener/métodos
                                A classe(javax.servleLhttp )
                                   interface classe
                                    Geralmente
                                valueBoundHHf'5es                               AJ~+b.:PJ4C f!.xtsh
                                             HttpSessionBindingEvent atributo Vds+e nft"hVJJ1
                                valueUnbound outra
                                HttpSessionActivationListener
                                    DUma HttpSessionEvent
                                HttpSessionBindingListener
                                HttpSessionAttributeListener
                                attributeReplaced do evento
                                             Tipo
                                      HttpSessionEvent
                                       HttpSessionListener                      AJ/Jfa: nõ'6
                                    ~ Alguma
                                         (javax.servleLhttp)
                                             HHf'Sess1i>"IrHri/fl,1-/-eíve,,-I-
                                sessionDestroyedoutra
                                        Alguma
                                        Uma classe
cê   desteforem sejam uma
     sessão.
     ou removidos de
     eles tipo associados
     notificados saber por
     implementado
     Você quer quando                                                                                   ~   Alguma outra
     Você quer saber




                                          Alguns dos eventos relacionados à sessão n~o seguem
                                          os pa d roes de nomenclatura para os eventos.
                                                   -

                         Os métodos HttpSessionListener adotam os HttpSessionEven~s.       . .
                         Os métodos HttpSessionBindingListener      adotam os HttpSesslOnBmdmgEvents.
                         Porém, os métodos HttpSessionAttributeListener     empregam o
                         HttpSessionBindingEvents.                                          .
                         E os métodos HttpSessionActivationListener     empregam o HttpSessl~nEvents.

                             Járfiqu~t clatssbeesmHtn~Soe~~~;:~:~;s~::~~:~:~c~:~:~;:;;:~~1:;;~~~;:;;
                                     as
                             pe el amen e       ,                                                                          de
                             eventos na API.




     264 capítulo 6
geref~lciélmienl'oda sessã



Os Ustmers para Evemos relaciotlados à Sessão e
utlta visão geral da API Objetos Evemo

              < <interfaee>     >
   HttpSessionActivationListener

sessionDidActivate(HttpSessionEvent)

session WiIlPassivate(HttpSessionEvent)




                                                                      HtipSessionEvení

              < <interfaee>     >
          HttpSessionListener

sessionCreated(HttpSessionEvent)

sessionDestroyed(HttpSessionEvent)




              < <interfaee>      >
     HtpSe~wnBmmngL~wn"
                                                              HttpSessionBindingEvení
valueBound(HttpSessionBindingEvent)
valueUnbond(HttpSessionBindingEvent)
                                             getSessionO
                                             getNameO
                                             getValueO




              < <interfaee>      >
     HtpSessionAttributeListener

attributeAdded(HttpSessionBindingEvent)
attributeRemoved(HttpSessionBindingEvent)
attributeReplaced(HttpSessionBindingEvent)   tJ ~tJ(/6        ~tJ.~                 ~tV'1?4.   6~           Ja
                                             .:s.f.f"Í15til) trl-rt~V+41JtIf ti.ese~aJelW 6
                                             tJ 1Pié+4Jó~/IJeO                      ~tlf'~a    t!J;   1I1J,/(Jf'
                                                                                                             JtI
                                                              J6      l)fJ~tI;          Jese~t:aJelW .,
                                             eve~.,.                                     f'~6f'~tJ.      6 tJ.~5(j
                                             iltJ./Óf'J   e      ., ~"VtJ. Is-I-<Js;~lltc4 1Ft ele
                                             re:+61"1?4. 118.161" () trl-1"t1JIJ-/-,(J suJa
                                                       tJ      1JIJe               ,6S
                                             A-AJrí:5 Jfi. IPI.{JJtJ.#1ftJ.1;IJe
                                                                           jtf'lW                     (j eve~d




                                                                                    você está
sessão Iisteners



                               Os Listetters relaeiottados à sessão
                               Sim, esta é uma cópia quase fiel da tabela que vimos duas
                               páginas atrás, então não vale olhar. Tente imaginar estes listeners
                               e anote seus melhores palpites. Você pode esperar por no mínimo
                               duas, ou até quatro perguntas sobre os listeners da sessão na
                               prova. Use a memória e o bom senso para preencher a tabela.




 Cenário           A interface Iistener/métodos     Tipo do evento              Geralmente
                                                                                 implementado por
                                                                                   classe
                                                                                D Alguma outra
                                                                                   atributo
 Você quer saber                                                                D Uma
                                                                                DUma classe
sessão.
    classe                                                                      D Alguma outra




                                                  'OJuaA:>! p!qo
                                                          o        ap sod!J S!OP svuadv   maJs!xa :g;)!<I

266 capl'tulo 6
'Pausa pata
                                                          9 caté



      1 Dado:
           10. pub1ic     class    MyServlet   extends    HttpServlet    {

           11.     public   void    doGet(HttpServletRequest       request,

         HttpServletResponse          response)
           12.     Ii       throws    IOException,    ServletException
17.
16.
15.
14.        13.
           18.          request.getSession()      .setAttribute(~key",        ~value");

                        request.getHttpSession()         .setAttribute(~key",      ~value");

                        «HttpSession)request.getSession(»            .setAttribute(~key",       ~value");

                        «HttpSession)request.getHttpSession(»                .setAttribute(~key",   ~value");




           Qual(is) linha(s) poderia(m) ser desanotada(s) sem causar erros de compilação ou runtime?
           (Escolha todas as que se aplicam.)
       DA. Somente a linha 13.
       DB. Somente a linha 14.
       Dc.       Somente a linha 15.
       DD. Somente a linha 16.
       DE. Linhas 13 ou 15.
       DF. Linhas 14 ou 16.




       2    Se um cliente NÃO aceita cookies, qual mecanismo de gerenciamento da sessão o web container
            pode utilizar? (Escolha uma.)
       DA. Cookies, mas NÃO reescrita de URL.
       OB. Reescrita de URL, mas NÃO cookies.
       Dc.       Tanto os cookies, como a reescrita de URL podem ser usados.
       DD. Nem os cookies, nem a reescrita de URL podem ser usados.
       DE. OS cookies e a reescrita de URL devem ser usados juntos.




                                                                                            você está aquj ••. 267
teste preparatório




3 Quais declarações    sobre os objetos HttpSession   são verdadeiras? (Escolha todas as que se
     aplicam.)
  DA. Uma sessão cujo tempo de timeout foi estipulado em -1 nunca expirará.
  DB. Uma sessão tomar-se-á inválida assim que o usuário fechar todas as janelas do seu browser.
  De.     Uma sessão tomar-se-á inválida depois do tempo de timeout definido pelo servlet container.
  DD. Uma sessão pode ser explicitamente invalidada chamando o HttpSession.
    invalidateSession().




4    Quais das segúintes opções NÃO representam tipos de eventos listener na API J2EE 1.4? (Escolha
     todas as que se aplicam.)
    [JA.HttpsessiOnEvent
    DB. ServletRequestEvent
    De.   HttpSessionBindingEvent
    DD.HttpsessiOnAttributeEvent
    C}E.servletContextAttributeEvent




5 Quais das seguintes      declarações sobre o monitoramento da sessão são verdadeiras? (Escolha todas
     as que se aplicam.)
  C}A. A reescrita de URL pode ser usada por um servidor como base para o monitoramento de
    sessões.

    C}E. O SSL tem um mecanismo nativo, que um container servlet pode usar para obter dados usados
      para definir uma sessão.
    De. Ao usar cookies para acompanhar as sessões, não há restrições para o nome do cookie que
       realiza o acompanhamento da sessão.
    C}D. Ao usar cookies para acompanhar as sessões, o cookie usado para acompanhar a sessão deve
      receber o nome de JSESSIONID.

    [JE. Se o browser de um usuário está desabilitado para receber cookies, o container pode decidir
       usar um objeto javax. servlet. http.CookielessHttpSession      para monitorar a sessão do
       usuário.




268 capítulo 6
gerenciamento   da sessão




6 Dado:
   1. import javax.servlet.http.*;
   2. public class MySessionListener
               implements HttpSessionListener
   3.       public void sessionCreated() {
   4.           System.out.println(~Session Created");
   5.
   6.       public void sessionDestroyed() {
   7.           System.out.println(~Session Destroyed");
   8.
   9.



   o que há de errado   com esta classe? (Escolha todas as que se aplicam.)
 DA. A assinatura do método na linha 3 está INCORRETA.
 DB. A assinatura do método na linha 6 está INCORRETA.
 De.    A declaração import não importará a interface HttpSessionListener.
 DD. O sessionCreated e o sessionDestroyed NÃO são os únicos métodos definidos pela
   interface HttpSessionListener.




1  Quais declarações sobre os atributos da sessão são verdadeiras? (Escolha todas as que se aplicam.)
 DA. O tipo de retomo do HttpSession.getAttribute          (String) é Object.
 DB. O tipo de retomo do HttpSession.getAttribute          (String) é String.
 De. OS atributos associados a uma sessão ficam disponíveis para qualquer servlet que faça parte
    do mesmo Serv1.etContext, e que trate uma solicitação identificada como sendo parte da mesma
   sessão.

 DD. Chamar o setAttribute (~keyA", ~va1.ueB")em um HttpSession que já possua um valor
   para a chave keyAcausará uma exceção.
 DE. Chamar o setAttribute (~keyA", ~valueB") em um HttpSession que já possua um valor
   para a chave keyAfará com que o valor anterior para este atributo seja substituído pela String
    valueB.




                                                                                 você está      •• 269
teste preparatório




8 Quais interfaces definem um método getSession       () ? (Escolha todas as que se aplicam.)
  C]i.ServletRequest
  C]B. ServletResponse
  C]C. HttpServletRequest
  C]D. HttpServletResponse




9 Seja um objeto sessão s e o código:
   s.setAttribute{~key",        value);
  Quais dos listeners podem ser notificados? (Escolha um.)
  Di. ipenas o HttpSessionListener.
  C]B. ipenas o HttpSessionBindingListener.
  C]C. ipenas o HttpSessionAttributeListener.
  C]D. O HttpSessionListener        e o HttpSessionBindingListener.
  C]E. O HttpSessionListener        e o HttpSessionAttributeListener.
  C]E O HttpSessionBindingListener          e o HttpSessiOnAttributeListener.
  00. Todos os três.




10   Considerando que req é um HttpServletRequest, quais das opções criam uma sessão, caso não
     exista nenhuma? (Escolha todas as que se aplicam.)
  Di.req.getsession{)      ;
  C]B. req.getSession{true);
  C]C. req. getSession (false) ;
  C]D. req. createSession () ;
  DE. req.getNewSession{);
  C]F.req.createSession{true);
  00. req. createSession        (false) ;




270 capítulo 6
gerencíamento    da sessão




11 Dado   o objeto sessão s com dois atributos chamados myAttrl e myAttr2, quais alternativas
     removerão ambos os atributos desta sessão? (Escolha todas as que se aplicam.)
 CJi. s.removeAllValues();
 [JB. s.removeAttribute(~myAttrl");s.removeAttribute(~myAttr2");
 [Je. s. removeAllAttributes      () ;
 [JD. s. getAttribute (~myAttrl", UNBIND); getAttribute
                                        s.                        (~myAttr2", UNBIND);
 [JE. s. getAttributeNames (UNBIND)
                                 ;




12   Quais das seguintes declarações sobre os objetos HttpSession em um ambiente distribuído são
     verdadeiras? (Escolha todas as que se aplicam.)
 CJA Quando uma sessão é movida de uma        NM   para outra, quaisquer atributos armazenados na
   sessão serão perdidos.
 DE.    Quando uma sessão é movida de uma NM para outra, os objetos
     HttpSessionBindingListener   devidamente registrados serão notificados.
 De.    Quando uma sessão é movida de uma NM para outra, os objetos
     HttpSessionActivationListener   devidamente registrados serão notificados.
 DD. Quando uma sessão é movida de uma NM para outra, os valores dos atributos que
   implementam j ava. io. Serializable serão transferidos para a nova NM.




13   Quaisdeclarações   sobre o timeout das sessões são verdadeiras? (Escolha todas as que se
     aplicam.)
 DA     is declarações de timeout da sessão que foram criadas no DD aceitam o tempo em segundos.
 DE.    is declarações de timeout da sessão que foram criadas no DD aceitam o tempo em minutos.
 De. is declarações de timeout da sessão que foram criadas programaticamente      aceitam o tempo
    em segundos.
 DD. is declarações de timeout da sessão que foram criadas programaticamente      aceitam o tempo
   em minutos.

 CJE. is declarações de timeout da sessão que foram criadas programaticamente     aceitam o tempo
   em minutos ou segundos.




                                                                             você está
teste preparatório




14- Escolha o trecho do código servlet que ativaria a partir de uma solicitação o valor de um cookie
      denominado "ORA_UID"? (Escolha todas as que se aplicam.)
  DA. String value           = request.getCookie("ORA_ UID");
  DB. String value           = request.getHeader("ORA_ UID");
  Dc.    javax.servlet.http.Cookie[]        cookies   =
                request.getCookies();
         String       cName    = null;
         String       value    = null;
         if    (cookies       !~ null) {
              for    (int i = O; i < cookies.length;         i++) {
                cName     = cookies[i]     .getName();
                if    (cName    != null    &&

                       cName.equalsIgnoreCase(~ORA_UID")){
                     value    = cookies[i] .getValue();



         }

  DD. javax.servlet.http.Cookie[]           cookies   =
        request.getCookiesO;
         if    (cookies.length       > O) {
               String     value   = cookies[O]    .getValue();




15    Qual(is) método(s) pode(m) ser usado(s) para pedir ao contêiner para notificar seu aplicativo
      sempre que uma sessão estiver com o tempo esgotado? (Escolha tudo que se aplica.)
  DA. HttpSessionlistener.sessionDestroyed;
  DB. HttpSessionBindingListener.valueBound;
  Dc.     HttpSessionBindingListener.valueUnbound;
  DD. HttpSessionBindingEvent.sessionDestroyed;
  DE. HttpSessionAttributeListener.attributeRemoved;
  DF. HttpSessionActivationListener.sessionWillPassivate;




272                   6
gerenciamento    da sessão




16   Como você usaria o objeto HttpServ1.etResponse em um servlet para adicionar um cookie no
     cliente? (Escolha todas as que se aplicam.)
 DA. <context-param>
                <param-name>myCookie</param-name>
                <param-va1ue>cookieVa1ue</param-va1ue>
           </context-param>

 DB. response.addCookie("myCookie"," cookie Value");
 Dc.       javax.servlet.http.Cookie newCook =
                  new javax.serv1et.http.Cookie(~myCookieH,HcookieValueH);
           // ...set other            Cookie   properties
           response.addCookie(newCook);

 DD. javax.servlet.http.Cookie[] cookies = request.getCookiesO;
           String       cname    ~ nu11;
           if    (cookies       != nu11) {
                 for    (int i = O; i < cookies.1ength;               i++) {
                       cName    ~ cookies[i]      .getName();
                       if    (cName    !~ nu11 &&
                             cName.equa1sIgnoreCase(~myCookieH»){
                            out.print1n(       cName   + ~: ~ + cookies[i]       .getVa1ue();




11 Dado:
     13.                    pub1ic     c1ass    Serv1etX    extends   HttpServ1et       {
     14.                     pub1ic    void doGet (HttpServ1etRequest             req, HttpServletResponse     resp)
     15.                     throws    IOException, Serv1etException             {
     16.                     HttpSession   sess = new HttpSession              (req);
     17.                     sess.setAttribute(~attr1H,
     18.                     sess.invalidate();
     19.                     String    s = sess.getAttribute(~attr1H);
     20.
     21. }
     Qual é o resultado? (Escolha tudo que se aplica.)
 DA. A compilação falha
 DB. O valor de s é null
 De.       O valor de s é "value"
 DD. Uma IOException é enviada
 DE. Uma ServletException é enviada
 DF. Uma IllegalStateException é enviada

                                                                                                você está      ~   273
respostas do teste




      1Dado:
         10. public     class MyServlet      extends    HttpServlet   {

         11.     public   void   doGet(HttpServletRequest         request,

         HttpServletResponse       response)
         12.     Ii       throws   IOException,    ServletException
16.
15.
14.
17.      13.
         18.          request.getSession()     .setAttribute(~key",          ~value");

                      request.getHttpSession()         .setAttribute(~key",      ~value");

                      «HttpSession)request.getSession(»            .setAttribute(~key",              ~value");

                      «HttpSession)request.getHttpSession(»               .setAttribute(~key",                ~value");




         Qual(is) linha(s) poderia(m) ser desanotada(s) sem causar erros de compilação ou runtime?
         (Escolha todas as que se aplicam.)
        DA. Somente a linha 13.
        DB.    Somente a linha 14.
        Dc.    Somente a linha 15.
        DD. Somente a linha 16.
        ~ E. Linhas 13 ou 15.

        DF. Linhas 14 ou 16.




       Z Se um cliente NÃO aceita cookies, qual mecanismo de gerenciamento da sessão o web container
          pode utilizar? (Escolha uma.)
        DA. Cookies, mas NÃO reescrita de URL.                                                (.5ervle.f-v2.'~f~'               S7
        ~ B. Reescrita de URL, mas NÃO cookies.
        Dc.    Tanto os cookies, como a reescrita de URL podem ser usados.

        OD. Nem os cookies, nem a reescrita de URL podem ser usados. -              A-   /jfJ';~     es.f-:   CÓl'l"fl.f-fJ.;


        DE. OS cookies e a reescrita de URL devem ser usados juntos.             f/j~l~e
                                                                                 Ctl_ff;S)   I-JA-o POJ)f.M.~?(/;fJ.;::
                                                                                               4{'I.$4 l"eeSCI'IT"IJ. ",e "" ••.•
                                                                                 AJA-o    tiepenJe tie 3(/f! eles          es.f-tja4
                                                                                 f"dtlt.f-a.tiós.


      274 capítulo 6
gerenciamento    da sessão




3 Quais declarações         sobre os objetos HttpSession     são verdadeiras? (Escolha todas as que se
    aplicam.)                                                               (Servle-l-v2.~p~.                 S"9)
  Iilr A. Uma sessão cujo tempo de timeout foi estipulado em -1 nunca expirará.
  OB. Uma sessão tomar-se-á inválida assim que o usuário fechar todas as janelas do seu browser.
  ~ C. Uma sessão tomar-se-á inválida depois do tempo de timeout definido pelo servlet container.
  OD. Uma sessão pode ser explicitamente invalidada chamando o HttpSession.
    invalidateSession().

- A- DfSãó!J es-l-: tÍ'/cÓN'e-l-~ plu'ave <l ",Ht:uill ave
                                                                  - A- ófSãó   5 es-l-:
devert). ser I/stldó ct.a",a-se tÍ'/valtda-hO.                    eXis-h: v", stPial
                                                                  de 3ve ti sessãó   acabóv.



4    Quais das seguintes opções NÃO representam tipos de eventos listener na API J2EE IA? (Escolha
     todas as que se aplicam.)
    OA. HttpSessionEvent
  OB.     ServletRequestEvent
    OCo HttpSessionBindingEvent
    IilrD.HttpSeSSiOnAttributeEvent
    OE.servletContextAttributeEvent




5 Quais das seguintes          declarações sobre o monitoramento da sessão são verdadeiras? (Escolha todas
     as que se aplicam.)                                                                  <'Servle+-
    Iilr A. A reescrita de URL pode ser usada por um servidor como base para o monitoramento             de
        sessões.

    Iilr B. O SSL tem um mecanismo nativo, que um container servlet pode usar para obter dados usados
        para definir uma sessão.
    Oe. Ao usar cook:ies para acompanhar as sessões, não há restrições para o nome do cookie que
      realiza o acompanhamento da sessão.
    Iilr D. Ao usar cook:ies para acompanhar as sessões, o cookie usado para acompanhar a sessão deve
        receber o nome de JSESSIONID.

    DE. Se o browser de um usuário está desabilitado para receber cook:ies, o container pode decidir
      usar um objeto javax. servlet. http.CookielessHttpSession      para monitorar a sessão do
      usuário.

- A- ~PSãó    í es-l-: tÍ'/c6N'e-l-tl)fór3ve   '1ãó
exls-!-e es-l-a c/4S5e.



                                                                                          você está      IP   275
respostas do teste




6 Dado:
   1. import javax.servlet.http.*;
   2. public class MySessionListener
                implements HttpSessionListener
   3.       public void sessionCreated() {
   4.            System.out.println(~Session Created");
   5.
   6.       public void sessionDestroyed() {
   7.            System.out.println(~Session Destroyed");
   8.
   9.
                                                                                               8
                                                                         - fJrs "pí.';es fJr e es-l-';" c""'t'e-l-4sJ f"t'3ve
                                                                         eshs      é-l-'Jfl"s tievel'l"Q. hl' ti•.•p4t'M..e+l'''
                                                                                 •.•                    •.•
                                                                         HHpSes sl(JIfLve.rl-.

   O que há de errado com esta classe? (Escolha todas as que se aplicam.)

  ~ A. A assinatura do método na linha 3 está INCORRETA.                           - fJr "P'j';t) C es-l-: ~Ptc4N'e-l-4J
  ~ B. A assinatura do método na linha 6 está INCORRETA.                           pt:II"3ve" lishlfel' e ofel,PtIi;f"IfD
                                                                                   p4c6h i"'f>"1'-I-4ti6.
  Dc.    A declaração import não importará a interface HttpSessionListener.
  DD. O sessionCreated e o sessionDestroyed NÃO são os únicos métodos definidos pela
    interface HttpSessionListener.
                                                                                   - fJr lJp,';6!J es-l-: IPtc(Jl'l'e-l-~ptJI'11'e
                                                                                   eshs     s'; •• tJS tids tJ..,ic/JS ""é=l-tJtitJs
                                                                                   Ifes-l-a ,Pt-h,..{ace.




1  Quais declarações sobre os atributos da sessão são verdadeiras? (Escolha todas as que se aplicam.)

                                                                                                (Sel'vle-l-   11   2..~ p~.   S-9)
  ~ A. O tipo de retomo do HttpSession.getAttribute                     (String) é Object.
  DB. O tipo de retomo do HttpSession.getAttribute                      (String) é String.
  ~ C. Os atributos associados a uma sessão ficam disponíveis para qualquer servlet que faça parte
    do mesmo ServletContext, e que trate uma solicitação identificada como sendo parte da mesma
    sessão.

  OD. Chamar o setAttribute (~keyA", ~valueB") em um HttpSession que já possua um valor
    para a chave keyAcausará uma exceção.
  ~ E. Chamar o setAttribute (~keyA", ~valueB") em um HttpSession que já possua um valor
    para a chave keyAfará com que o valor anterior para este atributo seja substituído pela String
      valueB.

                                  8
                     - fJr tJP'j';tJ es-l-~ IPtc61'1"e-l-t!..J
                                                         p61'{pe   tJ
                                                                            - fJr 6f,';" Õ es-l-: IPtC61"1"e+~fóI"3{jei!f-l-a
                     -I-ip" tie 1"e+"1"If6e 0!(jec+.                                                                      ja
                                                                            d,a_tio. apel1f),Ssvbs-l-,.-I-v""'f), ) Vf),I",..
                                                                                                                (
                                                                            exishl1h.




276     capítulo 6
gerencíamento               da sessão




8 Quais interfaces definem um método getSession{)?                  (Escolha todas as que se aplicam.)
 eli. ServletRequest
 elB. ServletResponse
 ~C.HttpServletRequest
 elD. HttpServletResponse




9 Seja um objeto sessão 5 e o código:
   s.setAttribute(~key",        value);
  Quais dos listeners podem ser notificados? (Escolha um.)
  eli. ipenas o HttpSessionListener.
  elB. ipenas o HttpSessionBindingListener.
  elC. ipenas o HttpSessionAttributeListener.
  elD. O HttpSessionListener        e o HttpSessionBindingListener.
  elE. O HttpSessionListener       e o HttpSessionAttributeListener.
  ~ F. O HttpSessionBindingListener         e o HttpSessionAttributeListener.
  DG. Todos os três.
                                          - Pr 4plã4 Fé li C41'1'rl-fl.)p4t''lll'!.           VIYI,
                                          H#p5es    Si61'1t;r#I'''!w/~L''s+el'1l!.I'             I!.114+'-llCfl.d<lse""I'e        3";
                                          VIYIa.f-l't!IlI-l-<I I!.aCl"escel'l-l-ad<l) e <I <lfje-l-tl valtll" .f-alYlIJelYt
                                                                                                                          sel"a
                                          I1tl+'-llcfl.d<l se ele iJty>lelYlelrÍ-fl.l' VlYtff#p5essl41'18t"ldtI'15L,"sI-e",el".




10   Considerando que req é um HttpServletRequest, quais das opções criam uma sessão, caso não
     exista nenhuma? (Escolha todas as que se aplicam.)
  ~ i. req.getSession{);
  ~B.   req. getSession (true) ;
  elC. req.getSession(false);               - Prs tlpjces        Pr e   8 cri"tJ.I'';<I"IYtfl."'''lia                 Cfl.Stl
                                             l'l6.tl ex'"s+-fI. "IYta. O 5rl-5essftll'l(IfJ.lstl)       I'e.f-"I'I'IfJ. tllYI
  elD. req. crea teSession () ;              l'es"l-I-ad6 "Ivl" se fi. S(,SS';<l '"146
  elE. req.getNewSession();
  elE req. createSession (true) ;
  elG. req. createSession (false) ;



                                                                                                        você está                 li>   277
res.lJostas do teste




11 Dado   o objeto sessão s com dois atributos chamados myAttrl e myAttr2, quais alternativas
     removerão ambos os atributos desta sessão? (Escolha todas as que se aplicam.)
  DA. s. removeAllValues () ;
  ~B. s.removeAttribute(~myAttrl");s.removeAttribute(~myAttr2");
  De. s. removeAllAttributes     () ;
  DD. s.getAttribute(~myAttrl",  UNBIND)
                                       ;s.getAttribute(~myAttr2",                     UNBIND);
  DE. s. getAttributeNames (UNBIND)
                                  ;
                                                       - /} cp{õ,c 8 es+: cCI'I'e+a. e>
                                                       reIMclleA-#rl/JlI+eO  é a tfJ'JlcafUIMtI. de
                                                       reIMCllerIMCS VIMa+l'lltll+C   de VIMctje+ó     sess46;
                                                       e ele reIMclle VIMa+l'lltv+c   de cada lIe;.



12   Quais das seguintes declarações sobre os objetos HttpSession em um ambiente distribuído são
    verdadeiras? (Escolha todas as que se aplicam.)              (5ervle+v2..~pt.s.   (,0)
  DA. Quando uma sessão é movida de uma NM para outra, quaisquer atributos armazenados na
    sessão serão perdidos.
  DE.   Quando uma sessão é movida de uma NM para outra, os objetos
     HttpSessionBindingListener devidamente registrados serão notificados.
  ~ C. Quando uma sessão é movida de uma NM para outra, os objetos
    HttpSessionActivationListener   devidamente registrados serão notificados.
  ~ D. Quando uma sessão é movida de uma NM para outra, os valores dos atributos que
    implementam java. io. Serializable serão transferidos para a nova NM.




13   Quais declarações sobre o timeout das sessões são verdadeiras? (Escolha todas as que se
    aplicam.)                                                                          (A-fI)
  DA. As declarações de timeout da sessão que foram criadas no DD aceitam o tempo em segundos.
  ~ E. As declarações de timeout da sessão que foram criadas no DD aceitam o tempo em minutos.
  ~c.  As declarações de timeout da sessão que foram criadas programaticamente             aceitam o tempo
     em segundos.
  DD. As declarações de timeout da sessão que foram criadas programaticamente              aceitam o tempo
    em minutos.

  DE. As declarações de timeout da sessão que foram criadas programaticamente             aceitamo tempo
    em minutos ou segundos.

                                                       c Se
                               espect/lcal' cs IMi'J'1V+cs. flSal'IMóS{;SlDJ'J-+,'w,ecl.I+:>~ f-cJew"t;s
                               -lJólJlJ; se IISfJ,t'IMCSeleIMe'l+c <ses se+MlJ.xI'Iac~·veI'I+ervtl.IO
                                                                                           s               rJó
                               ft#pSesS'i'c"l; ape"lfJs6S se51.1"1rJós
                                                                     p6r1eIMseI' especr-li'caJ6S'.


278 capitulo 6
gerenciamento          da sessão




14 Escolha     o trecho do código servlet que ativaria a partir de uma solicitação o valor de um cookie
        denominado "ORA_ UID"? (Escolha todas as que se aplicam.)
 DA. String value            = request.getCookie("ORA _illD");
 DB. String value            = request.getHeader("ORA _UID");
 li2'   c. javax.servlet.http.Cookie[]     cookies   =              -If (Jp{á(J If f"efef'e-      S't: 4 tllfI lfIé.f(JtJ(J
                 request.getCookies();                              Ôllt: "â.(J t:xtsh.
          String      eName    ~ null;                              - If   (JPSâ.(J f"ect:be 1I1f1 41'1'"
                                                                                   C                      C(J"kte
          String
          if
                      value
                (eookies
                               = null;
                              != null) {                                                  ,
                                                                    lIsa"tJ(J (J reÔlles.f'5~óók"e$()J

                                                                    de "(Jlfle espec,ftc(J.
                                                                                                               e
                                                                    tJepói'$ verlflca a exts+eJfci'fJ; tJe IIIf1 cóó/:te

               for   (int i = O; i < eookies.length;        i++){
                 eName = eookies[i].getName();                      -If     ópSâ."     b 1J11.44pf!114$     tl p"tlflt:if"tl
                 if (cName != null &&                               Có"l:te     Jfó   tAl'f"4j.

                       eName.equalsIgnoreCase(~ORA_UID"»){
                     value    ~ cookies[i].getValue();




          }


 DD. javax.servlet.http.Cookie[]           cookies   =
        request. getCookiesO;
          if    (eookies.length       > O) {
                String   value    ~ eookies[O]   .getValue();




15      Qual(is) método(s) pode(m) ser usado(s) para pedir ao contêiner para notificar seu aplicativo
        sempre que uma sessão estiver com o tempo esgotado? (Escolha tudo que se aplica.)
 li2' A. HttpSessionlistener.sessionDestroyed;

 DB. HttpSessionBindingListener.valueBound;
  li2' C. HttpSessionBindingListener.valueUnbound;

 DD. HttpSessionBindingEvent.sessionDestroyed;
  DE. HttpSessionAttributeListener.attributeRemoved;
  DF. HttpSessionActivationListener.sessionWillPassivate;




                                                                                          você está                11>     279
reSiPos:tas do teste




16   Como você usaria o objeto HttpServletResponse                          em um servlet para adicionar um cookie no
     cliente? (Escolha todas as que se aplicam.)
  DA. <context-param>                                                                    - jf            $
                                                                                                 Dffã •• es+~ il'/c{>l"l"e+a,;ffJf'3l1e (>
                 <param-name>myCookie</param-name>                                       ""fj-lNJIJ ~JdC<)fJJ:i'eO ehlpl'ej" li"" IJtje-l- ••
                                                                                         C6fJtte) e I'/ã•• :5+1"I"1'I5s, ••
                 <param-value>cookieValue</param-value>
        </context-param>
                                                                                         - /} "ffã6 b es+:             '''''CIJI''I'e+a,; p"l"?Jve
                                                                                         eltJ.""6S+I'~ V"" servle+            (J;·/-lV{J;I7J6)
                                                                                                                                             e
  OB. response.addCookie("myCookie","                         cookie Value");            Cf'i'o.I1JIJ11""cÕ6/i:ie.

  ~ C. javax.servlet.http.Cookie                  newCook      =
                   new javax.servlet.http.Cookie(~myCookie","cookieValue");
            // ...set other            Cookie     properties
            response.addCookie(newCook);

  OD. javax.servlet.http.Cookie[]                   cookies   = request.getCookiesO;
            String       cname    = null;
            if    (cookies       !~ null) {
                  for    (int i = O; i < cookies.length;                  i++) (
                        cName    = cookies[i] .getName();
                        if    (cName    != null     &&
                              cName.equalsIgnoreCase(~myCookie"))                  (
                             out.println(        eName   + ~: ~ + cookies[i]             .getValue();




11 Dado:
     13.                     public     elass ServletX extends HttpServlet  (
     14.                     publie     void doGet (HttpServletRequest  req, HttpServletResponse                                            resp)
     15.                      throws IOException,    ServletException   (
     16.                      HttpSession   sess = new HttpSession    (req);
     17 .                     sess.setAttribute(~attrl",
     18.                      sess.invalidate();
     19.                      String    s ~ sess.getAttribute(~attrl");
     20.
     21.     )
     Qual é o resultado? (Escolha tudo que se aplica.)

  ~ A. A compilação falha                                          _ {) ãD 1Jr:a ;,.",t.o.I' :       ,,,,,c/)f'reh..    Võcê <IJSlltl"e 11""
  O.
  .B.        O valor de s e null                                   "tie.,-/) ~lIe ihlp Ie""e'7ra
                                                                       í"~         .           L    #-/-+p5eSSi{»IIlSfA'7JIJ
                                                                                                         ,                              re'!..
                                                                                                                                            fi
                                                                    lXe+5esstIJJ'I( ).
  De.        O valor de s é "value"                                "
  OU. Uma IOException é enviada
  DE. Uma ServletException                      é enviada
  DF. Uma IllegalStateException                     é enviada

280 capitulo 6
t   USand9 9 JSP

                        Sendo umJSP




Um JSP torna-se um servlet. Um servlet que você não cria.
O Container olha o seu JSP, o traduz em código-fonte Java e o
compila em uma classe servlet de Java completa. Porém, você tem
que saber o que acontece quando o código que você escreveu em
JSP se transforma em código Java. Você pode escrever códigos
Java em JSP, mas será que você deveria? E se você não escrever
o código Java, o que você escreverá? Como ele faz a tradução
para o código Java? Neste capítulo, veremos seis diferentes tipos
de elementos JSP - cada um com seu próprio propósito e, sim,
sintaxe única. Você aprenderá como, por que e o que escrever
no seu JSP. Talvez o mais importante, você aprenderá o que não
escrever no seu JSP.



                                                      este   é um   novo ca{.lítu,rO'"   281
objetivos do exame oficial da Sun




                                                             os

o Modelo      de Tecnologia do JSP                    Notas sobre a Abrangência:


6.1 Identificar, descrever ou escrever o código       A maioria é tratada neste capítulo, mas os
    JSP para os seguintes elementos: (a) template     detalhes que envolvem as (c) ações-padrão e
    text, (b) elementos de scripting (comentários,    customizadas e (d) os elementos da expression
    diretivas, declarações, scriptlets e              language serão abordados nos próximos capítulos.
    expressões), (c) ações-padrão e customizadas,
    e (d) elementos da expression language.           A diretiva de página será abordada neste
6.2 Escrever o código JSP que usa as                  capítulo, mas o include e a taglib serão
    diretivas: (a) page (com os atributos             abordados nos próximos capítulos.
    import, session, contentType e
    isELIgnored), (b) include, e (c) taglib.          Não será abordado aqui; verifique o capítulo
                                                      sobre Distribuição.
6.3 Escrever um Documento JSP (documento
    baseado em XML) que usa a sintaxe correta.
                                                      Tudo abordado neste capítulo. (Dica: estas
6.4 Descrever o propósito e a seqüência de            serão algumas das perguntas mais tranqüilas
    eventos do ciclo de vida de uma página JSP:       do exame, uma vez que você aprendeu o básico
    (1) tradução da página JSP, (2) compilação        neste capítulo.)
    da página JSP, (3) carregar a classe, (4) criar
    a instância, (5) chamar o método jspInit, (6)
                                                      Tudo abordado neste capítulo, embora se espera
    chamar o método jspService, e (7) chamar o        que você já saiba o que a maioria deles significa,
    método jspDestroy.
                                                      baseado nos dois capítulos anteriores.
6.5 Dado um objetivo de design, escrever o
    código JSP, usando os objetos implícitos
                                                      Nós falamos sobre tudo aqui, exceto declarar as
    apropriados: (a) request, (b) response, (c)
                                                      bibliotecas de tags, que será visto no capítulo
    out, (d) session, (e) config, (f) application,    Usando a JSTL.
    (g) page, (h) pageContext, e (i) exception.
6.6 Configurar o deployment descriptor para
                                                      Não é abrangido aqui; verifique no próximo
    declarar uma ou mais bibliotecas de tags,
                                                      capítulo (JSP sem scripts).
    desativar a linguagem de avaliação e
    desativar a linguagem de scripting.
6.7 Dado um objetivo de projeto especifico para
    incluir um segmento JSP em outra página,
    escrever o código JSP que usa o mecanismo
    de inclusão mais apropriado (a diretiva
    include ou a ação-padrão jsp:include).




282 capítulo 7
usando      o JSP


No fitM das comas, o JSP é só             UtM servlet

9  seu JSP toma-se um servlet completo rodando em sua aplicação.
E muito parecido com qualquer outro servlet, exceto pelo fato de
que a classe do servlet é escrita para você - pelo Container.
O Container utiliza o que você escreveu no seu JSP, o traduz
para um arquivo-fonte da classe servlet (.java) e o compila em
uma classe servlet Java. Depois disso, ele será só um servlet e
rodará exatamente do mesmo jeito, como se você mesmo tivesse
escrito e compilado o código. Ou seja, o Container carrega a
classe servlet, instancia-a e inicializa-a, cria uma tbread para
cada solicitação e chama o método serviceO do servlet.



                                                                              , carregado
                                   é traduzido                                : ini ciali zado
                                        -paro.                                      como
                                                        com-pila em
                                    ~                   ~                           ~
                                                                                                 MyJSP jsp   Servlet

                       MyJSP.jsp                                   MyJSPjsp.class




              ••
Algumas das perguntas que responderemos neste capítulo são:



~ Para onde vai cada parte do seu arquivo JSP no código-fonte do servlet?

~ Você tem acesso às características "sem servlet" da sua página
  JSP? Por exemplo, o JSP tem noção do ServletConfig ou do
  ServletContext?

~ Quais são os tipos de elementos que você pode inserir em um JSP?

~ Qual é a sintaxe para os diferentes elementos de um JSP?

~ Qual é o ciclo de vida de um JSP? Você pode interferir nele?

~ Como os diferentes elementos de um JSP interagem no servlet final?




                                                                                    você está           ~      283
fazendo um JSP



Criando   UtM   JSP que exiba quatttas vezes ele foi acessado
Pauline quer usar JSPs em suas aplicações - ela está realmente cansada de
escrever HTML no seu método printlnO do PrintWriter do seu servlet.
Ela decide aprender JSPs, criando uma página dinâmica simples que
exibe o número de vezes que ela foi solicitada. Ela sabe que você pode
colocar um código Java normal em um JSP usando um scriptlet - que
significa simplesmente o código Java dentro de uma tag <% ... %>.




      Já que eu posso colocar código
        Java no JSP, vou criar um
      método estático em uma classe
      Counter, para manter a variável
         estática de contagem de                                 BasicCounter.jsp
      acessos e chamar este método
             a partir do JSP ...
                                             <html>
                                             <body>
                                             The page    count    is:
                                             <%
                                               out.println(Counter.getCount(»;


                                             </html>
                                             ~~bOdY>     ~                    1/            U       I      I
                                                               D cltje+6           (jiJ.fes+a ,~/u:r+t'J
                                                               1Vi/ce~l'e           <% e %> é iJl;i SCl'l,+le+J
                                                               3iJe é a,eJ1s's        JIJ.IIs'   s,~/es.


                                                                   Counter.java

                                             package    foo;

                                             public class Counter (
                                                private static int count;
                                                public static synchronized                       int getCount()

                                                      count++i
                                                      return count;




                                                                    Clas se (;.s
                                                                               sis-k?t-k
                                                                    JlJ.1I4   siMples.




284 capítulo 7
usando o JSP



Ela distribui e testa o JSP
Distribuir e testar é trivial. A única parte confusa é
garantir que a classe Counter esteja disponível para
o JSP. E isso é fácil: basta colocá-Ia no diretório
WEB-INF/classes da aplicação. Ela acessa o JSP
direto pelo browser:
http://localhost:8080/testJSPl/BasicCounter.j       sp




                                                              The page count is: 1
                 !tdjhqn
                 Jfhq.i
                 F.ijqof

 BasicCouj'-fér.jsp

                       Kcljhgn
                       3fhg.i
                       Fijgof

                 weh.'<rnl


      {
Po.l'fJ.   flc

                                               "-'OlOI




Ctl/lJ3ve b ,/il'e-l-/-l'ltJ
                                 I   ~.,m


                                   J (J
                                            Couni~~lcla"
                                                           HTTP Status     500 -


                                                           The server encountered       an internal   error   o that   prevent   it from fulfilling this request.
                                                           II!!J!IIorg.apache.jasper.JasperException:                  Unable to compile      c1ass for JSP
pfJ.clJh e" al'3VlV6             .class                    An errar occurred at line 1 in the jsp file :/Basic         Counter.jsp
                                                           Generated servlei errar:
JI1lJ .,fll'e-l-/-I'tô       wí$-IIJFI                     Uavac} Compiling 1 source file
                                                           IUsers/kathy/App[ications2/jakarta-tomcat-5.019!workfCatalinaJIocalhostltestJSP1/org/apache/jspl


clo.sses)        e 1Jtltl,!fl/el'pfJ.l'h                   ~::~~I~U;~~~f~ba~~~:;cannot          resolve symbol
                                                           location: class org.apache.jsp.basicCounterjsp
                                                                                                                                    4,cê       C611Se
                                                                                                                                                             ':5
                                                                                                                                                                   Vf
           I          '"          I
                     "
,/es"F1.I.apltcl.l.fl.l.o sel'lt                                               out.pri~t( Counter.getCountO);                       eJ1ffJ1Jel' IJ 3(1E'
capa; Je ve-!c.                                             1 error
                                                                                                                                    Jev E'I'I'D.,/ó?
                                                                               org.apache.jasper.compiler. DefaultErrorHandler.javacError(DefaultErrorHandler.java:       127)
                                                                               org.apache.jasper.compiler. ErrorDispatcher.javacError(ErrorDispatcher.java:351      )
                                                                               org.apache.jasper.compiler.generateclass(Compiler.java:415)
                                                                               org.apache.jasper.compiler.Compiler.compile(Compiler.java:458)
                                                                               org.apache.jasper.compiler.Compiler.compile(Compiler.java:439)
                                                                               org.apache.jasper.JspCompilalionContext.compile(JspCompilationContext.java:553)
                                                                               org .apache.jasper.servleUspServletWrapper.service(JspServletWrapper.java:291          )
                                                                               org .apache.jasper.servleUspServlet.serviceJspFile(JspServlet.java:301      )
                                                                               org.apache.jasper.servleUspServlet.service(JspServlet.java       :248)
                                                                               javax.servlet-http.HttpServlet.service(HttpServle1.java:856)



                                                                                                                                                                                 .,




                                                                                                                                  você está aqui ••.
o atributo imporl da diretiva da página


o JSP Kão recoKhece           a classe Couttter
A classe Counter está no pacote foo, mas não há nada no
JSP capaz de reconhecê-Ia. É idêntico ao que acontece
com você em qualquer outro código J ava. E você conhece
a regra: importe o pacote ou use o nome da classe
totalmente qualificado no seu código.




         Eu acho que você tem que usar o
      nome da classe totalmente  qualificado
        dentro dos JSPs. Faz sentido, pois
                                                                     Counter.java
       todos os JSPs foram transformados
         em código servlet Java simples
        pelo Container. Mas é claro que eu          package   foo;
        gostaria que você pudesse colocar
            im orts no seu código JSP ...           public class Counter (
                                                       private static int count;
                                                       public static int getCount()
                         C>                                 count++;
                         O                                  return count;




                                                  o código    JSP era:
                                                    <% out.println(Counter.getCount());                   %>



                                                  o código    JSP deveria ser:
                                                     <% out.println(foo.Counter.getCount());                   %>



                                                                      Il.~           . fVl'fcitJl'ltU".
                                                                      1"f3eJl'IJ. V ai




  286   ca(,~ítwro   7
usando         o JSP




  Mas você PODE
incluir declarações
 import num JSP...
   basta ter uma
      diretiva.
       C>
      O




                 Use a diretiva de págitla para itMportar pacotes
                 A diretiva é um recurso que você tem para dar instruções especiais ao
                 Container no momento da tradução da página. As diretivas vêm em três
                 sabores: page, include e taglib. Nós veremos as diretivas include e taglib nos
                 próximos capítulos. Por enquanto, nossa preocupação será com a diretiva
                 page, porque ela é a única que nos permite importar.
                 Para importar um único pacote:
                      <%@ page
                                                                                        f.s-t-a   é vh'la                   ptl.Je
                                   'import="foo. *"                %> '-(----           C"'h'I Vh'I     J.       J      ------y
                                                                                                      fJ.-rl"tbvró tlrlpl:il"r.
                      <html>
                      <body>                                                            (Obsel"ve 3ve         #fã",   1.:
                      The page     count    is:
                                                                                        #fel1t.VIt'Ip.m-t-.re-v{,.jVifJ.         11/J
                      <%
                                                                                                '/4
                                                                                        tli711.1 di're.f.tV4).
                           out.println(Counter.getCount(»)                          ;

                      %>                                                        
                      </body>
                      </html>                                                       Os scrlh-t-Ie.f.s
                                                                                            r               sã", Jtlva

                                                                                    l1",rh'lal:S-~l"'j4.) -t-6'/fJ.S as
                                                                                    decl41"l~f;e:s e:1t'I VIt'I scriphe-t-
                                                                                    devel!l1 -I-erh'lli7ar C<ll1!l1 Vh'I

                 Para importar múltiplos pacotes:                                   p61'1-t-c-e-v:l"jVIQ.!
                      <%@ page import="foo.*,java.util.*"                               %>

                                                             1',
                                           ti se   VI!l1Q.   VlrjvllA parti         separlAl" .os pIAC6-1-eS.
                                           II:S--t-a1i1-1-etra '/e pll.CfJ-I-es vel!l1fl'1-t-re



                 Reparou a diferença entre o código Java que exibe o contador e a diretiva
                 de página?
                 O código Java vem entre os símbolos <% e %>. Mas a diretiva acrescenta
                 um caractere a mais no começo do elemento - o símbolo @ (arroba)!
                 Se você vir um código JSP que começa com <%@, você já sabe que se trata
                 de uma diretiva. (Nós entraremos em maiores detalhes sobre a diretiva de
                 página mais adiante.)




                                                                                                  você está             ~       287
usando expressões



Mas etlt seguida Kitlt tltetlciotla as "expressões~~
Justo quando você pensou que fosse seguro, o Kim percebe
o scriptlet com uma declaração out.printlnO. Isto é JSP,
pessoal. Grande parte da razão do JSP é evitar o printlnO! É
por isso que existe um elemento expressão no JSP - ele exibe
automaticamente aquilo que você colocou entre as tags.




             Você não precisa dizer out.
             printlnO em um JSP! Basta
                usar uma expressão ...



                                     o código          script/et:

                                           <%@   page import="foo.*"         %>
                                           <html>
                                           <body>
                                           The page count is:
                                           <% out.println(Counter.getCount());                   %>
                                           </body>
                                           </html>


                                     o código          expressão:

                                           <%@ page    import="foo.*"        %>
                                           <html>
                                           <body>
                                           The page count is now:
                                           <%= Counter.getCount()           %>
                                           </body>
                                           </html>
                                                                I"f It expJ"esst'uJ'" e'"ífJi'tds cClJ"-ra
                                                                                                         J         I
                                                                                                              - I1IJS

                                                                pJ"edsfJ.ífJi'lJs escJ"eveJ"       IJ


                                     Notou a diferença entre a tag para o código scriptlet e a tag da
                                     expressão? O código scriptlet vem entre os sinais de porcentagem
                                     <% e >%. Já as expressões recebem um caractere adicional no
                                     início do elemento: um sinal de igual (=).
                                     Até agora nós já vimos três tipos diferentes de elementos do JSP:
                                                 Scriptlet:           <%          %>
                                                 Diretiva:            <%@         %>
                                                 Expressão:           <%=         %>




288 capftuio 7
usando oJSP




                           O;;Je es+: ó po;;+ó-e-v!rjVla?
                               J
    <%= Counter.getCount()       %>




 As expressões se tOl11atM o argUtMettto                 para UtM
 out.prittt()


 Em outras palavras, o Container carrega tudo o que você
 digita entre <%= e >% e acrescenta como argumento para uma
 declaração que exibe para a resposta implícita out do PrintWriter.

  Quando o Container encontra isso:
    <%~ Counter.getCount()       %>




  Ele o transforma nisso:
    out.print(Counter.getCount(»);




 Se você colocou mesmo um ponto-e-vírgula
 na sua expressão:
    <%= Counter.getCount();         %>




  Isso é mau. Significaria isso:
    out.print(Counter.getCount();)           ;



                                ,        ~
                             'x.l!! Is+ó     i1Vl1ca




NUNCA termine uma expressão com um ponto-e-vírgula!
      <%= nuncaColoqueUmPontoEVírgulaAqui                       %>
      <%= porquelstoÉUmArgumentoParaPrintO                      %>




                                                 você está        ••   289
expressões   e diretiva   de página




            N&9 exIstem

feth'untas Ídl9tas
                                                      Diga quais das seguintes expressões são
                                                      válidas, ou não, e por quê. Nós não abordamos
Y:    Bem, se você tem que usar as                    todos os exemplos aqui; portanto, use a sua
expressões EM VEZ DE colocar o out.printlnO
                                                      imaginação, baseado no que você já sabe sobre o
em um scriptlet, então por que existe um
                                                      funcionamento das expressões.
"out" implícito?
                                                      (As respostas estão mais adiante neste capítulo;
                                                      então, faça o exercício AGORA).
I:implícitaprovavelmente sua página JSP, mas
out
     Você
             de dentro da
                           não usará a variável
                                                      Válido? (Verifique se é válido ou não,
você pode passá-Ia adiante ... alguns outros
objetos que são parte da sua aplicação não têm        justificando quando não for.)
acesso direto ao stream de saída de dados da
                                                         0<%=     27%>
resposta.


f:   Em uma expressão, o que acontece se o
método não retomar coisa alguma?                         0<%=     ((Math.randomO   + 5)*2); %>

I: Você receberá     um erro!! Você não pode,
                                                         0<%=     "27"%>
e NÃO DEVE, usar um método com um tipo de
retorno void como uma expressão. O Container
é esperto o suficiente para descobrir que não
haverá nada a exibir se o método tem um tipo             0<%=     Math.randomO %>
de retorno void!


Y:    Por que a diretiva import começa com
                                                         0<%=     String s = "foo" %>
a palavra "page"? Por que é <%@ page
import %> em vez de simplesmente <%@
import %>?                                               0<%=     new String(3]) %>


I: Boa pergunta! Em vez de possuir uma                  0<%     = 42*20; %>
enorme pilha de diretivas, a especificação
JSP tem apenas três diretivas, que podem ter
atributos. O que você chamava de "a diretiva
import" é na verdade "o atributo import da diretiva       0<%=    5>3 %>
da página".


Y:     Quais são os outros atributos para a
                                                          0<%=    false %>
diretiva da página?

I: Lembre-se,    a diretiva da página é para dar         0<%=    new CounterO %>
ao Container a informação de que ele precisa
quando traduz seu JSP para servle1. Os atributos
que nos importam (além do import) são: session,
content-Type e isELlgnored (falaremos deles
mais adiante neste capítulo).

290 capítulo 7
usando    o JSP


KiiM solta a bOiMba fi"al...




            C>
           o


                                 Humm... eu sei que o JSP se
                                  transforma em um servlet.
                               Então, talvez eu possa declarar
                                uma variável contadora em um
                               scriptlet que transformar-se-ia
                                numa variável no servlet. Será
                                        que funcionaria?

                                           D
                                          O




                                                           o que ela tentou:
                                                           <htrnl>
                                                          <body>
                                                          <% int count=O; %>
                                                          The page count is now:
                                                          <%= ++count %>
                                                          </body>
                                                          </htrnl>



                                                           Isto vai compilar?
                                                          Vai funcionar?




                                                                     você está     ~    291
variáveis scr~[)tíet



l1eclarat1do uita variável eit Uit scriptlet
A declaração da variável é válida, mas não funcionará conforme Pauline esperava.

o que ela tentou:
                                        .~         N                                        ~
                                        NtlS I1Q4pt't;ClSQIi4S i'I'y>tlf'T"fi.t' P/4JQ; f.P/T"Q4P/IJ$
                                                                                                             ~   I
                  <htrnl> ~.f>tlI41i(J$                 fi.   Jlt'e-ftv4     tia P~i"'fl,.
                  <body>
sct'ifJ,~         <% int     count=O;      %>~                                          I
                  The page count is now:                        lJedl3.t'Q   fi.   v4F'ttJ.lIef cdP/.fQdót'4 •
            .----* <%= ++count     %>
flfpt'es    SIM
                  </htrnl>
                  </body>     ~                  -r                         I
                                                 J..p/ct'elie"T"a 4 VfJ.t'ltJ.lle!ctmT"adlJt'13.
                                                                 J                                 !
                                                 fi:   exl!le ti IIlJ,lóf'.




o que ela viu na primeira vez que abriu a página:



                  The page count is: 1




o que ela viu na segunda, na terceira                            e em todas as outras vezes em que ela abriu
a página:
usando    o JSP



o que REALMENfE acomece                    COtlt   o seu código JSP?
Você escreve um JSP, mas ele vira um servlet. A única maneira
de saber realmente o que está acontecendo é ver o que o
Container faz com o seu código JSP. Ou seja, como o Container
traduz o seu JSP em servlet?
Uma vez que você saiba onde os diferentes elementos do JSP se
encontram no arquivo de classe do servlet, você achará muito mais
fácil de saber como criar a estrutura do seu JSP.
 O código do servlet nesta página não é o código verdadeiro gerado
 pelo Container - nós o simplificamos e aproveitamos o essencial.
 O arquivo do servlet gerado pelo Container é, digamos, mais
feio. O verdadeiro código-fonte do servlet gerado é um pouco
 mais dificil de ser lido, mas nós o veremos nas próximas páginas.
 Contudo, por enquanto, o que nos interessa é onde o nosso código
 JSP realmente termina na classe servlet.


Este JSP:                                 Torna-se este servlet:
                                          public class basicCounter_jsp                   extends
                                          SomeSpecialHttpServlet   {

                                          public void    jspServlce(HttpServletRequest      request,
                                             HttpServletResponse    response)throws    java.
                                             io.IOException,
                                                       ServletException     {

                                          PrintWriter   out = response.getWriter();
                                          response.setContentType("text/html");
    <html><body>                        ~ out.write("<html><body>");
    <% int count=O;      %>----------~.int     count=O;
    The page count is now :-----~      out. wri te ("The page count                      is now:");
    <%= ++count %>---------------ãpout.print(        ++count );
    </body></html>-------------~.out.write("</body></html>");
                                                                                                                   I
                                                                   O CM-/-oJnel' c"IIJCil. /-l:Jtl.a cótl.ij"
                                                                                         -         lJ
                                                                    e"'" v"'" "",:J..ótl."sel'lIi'ce
                                                                    PePlse PIe/e C<:l""''' v"'"
                                                                     tl.tJbe-/-1 tl.lJ~s-/- ~ve



                                TODOS os códigos do scriptlet e das
                              expressões ficam em um método service.
                           Isto significa que as variáveis declaradas em
                            um scriptlet são sempre variáveis LOCAIS!




          JlJ 1;"",ca.j.jvocê sVi"sel' checal' ô cttl.fjlJ Jô sel'vle.f. jel'aJô tJ.1'((I'.f.ir
          AI".f.tJ.:Se V~4 e"",H'JI',:elJ'i"PlJSev1;irlca..f.!WIJl'k! Ca.f.ali'PlfJ.!

          AliJirlePI!JSevSel'vMtJl' (AJ.'irlebtJ.SvaApli'co.{ió!      IJ1'5! 4p4ct.e;Jsp.          (Os nlJirles
          svbl,i,t.IJ.JêJS irlvJI<I''i,,; JepenJenJIJ   JIJ sev sts.feirlt.(   ti!   Jfi. SVfJ.IJ.f1i'clJ.g'i,,)


                                                                                                você está aqui..         293
declarações JSP




            D
           o
                  PrecisatMos de outro e1etMettto JSP ...
                  Declarar a variável contadora no scriptlet nos mostrou que a
                  variável foi reinicializada cada vez que o método de serviço
                  rodou. Quer dizer que ela foi reiniciada para Oa cada solicitação.
                  De alguma forma, precisamos tomar count uma variável de
                  instância.
                  Até agora, nós vimos as diretivas, os scriptlets e as expressões.
                  As diretivas são para instruções especiais para o Container, os
                  scriptlets são Java simples localizados dentro de um método
                  service do servlet gerado, e o resultado de uma expressão sempre
                  se toma o argumento para um método printO·
                  Mas existe um outro elemento JSP chamado declaração.


                     <%!    int
                        j

                  As declarações JSP servem para declarar membros da classe do
                  servlet gerado. Isto significa as variáveis e os métodos! Portanto,
                  tudo que estiver entre a tag <%! e %> é adicionado à classe fora
                  do método service. Logo, você pode declarar os métodos e as
                  variáveis estáticas e de instância.




 294 capítulo 7
As declarações JSP
Vma declaração JSP é sempre definida dentro da classe, mas fora do método service (ou qualquer outro).
E simples assim: as declarações servem para as variáveis estáticas e de instância e para os métodos. (Na
teoria, sim, você poderia definir outros membros, incluindo as classes internas, mas em 99,9999% das
vezes você utilizará as declarações para os métodos e as variáveis.) O código abaixo resolve o problema
de Pauline; agora, o contador é incrementado cada vez que um cliente solicitar a página.

A Declaração da Variável
Este JSP:                             Torna-se este servtet:
                                     public   class    basicCounter        jsp extends          HttpServlet             {




                                          public void         jspService(HttpServletRequest

                                 Gintrequest,
                                               count=O;
                                                                         HttpServletResponse


   <html><body>
   <%! int count=O; %>       J       response)throws   java.io.IOException
                                              PrintWriter                     {
                                                            out = response.getWriter();
                                              response.setContentType(~text/html");
   The page count is now:
                                              out.write(~<html><body>");
   <%= ++count %>
                                              out.write(~The   page count is now:");
    </body></html>

                                               out.print(
                                               out.write("</body></html>");
                                                           ++count ); ~                                 .~
                                                                                                               '

                                                                              1Jfs-+-a VfjJ fs-+-all'liJS-
                                                                              tl'Jcl"fll'le"';-tl.I'JJ" lIlI'l~

                                                                              Je   li1s-+-';"ci'a
                                                                                      E
                                                                                                        ell'l vej Je lIlI'lfll
                                                                              vai"lfJ.Velltlcal,


A Declaração do Método
Este JSP:                         Torna-se este servtet:
                                  public   class    basicCounter      jsp extends         HttpServlet               {

                                       -nt doubleCount()   {
                                          count = count*2;
    <html>
   <body>                                  return    count;            alie
                                       }
   <%! int doubleCount()   {
          count = count*2;             int count~l;~
          return count;                                         é
                                                        Is-l-e ~ Java.; eP'l.fió) selll fl'ób1ellltJ.S 3vu'I'J-I-
                                                                                                    N                   ••

                                                        referel1cfu,s de f ••/'ward (ofedlu'fJ.JlJ.tJ  .lu,
    %>
    <%! int count=l;    %>                              !JíPOI:5 Sue l/ecê U, u-/-NtYJiE        e'1II   VIII hlé-l-fJdc),
    The page count is now:            public void     ]spService(HttpServletRequest    request,
    <%= doubleCount() %>                    HttpServletResponse     response)throws  java.
    </body>                       io.IOException   {
    </html>                                PrintWriter   out ~ response.getWriter();
                                           response.setContentType(~text/html");
                                           out.write("<html><body>");
                                           out.write("The    page count is now:");
                                           out.print(   doubleCount()    );
                                           out.write("</body></html>");




                                                                                        você está
o servlet gerado



Hora de ver o VERUAUEIRO servlet               gerado
Estávamos vendo uma versão bem simplificada do servlet que o Container realmente cria a partir do
seu JSP. Não há necessidade de se ver o código gerado pelo Container durante o desenvolvimento,
mas você pode usá-Io para ajudá-Io a aprender. Uma vez que você veja o que o Container faz com
os diferentes elementos de um JSP, você não precisará mais ver os arquivos-fonte .java gerados pelo
Container. Alguns fabricantes não deixarão que você veja a fonte Java gerada, mantendo apenas os
arquivos .class compilados.
Não se intimide quando você notar partes da API que você não conheça. Os tipos de classe e interface
são, na maioria, implementações específicas do fabricante que você não deve se preocupar.




o que o Container          faz com o seu JSP

~ Olha as diretivas, em busca de informações de que ele
  possa necessitar durante a tradução.

~ Cria uma subclasse HttpServlet.
  Para o Tomcat 5, o servlet gerado estende:
   org.apache.jasper.runtime.HttpJspBase
                                                                Nós estam os mostrando o código
~ Se houver uma diretiva de página com um atributo              gerado de forma que você possa
  import, ele escreve as instruções do import no topo do        entender como o JSP é traduzido
  arquivo classe, logo abaixo da declaração do pacote.        para o código servlet. Mas você
   Para o Tomcat 5, a declaração do pacote (com a qual        não precisa saber em detalhes como
   você não deve se preocupar) é:                             um determinado fabricante faz isso
  package org.apache.jsp;                                     e nem a aparência verdadeira do
                                                              código gerado. Tudo o que você
~ Se houver declarações, ele escreve-as no arquivo classe, precisa saber é como se comporta
  geralmente logo abaixo da declaração da classe e antes • cada tipo de elemento (scriptlet,
  do método service. O Tomcat 5 por si só declara uma         diretiva, declaração, etc.) e como
  variável estática e um método de instância.                 aquele elemento funciona dentro do
                                                              servlet gerado. Você precisa saber,
~ Cria o método service. O nome real do método              : por exemplo, que seu scriptlet pode
  é _j spService (). Ele é chamado pelo método                usar objetos implícitos, e você precisa
  ativado serviceO da superclasse do servlet e recebe o
                                                              conhecer os tipos de objetos implícitos
  HttpServletRequest e o HttpServletResponse. Como            daAPI Servlet. Mas você NÃO
  parte da construção desse método, o Container declara
                                                              precisa conhecer o código usado para
  e inicializa todos os objetos implícitos. (Você verá mais
  objetos implícitos quando mudar de página.)                 disponibilizar tais objetos.
                                                              A única coisa que você precisa saber
~ Mistura o HTML simples (chamado template text) com os: sobre o código gerado são os três
  scriptlets e as expressões no método service, formatando: métodos do ciclo de vida do JSP: jsplnitO,
  tudo e escrevendo no PrintWriter da resposta.            : jspDestroy e -.JspServiceO. (Falaremos
                                                            .
                                                           ~ sobre eles ainda neste capítulo.)
                                                            .
                                                            ...........................................




296   capítulo 7
usando     o JSP


A classe gerada pelo Tomcat 5                                                                                <html><body>
  package                  .
              org.apache.]sp;                  Se você -hvel' /T "'~I'·h
                                                               ,.•••   tio.                                  <%! int count=O;     %>
  import    javax. servlet. *;                 tiil'e-hv!l:!e      pD.Jíi"""J,eles".                         The page count is now:
  import    javax. servleLhttp.   *;       ~~l!1.l'eCer46 4'1pt(,,6S "46, +e_s                               <%== ++count %>
  import    javax. servlet. jsp. *;            "JI!11t.VIYo,   Iw.p~r+ J'II!S+ei.JSP>.                       </body></html>


  public    final class         BasicCounter_jsp    extends org.apache.jasper.runtime.HttpJspBase
                                         implements   org.apache.jasper.runtime.JspSourceDependent



      int count=O;
      private          static   java.util.Vector         jspx~dependants;
                                                                      O Ca"+IlIPier          ca!t:,c4   4S   suAs
      public java. util. List getDependants
        return  jspx_dependants;                                () {tie;,+r6
                                                                         I"     tias +4itS <%/ %» N
                                                                      PI'<JPf't4S d4tXtJ tia tieclaf'IJJaa

     public       void _jspService(HttpServletRequest                           request,           HttpServletResponse
  response)
                                                throws                            java.io.IOException,
  ServletException
         JspFactory    jspxFactory   = null;
         PageContext   pageContext   ~ null;
         HttpSession   session = null;
         ServletContext    application  ~ null;
         ServletConfig config = null;
         JspWriter out = null;
         Object page = this;
         JspWriter    jspx_out = null;
         PageContext    jspx_page context      null;

            try  {
               jspxFactory    = JspFactory.getDefaultFactory();
              response.setContentl'ype("text/html");
              pageContext   =   jspxFactory.getPageContext(this,                                    request,        response,    null,
   true.    8192, true);
               jspx pagecontext     = pageContext;
              ;;-ppli~atio:;;: pageContext. getServletContext
                            =                                                              (); A»11t ele +e~4 inicia!i;").;' as
              config = pageContext. getServletConfig ();                                       a~e+"s    11ty>11!:t+as.
              session = pageContext.getSession();
              out = pageContext.getOut();
               jspx_out ~ out;
              out.write("r<html>r<body>r");
              out.write("rThe    page count is now: r");
              out.print(   ++count );
              out.write("r</body>r</html>r");
              catch (Throwable t) {
               if (! (t instanceof    SkipPageException){
                  out = jspx_out;                                                              I
                  if    (out != null && ouLgetBufferSize()                             != O) !clar"zveatsóp"tietio.rerf'flltió         •••
                         out.clearBuffer();
                if ( ]spx_page           context      1= null)             jspx_page           contexto
   handlePageException(t);
                  }

          } finally {
             if ( jspxFactory            != null)         jspxFactory.releasePageContext(                              ]spx_page~
   context);
       }




                                                                                                               você está
objetos implícitos do JSP



    A variável out não        é o único objeto itMplícito
                                                        ...
    Quando o ContaÍner transforma o JSP em um servlet, o começo do método
    service é uma pilha de declarações de objetos implícitos e atribuições.
    Com os objetos implícitos, você pode escrever um JSP, sabendo que o seu
    código fará parte de um servlet. Em outras palavras, você pode aproveitar
    as suas características de servlet, mesmo que você não esteja escrevendo
    diretamente uma classe servlet.
    Lembre-se dos capítulos 4,5 e 6. Quais foram alguns dos objetos
    importantes que você usou? Como o seu servlet conseguiu seus
    parâmetros init? Como o seu servlet obteve a sessão? Como ele conseguiu
    os parâmetros enviados pelo cliente em um formulário?
    Estas são algumas das razões que seu JSP pode precisar para usar alguns
    dos recursos disponíveis para o servlet. Todos os objetos implícitos
    apontam para algum item daAPI Servlet/JSP. O objeto implícito request,
    por exemplo, é uma referência ao objeto HttpServletRequest, passado
    para o método service pelo ContaÍner.



                       AP.
                 JspWriter

      HttpServletRequest

     HttpServletResponse

               HttpSession                      session

           ServletContext
                                                application                 '"                  é
                                                                    'l.s+e óbid-ó 'hy>I:Cl+ó disp~JI1:vel ~f.ep!~s/
                                                                                                                .•..
             ServletConfig                      config              p41'a pI.!Jll'l4Sde f!1'1'6detll'litl4s. ~ce Vel'4
             JspException                       exception   ~       lSSIJ 1Pl41$ al'de)
                                                                               +
               PageContext

                     Object                     page
                                                pageContext     ~    "

                                                            IJIPl~l.!JeCó~x+      eJOlc4pslI!o.  CII+1'6$ atJe+cs
                                                            1hy>I,cttas. A-ssi~ se vóce pll,SSQI' IIIPlIl,
                                                            l'elel'e'1C1~ Pl.!JeCc~x+        o. 'f,5l/1Pl tJe+4 t.elpel'j
                                                                                                        4
                                                            ele ptAdf.NI l/S41' es so. I'e-lel'el'lct~ p~l'o. tJb+e,.
                                                            I'elel'ê-,cl~s pU·o. ()trrJetJS ctJe+cs t""Pl:Cl+tJSe
                                                            a+dIJII+ó$ de +ad4s tASescapas.




    r:   Qual é a diferença entre um JspWriter e um
    PrintWriter que eu recebo de um HttpServletResponse?

    R:    Não muita. O JspWriter É UM PrintWriter com algumas
    funções de buffer. O único momento em que você deve
    realmente dar maior atenção a ele é quando você estiver
    criando tags customizadas. Portanto, falaremos um pouco a
    respeito das habilidades especiais do JspWriter no capítulo
    que aborda o desenvolvimento das tags customizadas.



I   298   capítulo 7
Exetcíc'l9S                Cada um d9Sttecb9s vem de umJSY. Seu
                           ttabalb9 setá desc9btlt 9 '1ue aC9nteootá
                            '1uand9 9 C9Iltalnet tentar ttanst9tmat 9
                             J S Y num setVlet. O C9ntalnet setá
                                          cap~ dettaduz,'lt 9 seulSY
                                          em um c9d'lg9 setvlet legítlm9
                                          e c9mp'llável? Se nã9, p9t
                                          '1ue? Em CClS9 t'ltmatlv9, 9
                                                        a
                                      '1ue aC9nteoo '1uand9 um cl'lente
                              aoossat 9 JSY?

o   <htrnl><body>
    Test scriptlets ...
    <% int y=5+x; %>
    <% int x=2; %>
    </body></htrnl>




    <%@ page irnport="java.util.*"   %>
    <htrnl><body>
    Test scriptlets ...
    <% ArrayList  list = new ArrayList(
       list.add(new  String(ftfoo"));
    %>
    <%= list.get(O)   %>
    </body></htrnl>




e   <htrnl><body>
    Test scriptlets ...
    <%! int x ~ 42; %>
    <% int x = 22; %>
    <%= x %>
    </body></htrnl>




                                                           você está
exercícíos JSP


            ~
            Imã de Gehtde'h'q ([este Ytepéttflt9tl9)
            Estude o cenário (e o restante nesta página) e coloque os
            ímãs no JSP para criar um arquivo legítimo que produziria
            o resultado correto. Você não deve usar um ímã mais de
            uma vez e nem usará todos eles. Este exercício supõe que
            existe um servlet (que você não precisa ver) que recebe
            a solicitação inicial, associa um atributo no escopo da
            solicitação e encaminha para o JSP que você está criando.

            (Nota: nós chamamos este exercício de "Ímã de Geladeira
            (Teste Preparatório)" em vez de "Ímã de Geladeira", pois a
            prova está repleta de perguntas "arrastar e soltar" como esta).


Objetivo do Projeto
    Criar um JSP que produzirá isto:



!The friends who share your hobby of extreme knitting are:

IFred
lPhilippe
I
                                                                Ui           I O texto   "extreme knitting" vem de um

                                                                               parâmetro do formulário de solicitação.
                                                                             ! seu JSP. O servlet obtera a sohcltaçao
                                                                             ! primeiro (e então a encaminhará ao JSP),
.
l.pradeep ~                                                                  . mas precisa receber es~e par~~etr~ do
                                                                             ;•.Vocêisto não muda a forma como você
      Os três nomes vêm de uma ArrayList de                                     receberá o parâmetro no seu JSP.
      atributos da solicitação, chamados "names".
      Você terá que receber o atributo do objeto
      solicitação. Considere que o servlet recebeu
      esta solicitação e configurou um atributo no
      escopo da mesma.              Zsra   J                   a
                                         vle.f- 311e eCll'ltij(,ll'4
                                    "e •.•
                                    6   a.f-I'l!II./7<;   $<;ll"el-+8.J';6
                                                                             Conselhos e dicas importantes
O formulário HTML                   e tÁeplJls ePlcelíI'Ililho.
                                                                             ~ O atributo da solicitação é do tipo java.
    <form method~"POST"             JSP 311e V••ee      es.f-:                 util.ArrayList.
    <html><body>              ç..   « $<;líCl.f-a{õ.a farei 6
                                    eSCl'evel'/tÁ6.
        action~"HobbyPage.do">
        Choose a hobby:<p>
                                                                             ~ A variável implícita para o objeto
                                                                               HttpServletRequest é chamada de
        <select   name=NhobbyJ'.f size="1">                                    request e você pode usá-Ia em scriptlets
          <option>horse      skiing                                            ou expressões, mas não em diretivas
          <option>extreme      knitting                                        ou declarações. Independentemente
          <option>alpine      scuba                                            do que você fizer com um objeto
          <option>speed      dating
        </select>
                                                                               solicitação em um servlet, você o fará
       <br><br>
                                                                               dentro do seu JSP.
       <center>
         <input type="SUBMIT">                                               ~ O método servlet do JSP pode processar
      </center>
                                                                               os parâmetros request, pois lembre-se,
     </form>
    </body></html>
                                                                               seu código vai estar dentro do método
                                                                               service do servlet. Você não precisa se
                                                                               preocupar com o método HTTP(GET
                                                                               ou POST) que foi usado na solicitação.

300               7
usando o JSP



Nós colocamos algumas linhas para você. O código
que você colocar neste JSP DEVE funcionar com o
código que já está aqui. Quando você tiver terminado,
ele deve ser compilável e produzir o resultado na
página anterior (você deve CONSIDERAR que já
exista um servlet funcionando, que primeiro recebe
a solicitação, configura o atributo "names" da                PARE
solicitação e encaminha a solicitação para esse JSP).             .       exercCO
                                                             ~O   e u'"
                                                        Este ~pCona.~ sobre a
                                                               o    rçao
                                                        É parte da         JSP
                                                             Sntaxe do




      The fríends   who   share   your hobby   of




      are:   <br>




      <% Iterator   ít     alo íterator ();




                                                                          você está     ~   301
respostas dos exercícios



           SEJA 9 C9ntUnet
               Iesp9sta5       O nQ 2 é fácil de entender e funciona. O nQ 1 é uma questão básica da
                                linguagem Java (usar uma variável local antes que ela seja declarada)
                                e o nQ 3 também demonstra uma questão básica da linguagem Java
                                - aquilo que acontece quando você tem uma variável local e de
                                instância com o mesmo nome. Então veja ... se você traduzir o código
                                JSP no código Java do servlet, você não terá problemas em descobrir
                                o resultado. Uma vez que o conteúdo do seu JSP estiver dentro do
                                servlet, isso é Java.
                                                             /
                                 ís+e J'jãó ir:              í
                                                   CÓJJy>lftU"/ exahl>le~            C<ll>l,{l   escrever


o     <htrnl><body>
      Test scriptlets ...
      <% int y=5+x; %>
                                 V/tl /tlé+ódl.l ca/tl;



                                                   ,~            lf9c~es+:    +e,,+aPld<l vsar a vt<r,-tvel
      <% int X=2i %>
                                                  xJ               x     A-Alrf.,5 Zll'i! ela s!:ia Jef;#jiGla. A-
      </body></htrnl>
                                                                 lii15vt<5el>lJt<Vll "lã", perl>l,"-k iSslJ e IJ
                                                                 c.cl1+IJ.,#jer "Iãc se ,i1C,{l/tlcdfJ. /tl N!liif'rlll>lfl.r
                                                                                                      e
                                                                 a <lr",!!1>I   "ti sev    C:diJ6 scrij>+le+.




      <%@ page import="java.util.*"    %>
      <htrnl><body>                                                        scriptlets ... foo
      Test scriptlets ...
      <% ArrayList  list = new ArrayList();                                -;el>l pr<l!;le/tlt<s; exl!;e ., pf'l"'elf'õ    (e
         list.add(new  String(~foo"));                                     1I1'J1Có) ~e+-ó
                                                                                   ó              da /}N,L.lS.f.
      %>
      <%= list.get(O)      %>
      </body></htrnl>




e



302   capítuio 7
usando o JSP



                ~                                 Se a sua resposta parecer um pouco
                Imã de &lade'ita                  diferente e você ainda acreditar que ela
                                                  deve funcionar - tente! Você terá que
                Resp9staB                         fazer o servlet que carrega o formulário
                                                  de solicitação configurar um atributo e
                                                  encaminhar (despachar) a solicitação
                                                  para o JSP.




B8                   ímport="java.util.*"~1i:J                AJ:s fl"eci'sahics     da dll"e.f.lV4    de f:.slP;a i'IIV>ÓI"Ij

                                                                                                     d4 I./-el"a..f<IfJI".
j <html><body>        r
                                                               p41" C4t1SadalJrl"l",Lts..f       e




The friends         who    share   your   hobby   of


1<%= 1 request.' getParameter ("hobby"l ~
   I




are: <br>


EJIArraYLíst~~               [:]   I(ArraYLístlUrequest·1           IgetAttríbute("names"ll          O~
<%   Iterator it = aI. ~terator (); ~
          ______
                                                          -r ..              . I"e-r 4~tll •
                                                          .L,.p;ICre C SCI"IP"'-'
                                                                                   I       •••

IWhilell(ít.hasNext(»lE3~

,<%= 11   í t. next () l  a~                      e {j fiYtalt;e o.ôtlt•
                                    Use tlhi4 eXfl"ess';e.

<br>

<% } %>
               l.p;cel"l"e c blccc de Icep    w"'l!e! (Se vccê
               eS3t1ecel" i's.f.c) ele P;';c c<:JlIV>t/al":)




                                                    ímport

                                                                                                     ("names")



                                                                                                 você está
expressões válidas      a inválidas


u~co~etttário...
Sim, você pode colocar comentários no                   A.P9nte seu lápIS
                                                                  Respostas
seu JSP. Se você é um programador Java
com alguma experiência em HTML, você          As Expressões Válidas e Inválidas
pegar-se-á digitando:
                                              Válidas?
// isso é um comentário
                                                 lZ <%=; 27 %>
sem pensar duas vezes. Mas se você o fizer,
                                                   1;das as Ir.ferats              f'I',,,,rftvas          valeli<l,
a não ser que esteja dentro de um scriptlet
ou em uma tag de declaração, você acabará
EXIBINDO isso para o cliente como parte          o <%=; ((Math.randomO                          + 5)*2); %>
da resposta. Portanto, para o Container
                                                   AJfi() / () p~;;f<l-e-V(l'j(/lt<              1'/';<1   ptlde es+al'   11$11",
aquelas duas barras são simplesmente mais
texto, como "Olá" ou •• E-mail é:".             lZ <%=; "27" %>
Você pode colocar dois tipos diferentes de
comentários em um JSP:                             /1r S+I't'í'l5 1".feNJ.I            é 1I~!tfia,

                                                lZ <%=; Math.randomO %>
~ <!-- comentário HTML -->                         Si"';   D li<lé-l-6dD       1'e+61'11t1. Uli<lo. c:1' •• ..
                                                                                                          o

   O Container passa isso diretamente
   para o cliente e o browser o interpreta
                                                o <~=;        String s =;"foo" %>
   como um comentário.                             AJf.}O/ ~cê 1'/41) ade .fel' """li declaras';"
                                                                        p
                                                   de vadfJ.llel "3"''''


~ <%-- comentário JSP --%>                      lZ <%=; new String[3] ) %>                                     ,.

   Estes são para os desenvolvedores de            S'''''J.pDI'
                                                   t:lIJ I'f:       Je.
                                                                          <I0,1'1"" I'/ew S+r''í'l5 e VIi<l atJe+ó e
                                                                           ~tJe+" p~de seI' e"llll"tldD p{(l'a y""a
   páginas e, tal qual com os comentários          decftu'o.S';" prtn+ll1Ú.
   Java em um arquivo-fonte Java, eles
                                                0<%        =; 42*20· %>
   são tirados da página traduzi da. Se
   você estiver digitando um JSP e quiser           AJfi()/    f.} al',~""é-hcfJ. es+: bt>fJ.Ji<las J.: tlli<l
                                                                                                  I
   adicionar comentários da maneira                esptJ.fD e'1+l'e õ %       fi: " "', AJ';c f<lde seI' <% "')

   como você os usaria em um arquivo-              .fe""   3t1e seI' <%=.
   fonte Java, use um comentário JSP.           lZ <%=; 5 > 3 %>
   Se você quiser que os comentários               CItJ.I''') p<ll' seI'       YIi<l   btMllo'l'/D) extile +rve.
   façam parte da resposta HTML que
   vai para o cliente (embora o browser
                                                lZ <%=; false %>
   não os mostrará ao cliente), use um
   comentário HTML.                                 ~
                                                   AJ:sJ: ,. dtsseli<les 3"'e o,s Il.fel'fl.f"$ pr,,,,t+rllt<s
                                                   St<Dvalfila$'.

                                                lZ <%=; new CounterO %>
                                                  Seli<lpr<l/!Ie •••a. Is+e     é IU(tJ.+a•••el'l.fe
                                                  S+I'I'í'I      ••• Ir~ ext/! •• e N!sv!+o.d6
                                                                                I'                                   de
                                                  +6S                 d<l otJe+""




304   C8j'Jít1Jlo   7
usando o JSP



A API para o servlet gerado
o Container   gera uma classe a partir do seu JSP, que
implementa a interface HttpJspPage. Esta é a única
parte daAPI do servlet gerado que você precisa
saber. Não se incomode se no Tomcat, por exemplo,
a sua classe gerada estenda:
org.apache.jasper.runtime.HttpJspBase

Tudo o que você precisa saber são os três métodos
                                                                        <<interface> >
pnnCIpaIS:
                                                                  javax.servlet.jsp.JspPage
                                                         jsplntQ
                                                         jspDestroyQ
~ jspInitO
   Este método é chamado pelo método irritO.
   Você pode anular este método. (Você consegue
   imaginar como?)
                                                                          <<interface> >
                                                                 javax.servlet.jsp.HttpJspPage
~ jspDestroyO                                             -.JspService(HttpServletRequest,    HttpServlet
                                                                             ""
   Este método é chamado pelo método destroyO do
   servlet. Você também pode anular este método.                    4cê MfJrO POJ)í     Q#'}lIl,u" es+ef




~ -ispServiceO
   Este método é chamado pelo método serviceO
   do servlet, o que significa que ele roda em
   uma thread separada para cada solicitação. O
   Container passa para este método os objetos
   Solicitação e Resposta.
   Você pode anular este método! Você não pode
   fazer NADA por sua própria conta neste método
   (exceto escrever o código que vai dentro dele),
   e é responsabilidade do fabricante do Container
   aceitar seu código JSP e adaptar o método
  jspServiceO que irá utilizá-Ia.
                                                                 Observe o underscore
                                                                 no início do método -
                                                                 jspService()
                                                     Ele NÃO aparece no início dos outros dois
                                                     métodos jsplnitQ ejspDestroy(). Faça ~e d
                                                     conta q~e o underscore no início do meto o
                                                     significa "não toque"   !               .,.
                                                     Portanto, nenhum underscore no m!ClOdOas
                                                     nome significa que você pode a~~l~-lo. M; ão
                                                      se EXISTIR um underscore no ZnlClO  voce n
                                                      DEVE tentar anulá-Io!




                                                                                  você               !I>    305
ciclo da vida JSP



o ciclo de vida       de   UtM   JSP
Você escreve o arquivo .jsp.
O Container escreve o arquivo .java para o servlet no qual o seu JSP se transformou.



o     Kim escreve um arquivo
      .jsp e o distribui como
                                          o Container "lê" o web.xml (DD) para
                                          esta aplicação, mas não faz mais nada
      parte de uma aplicação.             com o arquivo .jsp (até que ele seja
                                          solicitado pela primeira vez).                      e I;.         I         L I 1_'
                                                                                              l.S-rtl.JlIs-rall1f!"IT"f: (CCllli;ill"C
                                                                                              "lQ sel'vMQI' ••• eSf>/tNJ."Itl.ópeta
                                                                                              salici1-agãl:J          dre"lh.




                                                                          web.xml
                                       Web Container



      o cliente c1icaem um                o Container tenta   TRADUZIR o


         "
      link que solicita o .jsp.           .jsp em código-fonte .java para
                                          uma classe servlet.




                                              ...-- traduz       ~           "",-      gera


                                                                     MyJSP.jsp                   MyJSP jsp.java
                                  Web Container




e                                 o Container tenta COMPILAR o código-
                                  fonte .java do servlet em um arquivo .c1ass.




                                         __     compila      ~                   ___     gera~


                                                                                                    MyJSP jsp.class
                                                             MyJSP jsp.java
                           Web Container




306               7
usando o JSP



o ciclo de vida   do JSP com1ttua...


o                                                o Container  CARREGA a classe do
                                                 serv/et gerada recentemente.

                                                               carrega




                                                                          MyJSP .Jsp.class
                                            Web Container




                      o Container insta o servlet e faz com              o objeto    agora é um servlet
                      que o método jsplnitO dele rode.                   completo, pronto para aceitar
                                                                         as solicitações do cliente .



                                . ..---   jspInitO ~             ..../torna-se~


                                                       MyJSP -Jsp                         MyJSP -Jsp
                     Web Container




                       o Container   cria uma nova thread para
                       tratar a solicitação deste cliente, e o
                       método -JspServiceO do serv/et roda.
                                                                             Tudo o que acontece
                                                                             depois disso é
                                                                             simplesmente a rotina
                                                                             normal do servlet
                                                                             para tratamento de
                                                                             solicitações.
                                                                             Por fim, o servlet envia
                                                                             uma resposta de volta para
                    Web Container                                            o cliente (ou encaminha
                                                                             a solicitação para outro
                                                                             componente da aplicação).




                                                                                você está aqui'"       307
tradução   e compilação




                          A tradução e a cotMpilação acomecetM
                          UMA út1ica vez

                          Quando você distribui uma aplicação com um
                          JSP, toda a etapa de tradução e compilação
                          acontece uma única vez na vida do JSP. Uma
                          vez que esteja traduzido e compilado, ele fica
                          exatamente como qualquer outro servlet. E
                          como qualquer outro servlet, uma vez que tenha
                          sido carregado e inicializado, a única coisa que
                          acontece na hora da solicitação é a criação ou a
                          alocação de uma thread para o método service.
                          Portanto, a figura mostrada na página anterior e
                          nesta é apenas para a primeira solicitação.



                          r:   Tudo bem, quer dizer que somente o
                          primeiro cliente a solicitar o JSP é que leva
                          a pancada. Mas DEVE haver uma maneira
                          de configurar o servidor para pré-traduzir e
                          compilar ... certo?


                          I:   Embora apenas o primeiro cliente tenha
                          que esperar, a maioria dos fabricantes de
                          Container OFERECE uma forma de fazer toda
                          a tarefa de tradução e compilação acontecer
                          antecipadamente, de forma que até mesmo a
                          primeira solicitação aconteça como em qualquer
                          outra solicitação do servlet.
                          Mas cuidado, isso depende do fabricante e não é
                          garantido. EXISTE uma menção na especificação
                          JSP (JSP 11.4.2) que sugere um protocolo para
                          a pré-compilação do JSP. Você faz a solicitação
                          para o JSP anexando uma query string "?jsp_
                          precompile" e o Container pode (caso queira)
                          fazer a tradução/compilação ali mesmo, em vez
                          de esperar pela primeira solicitação real do cliente.




308 capítulo 7
usando o JSP




 Se o JSP se transforma em um
servlet, eu gostaria de saber se
posso configurar os parâmetros
 init do servlet ... e já que estou
  aqui, será que posso anular o
    método initO do servlet ...




                                      Observe estas perguntas. Dê uma olhada nas
                                      páginas anteriores (e capítulos), caso ache
                                      necessário, mas não continue antes de terminar.


                                      Sim, você PODE obter os parâmetros init do
                                      servlet através de um JSP, então, as questões são:

                                      1) Como você os restaurou de seu código? (Grande,
                                          imensa, embaraçosa dica: muito parecido com
                                          a maneira que você o restaura em um servlet
                                          "comum". De qual objeto você normalmente
                                          obtém os parâmetros init do servlet? Ele está
                                          disponível para o seu código JSP?)




                                      2) Como e onde você configura os parâmetros init
                                          do servlet?




                                      3) Suponha que você queira mesmo anular
                                         o método initO ... como você o faria? Há
                                         alguma outra maneira de se fazer e que traga
                                         o mesmo resultado?




                                                                       você está           •.• 309
uítrapassando jsplnít( )



lt1icializat1do seu JSP
Você pode fazer tarefas relacionadas à inicialização do servlet com seu JSP, mas é um
pouco diferente do que você faz num servlet comum.


Configurando os parâmetros init do servlet
Você configura os parâmetros init do servlet para o seu JSP, quase da mesma maneira
que você os configura para um servlet normal. A única diferença é que você tem que
acrescentar um elemento <jsp-file> na tag <servlet>.

   <web-app ... >
     <servlet>                                                           ísrll.
                                                                             J
                                                                                  e
                                                                                   /                             1./           L me
                                                                                       li !.II'/tc(;. , lI.~Vli!li!Jf'rli!rli!J'I7""fI:V*'
                                                                                           /
                                                                                                 II"1'1 ••
                                                                                                                                  .J



       <servlet-name>MyTestlni               t</ servlet-name>           servle}          c,,*,v*,. Pij basictl*,tl1h: tlfl'?pe

          <j sp-file> /Testlni t. j sp</ j sp-file> ~
           <init-param>                                      -I-vJ" Jes-l-t< -I-fAJ ,a;,"I'IQJSp' "" servli-/-
                                                             crraJó '(;1' es+a <:;el'vle-l-> ••
              <param-name>email</param-name>
              <param-value>ikickedbutt@wickedlysmart.com</param-value>
           </init-param>
        </servlet>
      <servlet-mapping>                                                           t,(lIi:1'7Jti
                                                                                              lI"cê JIi!/I"I'Ie*' servle-l- ,b.rt;.
                                                                                                                v
         <servlet-name>MyTestlni         t</ servlet-name>          ~             li*' JSP v"cê Jelle '5l.1a/*,li!l1hJe{tp/i'r
         <url-pattern>/Testlnit.jsp</url-pattern>
      </ servlet -mapping>                                                        v*' sel'v
                                                                                             .l/e-!-           Jti " I. JeJSP
                                                                                                     *,1I.f'el1,i1 i:I f'a;'p/11,
    </web-app>



Anulando o jsplnit()
É simples assim. Se você implementar um método jsplnitO, o Container o chama
no começo da vida desta página como um servlet. Ele é chamado pelo método initO
do servlet, portanto, na hora em que este método roda, haverá um ServletConfig e
um ServletContext disponíveis para o servlet. Isto significa que você pode chamar o
getServletConfigO e o getServletContextO de dentro do jspInitO.
Este exemplo usa o jspInitO para recuperar um parâmetro init do servlet (configurado no
DD) e usa este valor para configurar um atributo de escopo application.




    < %! <:             lI*,1:I
        public void j splnit ()
          ServletConfig sConfig          getServletConfig();
                                                               r     ~cê es-l-: "li*' servle-l-; f',,/'hi1-1-j f'tiJe chl1,*,i:I/'
                                                                     sev je-!-Serv/e+e.til'/fijO    I.e/'Jo.J".



          String emailAddr = sConfig.getlnitParameter("email");~
          ServletContext  ctx ~ getServletContext();     f                                        )


    "     ctx. setAttribute       ("mail",             ~
                                               emailAddr);    r)
                                                   Cói1sl!jve V*,11,
                                                                        _,             ''} ."~ se'VlH-         ~_I.
                                                                                       Is-l-ti é 'i.'x.A'rA'JtA.íAlrí ó 3Vl!
                                                                    I'efel'el'/c,"a '111'(;' " S/i!l"v/e+e.tii1hx-l- '!
                                                   CÓ"lfijVI"RIIhI 4-1-l'ibv+e Je escópó tlfplicR+lim.




310     capítulo 7
usando       o JSP


Os atributos       etM UtM   JSP
o exemplo    da página anterior mostra o JSP configurando um atributo
application, usando uma declaração que anule o jspInitO. Porém, na
maioria das vezes você usará um dos quatro objetos implícitos para
receber e configurar os atributos correspondentes aos quatro escopos
disponíveis no JSP.
Sim, quatro. Lembre-se, além dos escopos-padrão do servlet - request,
session e application (contexto), o JSP acrescenta um quarto escopo - o
escopo page -, que você obtém de um objeto pageContext.
Geralmente, você não precisará (e nem se preocupar) do escopo page, a menos
que você esteja desenvolvendo tags custornízadas. Por isso, não entraremos em
maiores detalhes, até o capítulo que trata das tags custornízadas.

                 Em um servlet                                         Em umJSP
                                                                       (usando objetos implícitos)

 Application     getServletContext().setAtlribute("foo", barObj);      application.setAtlribute("foo", barObj);

 Request         request.setAtlribute("foo", barObj);                  request.setAtlribute("foo", barObj);

 Session         request.getSession().setAtlribute("foo",   barObj);   session.setAtlribute("foo", barObj);

 Page            Não se aplica!                                        pageContext.setAtlribute("foo", barObj);




Mas não é só isso! Em um JSP, existe uma outra maneira de receber
e configurar os atributos em qualquer escopo, usando apenas o objeto
implícito pageContext. Continue e descubra como ...




                                            "context" .. mesmo que .os
                                                             0


                     Não existe um escopo lication estejam assocIados
                     atributos no escopo Wllal!Pl2o'==---
                     ao ob·]eto ServletContext.

                                                 , 10 a pensar que os
                   _         enclatura pode leva- _         d   copo context.
        A convençao de nom          S rvletContext sao... o:~         t"
        atributos armazenados no e         do você encontrar Contex ,
        Não existe isso. Lern:br~:s~ q~an existe uma diferença entre os
        pense em "appliC~~°::Sado~;e:;~ obter os atributos do escopo
         nomes servlet e],             , diz'
              . . . um servlet, voce·                  ,,")
         apphcatlOn. n             )    tAttribute ( foo
                tservletcontext(     .ge
             ge        SP você diz:
          mas em um],                . t ("foo")
               application.getAttrlbu       e




                                                                                          você está           ~     311
pageContext   e atributos


Usando o PageCotttext para atributos
Você pode usar uma referência PageContext
para obter atributos a partir de qualquer escopo,
inclusive o escopo page para atributos associados
ao PageContext.
Os métodos que funcionam com os outros
escopos usam um argumento int para indicar o
escopo. Embora os métodos de acesso derivem do
JspContext, você encontrará as constantes para os
escopos na classe PageContext.




      JspContext

      getAttribute(nome da String)
      getAttribute(nome da String, escopo int)
      getAttributeNamesInScope   (escopo int)
      findAttribute(nome da String)
                         lJ'IéfctiC$     ave   IV'7CicPlfJ.IJ'If'fJ.I'fJ.
                         ~II A-L.~fJ!/t.
      11 mais métodos
      11 inclusive, métodos similares
      11 para armazenar   e remover atributos de
      11 qualquer escopo




           PageContext

           APPLICATION         SCOPE
           PAGE SCOPE
           REQUEST _SCOPE               ca""ft;S
           SESSION SCOPE                e$+~+lc"S Ilnats
           l/mais campos

           getRequestO                  ,
           getServletConfigO           1M,&"d6S para
           getServletContextO ct."seSulr ?Jutl.l»ver
           getSessionO        6h't!!+•.•i""flct+6
           1/ mais métodos      ~




312             7
usando o JSP



ExeiMplosusat1do o pageCotttext para obter
                                                                             o pageContext   .
e cot1figurar atributos                                                      getAttribute(stnng)
                                                                             serve para o escopo
                                                                             ~
Configurando um atributo do escopo page
<% Float      one = new Float(42.5);     %>                            .     DOIS métodos getAttributeO
<% pageContext.setAttribute("foo",            one);   %>           EXistem                A   pode chamar
                                                                   muito usados que voce           .
                                                                                     t· m de um so
                                                                   no pageContex . u              d dois
                                                                              to IString) e outro e
                                                                    argumen      '          . )
                                                                    argumentos (String e mt. todos os
                                                                     O prunelro fiunc I'ona como
                                                                           . .                       . dos
Obtendo um atributo do escopo page                                              ara atributos aSSOCia
<%~ pageContext.getAttribute("foo")            %>
                                                                     outros - P        C text O segundo,
                                                                     AO objeto page onado p'ara obter
                                                                          . pode ser us
                                                                     porem,
                                                                      atributos de QUALQUER um dos
Usando o      eC:Ofl'h;~xt para configurar um                         quatro escopos.
atributo do escopo session
<% Float      two = new Float(22.4);     %>
<% pageContext.setAttribute("foo",            two, PageContext.SESSION_SCOPE);           %>




Usando o pageContext para obter um atributo do escopo session
<%= pageContext.getAttribute("foo",            PageContext.SESSION_SCOPE)         %>
(Que é idêntico a:   <%=   session.getAttribute("foo")        %»




Usando o pageContext               para obter um atributo do escopo application
Email   is:
<%~ pageContext.getAttribute("mail",            PageContext.APPLlCATION_SCOPE)           %>

Dentro de um JSP, o código acima é idêntico a:
Email   is:
<%~ application.getAttribute("mail")            %>



Usando o pageContext para encontrar um atributo quando você não
conhece o escopo
                  ..
<%~ pageContext.findAttrlbute("foo")           %> enC<lnrI'I'~-I<l<lI'I~e?


Onde o método findAttributeO olha? Ele olha primeiro no page context,
e se houver um atributo "foo" com o escopo page context, então, chamar
ofindAttribute(nome da String) num PageContext funcionará exatamente
como chamar o getAttribute(nome da String) num PageContext. Mas
se não existir nenhum atributo "foo", o método começa procurando em
outros escopos, do mais restrito ao menos restrito ~ ou seja, primeiro o
escopo request, depois o session e, finalmente, o application. O primeiro
que ele encontrar com este nome ganha.


                                                                                    você está         [!>    313
diretriz three



Já que estatltOS falatldo sobre isso ... vatltos falar
tltais sobre as três diretivas
Nós já vimos as diretivas usadas para inserir as declarações import
na classe do servlet gerado pelo seu JSP. Foi a diretiva page (um
dos três tipos de diretivas) com um atributo import (um dos 13
atributos da diretiva page). Nós agora daremos uma rápida olhada
nas outras, embora algumas não sejam abordadas em detalhes até
os próximos capítulos. Outras, inclusive, nem serão muito faladas
aqui, pois são raramente usadas.



  o    A diretiva paga
       <%@ page import=lIfoo.*"      session="false"     %>

       Define propriedades específicas da página, como códigos de
       caracteres, o tipo de conteúdo para a resposta e se esta página
       deveria possuir o objeto implícito session. Uma diretiva page
       pode utilizar até 13 atributos diferentes (como o atributo import),
       embora apenas quatro sejam cobrados no exame.


  8    A diretiva taglib
       <%@ taglib    tagdir~"/WEB-INF/tags/cool"         prefix~"cool"   %>

       Define as bibliotecas de tags disponíveis para o JSP. Nós ainda não
       falamos sobre o uso das tags customizadas e ações padronizadas;
       portanto, talvez não faça sentido neste momento. Fique com isto
       por enquanto ... teremos dois capítulos inteiros sobre bibliotecas de
       tags vindo em breve.


  e    Adiretiva
       <%@ include    file="wickedHeader.html"      %>


       Define os textos e os códigos que são acrescentados na página
       atual no momento da tradução. Isto lhe permite construir pedaços
       reutilizáveis (como um título-padrão para a página ou a barra de
       navegação), que podem ser acrescentados a cada página, sem
       precisar repetir todo aquele código em cada JSP.




r:   Estou confuso ... o título deste tópico diz: "Já que estam os falando
sobre isso ...", mas eu não vejo o que as diretivas têm a ver com
pageContext e atributos.


1:    Nada a ver, realmente. Nós só dissemos aquilo para disfarçar
a transição inexistente e patética entre dois tópicos não relacionados.
Esperávamos que ninguém notasse, mas NÃO ... você simplesmente não
permitiria, não é mesmo?


314 capitulo 7
usando    o JSP



Os atributos para a diretiva page
Dos 13 atributos da diretiva page da especificação JSP 2.0, apenas quatro são cobrados no exame.
Você NÃO precisa memorizar a lista inteira, mas veja o que você pode fazer. (Veremos os atributos
isELIgnored e os dois atributos relacionados a erros mais adiante.)


 PODE cair na prova --------------------------
 import             Define as declarações import do Java que serão adicionadas à classe do servlet
                    gerado. Você tem alguns import de graça (por padrão):java.lang (óbvio),javax.
                    servlet,javax.servlet.http ejavax.servletjsp.
 isThreadSafe       Define se o servlet gerado precisa implementar o SingleThreadModel que,
                    como você já sabe, é uma Coisa Terrivelmente Ruim. O valor-padrão é...
                    "true", o que significa: "Minha aplicação é thread-safe e eu NÃO preciso
                    implementar o SingleThreadModel, pois sei que é ruim por natureza." A única
                    razão para especificar este atributo seria se você precisasse configurar o valor do
                    atributo para "false", o que significa que você quer que o servlet gerado use o
                    SingleThreadModel, mas você nunca/ará isto.

 contentType        Define o tipo MIME (e o código opcional do caractere) para a resposta JSP. Você
                    conhece o padrão.
 isELlgnored        Define se as expressões EL serão ignoradas quando a página for traduzi da. Nós só
                    falaremos a respeito da EL no próximo capítulo. Por enquanto, saiba apenas que
                    você talvez queira ignorar a sintaxe EL em sua página, e este é um dos dois modos
                    que você pode informar ao Container.
 isErrorPage        Define se a página atual representa uma outra página de erro dos JSPs. O valor-
                    padrão é "false", mas se for true, as páginas têm acesso ao objeto implícito exception
                    (que é uma referência ao inconveniente Throwable). Se for false, o objeto implícito
                    exception fica indisponível para o JSP.

 errorPage          Define uma URL para o recurso para onde os uncaught Throwables devem
                    ser enviados. Se você definir um JSP aqui, então este JSP terá um atributo
                    isErrorPage="true"    na sua diretiva page.
 NÃO cairá na prova ----------------------------

 language           Define a linguagem scripting usada nos scriptlets, expressões e declarações. No
                    momento, o único valor possível é "java", mas ele está aqui pensando no futuro -
                    quando outras linguagens provavelmente serão usadas.

 extends            Define a superclasse da classe que este JSP tomar-se-á. Você não o usará, a menos
                    que REALMENTE saiba o que está fazendo - ele anula a hierarquia da classe
                    fomecida pelo Container.
 session            Define se a página terá um objeto implícito session. O valor-padrão é "true".

 buffer             Define como o buffering é tratado pelo objeto implícito out (referente ao JspWriter).

 autoFlush          Define se a saída bufferizada está limpa automaticamente. O valor-padrão é "true".
 info               Define uma String que é inserida na página traduzida, exatamente para que você
                    possa obtê-la usando o método getServletInfoO herdado do servlet.

 pageEncoding       Define o código de caracteres para o JSP. O padrão é "ISO-8859-1" (a menos que o
                    atributo contentType já o tenha definido ou a página use a sintaxe XML Document).


                                                                                  você está aqui...       315
são scriptiets maus?




316   capítulo 7
usando oJSP



Scriptlets cotlsideradas prejudiciais?
Isso é verdade? Poderia haver uma desvantagem em se colocar todo
este Java no seu JSP? Afinal, não é este todo o PROPÓSITO do JSP?
De forma que você escreva seu Java no que é essencialmente uma
página HTML, ao contrário de escrever o HTML em uma classe Java?
Algumas pessoas acreditam (tudo bem, tecnicamente um monte de
gente, inclusive as equipes que criaram as especificações do JSP e do
servlet) ser uma prática ruim colocarmos todo este Java no seu JSP.
Por que? Imagine que você foi contratado para construir um grande
site. A sua equipe inclui uns poucos programadores Java e um enorme
grupo de "webdesigners" - artistas gráficos e profissionais que criam
páginas utilizando o Dreamweaver e o Photoshop para construírem
aquelas páginas fabulosas. Eles não são programadores (bem, existem
aqueles que continuam achando que HTML é " programação").




              Atores   aspirantes   trabalhando   como webdesigners   enquanto
              esperam por sua grande oportunidade       no showbiz.




                                                                                 você está    ••. 317
fora do scripting




                  Duas perguntas: POR QUE
                 você está nos ensinando isso
                e QUAL é a alternativa? Que
                 outra m**** EXISTE, além
                do HTML, já que não podemos
                usar scriptlets, declarações e
                     expressões no JSP?




                                              Não EXISflA .,e.,hutMa alternativa.
                                              Isso significa que já existem montanhas de arquivos JSP abarrotados
                                              de código Java enfiados em cada pedaço da página, acomodados
                                              entre scriptlets, expressões e tags de declarações. Já está lá e não
                                              há nada que alguém possa fazer para mudar o passado. Portanto,
                                              significa que você tem que saber como ler e entender estes
                                              elementos e como manter páginas escritas com eles (a menos que
                                              você tenha a chance de recriar todo o JSP da sua aplicação).
                                              Cá entre nós, até achamos que ainda há lugar para coisas desse tipo
                                              - não há nada melhor do que um pouco de Java no JSP para testar
                                              rapidamente algo no seu servidor. Mas na maioria das vezes, você
                                              não vai querer usar isso nas suas páginas verdadeiras e em produção.
                                              A razão para tudo isto estar no exame é que as alternativas
                                              ainda são novidade. Por isso, a maioria das páginas hoje ainda
                                              é "da antiga". Por enquanto, você ainda tem que ser capaz de
                                              trabalhar assim! Em algum momento, quando novas técnicas que
                                              dispensem Java atingirem um público considerável, os objetivos
                                              deste capítulo provavelmente não constarão mais na prova. E
                                              respiraremos aliviados pela morte do Java-em-JSPs.
                                              Mas esse dia ainda não é hoje.




(Nota para pais e professores:   a palavra
de cinco letras implícita no balão acima,
que começa com "m" seguida por quatro
asteriscos, NÃO é o que vocês estão
pensando. É simplesmente    uma palavra
que achamos engraçada demais para
ser incluída aqui, sem que distraísse o
leitor. Por isso ela foi truncada. Porque é
engraçada. E não, imprópria.)

318                  7
usando oJSP




       Poxa, se pelo menos existisse uma
       maneira do JSP usar tags simples
        que permitissem que os métodos
      J ava rodassem, sem ter que colocar
          na página o código Java em si.


                    C>
                     o




EL:   a resposta para, digatltos, tudo.
Ou quase tudo. Mas certamente uma resposta para duas grandes
reclamações sobre colocar o lava no lSP:

1. Os designers não precisariam saber Java.

2. O código Java existente no JSP é difícil de mudar e manter.

EL significa "Expression Language" e, oficialmente, tomou-se parte
da especificação a partir da especificação lSP 2.0. A EL é quase
sempre o jeito mais simples de se fazer algo que você normalmente
faria com scriptlets e expressões.
É claro que neste momento você está pensando: "Mas se eu quiser
que meu lSP use métodos customizados, como poderei declará-Ios e
escrevê-Ios se não posso usar lava?"
Ahhhh ... escrever a funcionalidade real (o código do método) não é
o propósito da EL. O propósito da EL é oferecer um jeito simples de
invocar o código lava - mas o código em si pertence a algum outro
lugar. Ou seja, uma classe lava simples normal, que funcione como
um lavaBean, uma classe com métodos estáticos, ou aquilo que
chamamos de Tag Handler. Em outras palavras, você não escreve o
código do método no seu lSP se você estiver seguindo as Melhores
Práticas de hoje em dia. Você escreve o método lava em algum outro
lugar e o chama usando a EL.



                                                        você está      ••. 319
fora do scripting



UtMa apresentação rápida da EL
                                                               Uma expressão EL SEMPRE
o capítulo seguinte fala só sobre EL, portanto não             se parece com: ${alguma
entraremos em detalhes aqui. A única razão de estarmos         coisa}
falando dela é devido ao fato de ela ser um outro elemento
(com sua própria sintaxe) que o JSP aceita. E os objetivos      Ou seja, ela vem SEMPRE
da prova que constam neste capítulo incluem reconhecer          entre chaves e precedida
tudo o que possa estar em um JSP.                               pelo símbolo ($).




Esta expressão EL:
   Please    contact:   ${applicationScope.mail}


É o mesmo que esta expressão Java:
    Please   contact:   <%= application.getAttribute("mail")      %>




        Não exIstem

f etguntéls         idl9Í:élS

r:   Não querendo ser chato, mas creio não ter visto nenhuma
grande diferença entre a EL e a expressão Java. Claro que ela é um
pouco menor, mas vale a pena mudar toda a linguagem scripting e
os códigos no JSP?


1:   Você AINDA não viu as vantagens da EL. As diferenças tornar-
se-ão óbvias no próximo capítulo, quando mergulharemos no assunto
de cabeça. Mas você deve se lembrar que para um programador
Java, a EL NÃO oferece, necessariamente, uma gigantesca vantagem
no desenvolvimento. Na realidade, para um programador Java ela
simplesmente significa "uma coisa a mais (com sua própria sintaxe e tudo)
para aprender, quando, psiu, eu já SEI Java ..."

Mas não é só com relação a você. A EL é muito mais fácil para alguém que
não programe em Java aprender rapidamente. E para um programador
Java, ainda é muito mais fácil manter uma página sem scripts.

Sim, é mais uma coisa a aprender. Ela não deixa os webdesigners
completamente a salvo, mas você verá em breve que é mais intuitivo
e natural para eles usar a EL. Por enquanto, aqui neste capítulo, você
simplesmente precisará ser capaz de reconhecer uma EL quando se
deparar com ela. E não se preocupe ainda em diferenciar se a EL é válida
- tudo que queremos saber agora é se você consegue identificar uma
expressão EL em uma página JSP.


320    capítulo 7
usando oJSP




                                                         Usat1do     <Scriptit1g~it1valid>
                                                         É simples, você pode impedir que um JSP
                                                         possua elementos scripting (scriptlets,
                                                         expressões Java ou declarações), colocando
                                                         uma tag <scripting-invalid> no DD:


                                                          <web-app     ...>

                                                             <jsp-config>
                                                                <jsp-property-group>
                                                                <url-pattern>*.jsp</url-pattern>
                                                                <scripting-invalid>
                                                                   true
                                                                 </scripting-invalid>
           IS+6       Jesdfll-h.        6S                      </jsp-property-group>
                                                             </ jsp-config>
           elellP;ePl+6s scri,+tPlj
           pare.    rf:ibos         (lS JSPs              </web-app>

           l'1a fJ.p/í'ca{41J   (p.:.r1pe
           (JSO,IIP;6S *,:}Sf> C(lIIP;(I
                     tJ                                 Cuidado - você pode ter visto outros livros e
           pfJ.dr'ió de tJ/I!.L).                       artigos mostrando uma diretiva page que desabilita
                                                        o scripting. Na versão rascunho da especificação
                                                        2.0, havia um atributo da diretiva page:

                                                        <%@ page isScriptingEnabled="false"       %>
Is+    •• PI'i•• tllm:ttJP1e.! () fJ.+rtbll+tJ __   ~
i'sScrip+/'PI;7"PlfJ.b1e.d PI'i<I'J
                                 CIJP1s+1J.             mas ele foi removido da especificação
IIP;lJ,i's lIJ, speclti'clJ.f'iIJ
         P e                         dlJ JSP/
                                                        definitiva!!
                                                        A única forma de invalidarmos o scripting agora
                                                        é através da tag <scripting-invalid> no DD.


                                                                                      você está         ~    321
ignorando   a EL


Você pode decidir ignorar a EL
Sim, a EL é uma coisa legal que salvará o mundo, como nós já sabemos. Mas algumas
vezes você pode querer desabilitá-Ia. Por quê?
Lembre-se de quando a palavra-chave assert foi adicionada na linguagem Java versão
1.4. De uma hora para outra, o identificador perfeitamente legal e não reservado
"assert" passou a significar algo para o compilador. Então, se você tivesse, digamos,
uma variável chamada assert, você estaria "ferrado". Com exceção da versão J2SE 1.4,
que veio com as declarações desabilitadas por padrão. Se você soubesse que estaria
escrevendo (ou recompilando) um código que não usasse assert como identificador,
você poderia escolher habilitar as tais declarações.
Ou seja, é quase o mesmo que desabilitar a EL - se você decidiu ter template text (HTML
simples ou texto) em um JSP que incluísse algo parecido com a EL ($ {alguma coisa} ),
você estaria com um Grande Problema, caso não pudesse informar ao Container para
ignorar tudo que se parecesse com a EL, em vez de tratar como qualquer outro texto
comum. Exceto pelo fato de haver uma grande diferença entre a EL e as assertions:


A EL é habilitada por padrão!
Se você quiser que os elementos do seu JSP parecidos com a EL sejam
ignorados, você tem que dizer explicitamente, ou através de uma diretiva
page ou de um elemento no DD.


                                                                   A.diretiva page tem
                                                                   prioridade sobre a
Inserindo <el-ignored> no DD                                       configuração do DO!
    <web-app     ...>                                     Se houver um conflito entre a tag
                                                          <el-ignored> configurada n? D.D
      <jsp-config>
                                                          o atributo isELIgnored da dlretlva
         <jsp-property-group>
         <url-pattern>*.jsp</url-pattern>                 page, a diretiva se,!!pre ga~ha!
         <el-ignored>                                     Isto permite a voce determmar o
            true                                          comportamento-padrão no DD,
         </el-ignored>                                     mas, também, anulá-Io em uma
        </jsp-property-group>
                                                          página especifica, usando uma
      </jsp-config>
                                                           diretiva page.
    </web-app>

                                                                                Cuidado com as
                                                                                inconsistências na
                                                                                nomenclatura!

                                                                    A tag do DD é <el-ignored>
Usando o atributo isELlgnored                                       portanto, alguém poderia      '
da diretiva page                                                   pe~sar, com toda razão, que o
                                                                    atributo da diretiva page seria
                                                                    talvez, elIgnored. Mas não      '
    <%@ page     isELIgnored="true"   %>
                                                                   esse alguém estaria errad; se
                                                                   chegasse a tal conclusão. O
                                                                   DDe d' .
                                                                         _a ~r~tzva para ignorar a


                                                                  l
                                                                   EL sao dIstzntos! Não caia na

                                                                   armadilha da <is-el-ignored>.
                                                                            2     ::    i&1;     i
 322 capítulo 7
usando o JSP



Mas espere ... existe UtMoutro eletMettto JSP
que nós ainda não vitMos:

Até aqui, você viu cinco diferentes tipos de elementos
que podem aparecer em um JSP: scriptlets, diretivas,
declarações, expressões Java e expressões EL.
Mas nós não vimos as ações. Elas vêm em dois sabores:
padrões e... não-padrões.


Ação-Padrão:
   <jsp:include   page="wickedFooter.jsp"



Outra Ação:
   <c:set   var="rate"   value="32"   />




Embora possa parecer confuso, existem ações que
não são consideradas ações-padrão, mas que ainda
fazem parte de uma biblioteca agora padronizada. Ou
seja, você aprenderá mais tarde que algumas ações
não-padrão (os objetivos referem-se a elas como
customizadas) são ... padrões, mas ainda não são
consideradas "ações-padrão". Sim, é isso mesmo: elas
são ações customizadas padronizadas não-padrão. Agora
não ficou mais claro?
Num capítulo mais adiante, quando chegarmos em
"usando tags", usaremos um vocabulário um pouco
mais rico, em que trataremos deste assunto mais
detalhadamente. Então, relaxe. Agora, tudo o que nos
interessa é que você reconheça uma ação quando se
deparar com ela em um JSP!




Observe a sintaxe de uma ação e compare-a com a sintaxe de outros tipos de elementos JSP. E
responda:


1) Quais são as diferenças entre o elemento de uma ação e um scriptlet?




2) Como você reconheceria uma ação?




                                                                          você está    ."   323
exercício de avaliação



                            Matriz de Avaliação
                           O que acontece quando cada
                           uma destas configurações (ou a
                           combinação delas) ocorre? Você verá
      E){etc1C19S
             ? o           as respostas quando virar a página;
                           portanto, faça AGORA.



                                                  Faça um X na coluna avaliado, se as combinações
                                                  levarem as expressões EL a serem avaliadas, OU
                                                  faça um X na coluna ignorado, se a EL for tratada
                                                  como outro texto template. Nenhuma linha terá as
                                                  duas opções marcadas, é claro.


   o Avaliação da EL
       Configuração no DD          diretiva de página             avaliado           ignorado
          <el-ignored>                 isELlgnored
                               verdadeira
                               falsa
                               não-especificado
    não-especificado




                                        Faça um X na coluna avaliado, se as configurações levarem
                                        as expressões de scripting a serem avaliadas, OU faça um X
                                        na coluna erro, se o scripting gerar um erro de tradução.


   e     Validade do scripting

                               avaliado
       Configuração ignorado
                      no DD
não-especificado
   verdadeira
   falsa




   324    capítulo 7
~
        e>?~'
        ",,<PqT   1t
                       ímã de GeladeIra (Element9SJSY)
                  t    Correlacione o elemento JSP com o seu trecho de código,
                       associando o código à caixa que o representa. Lembre-se
                       de que você terá questões "arrastar e soltar" no exame,
                       semelhante a este exercício; então, não o pule!




              Tipo de elemento JSP                                Trecho de código JSP
                             ,




    ;                      êlirefiva



                                                                            /}"1"4Sie e sclie "a CIA/XIi.
                                                                            cttll"l"es/'(j"de"ie.


                                                 <% Float one      = new Float        (42.5); %>


                                                                                     ='   3;   %>
                                                                     <%! int Y


                                                             <%@pagei
                                                                             mport=Njava.util.

                                                                                                    "
                                                        <jsp:include


                                                  i<%= pagecontext        g tAt      .
                                                                        .e        tr~bute{"foON)%

                                                         email:    ${ap
        ~'"            ~                ""   ~
    ~                                        '



.                      eXlressão




                                                                                      você está aqui    li>   325
exercício de avaliação


                ~
17~$"ô~         1mã de G-ela.de'lta.(Element98JSf):                       C9nt1nua.c;ã9
  ~.         yocê sabe o ~ome deles, ~as :,oc~ se lembra onde eles ficam no servlet gerado?
           . E claro que Sim. Mas este e so maiS um reforço antes de passarmos para um
             capítulo e um assunto diferentes.
             (Considerando o arquivo da classe servlet, coloque o elemento no quadro onde
             o código gerado por ele ficará. Note que o ímã, em si, não representa o código
             REAL que será gerado.)




       public    final class   BasicCounter_jsp     extends org.apache.jasper.runtime.HttpJspBase
                                     implements    org.apache.jasper.runtime.JspSourceDependent                {




       public    void _jspService(HttpServletRequest          request, HttpServletResponse    response)
                                                throws       java.io.IOException,   ServletException    {




                                                                                A-  IJl'dehldes+es 1-l'ês   :11';5

                                                                                ; ll'l'eleval1+e.




        request.getA·ttl~it'ute                   email:   ${applicationScope

                                                                                        <%! int Y = 3; %>




326      capjitulo 7
Matriz de Avaliação
                         RESPOSTAS

       EXetc1C19S
             ~o


   o    Avaliação da EL



       Configuração no DD          diretiva de página    avaliado           ignorado
          <el-ignored>                 isELlgnored

    não-especificado
                                     V
                               falsa '"
                               verdadeira
                               não-especificado     '"




   f) Validade do scripting
                               avaliado
                                    '"              '"
       Configuração ignorado
                      no DD
não-especificado




                                                                    você está
res:{Josta'sdos elementos JSP


           ~
          Imã de GeladeI!a (Element9SJSY)
          Respostas




        Tipo de elemento    JSP           Trecho de código JSP




                                            A palavra "expressão" significa
                                            "expressão scripting", e NÃO
                                            "expressão EL".


                                  É claro que a palavra "expressão" é muito usada
                                  pelos elementos lSP Se você encontrar a palavra
                                   "expressão", ou "expressão scripting", elas
                                  querem dizer o mesmo: uma expressão que usa a
                                  sintaxe da linguagem lava:
                                   <%= foo.getNameO %>
                                   A única vez que a palavra "expressão" se refere
                                   à EL, é quando você especificar "EL" no label ou
                                   nas descrições! Portanto, considere sempre que o
                                   padrão para a palavra "expressão" é "scripting/
                                    expressão lava ", e não EL.




328   capítulo 7
usando         o JSP


             ?

/) g'; ímã
 ~                   de Geüldeltq (Element9sJSY):                                    C9nt1nuqyã9
~            RESPOSTAS




                                                                                                  ;            CCh>1Ih>a+ribll+ó     'Ity>cr+
                                                                                                       '''''1>61'+ Javo..


    public       final class         BasicCounter_jsp           extends org.apache.jasper.runtime.HttpJspBase
                                           implements          org.apache.jasper.runtime.JspSourceDependent                                     {

                                                                                       /}s declara)';'!s
                                    <%! int       y =      3; %>                       X4.í.X4.8;e.f)5~
                                                                                       da classe      taNJ.f
    public       void _jspService(HttpServletRequest                      request, HttpServletResponse    response)
                                                throws                   java.io.IOException,   ServletException    {




                             <%=request.getAttribute(fffoo




                             <% F10at one = new Float                (42.5); %>          Os scrip+le+s       'tc4h> del1+r<> da
                                                                                         h>é-I-4d4 sel"vtce.




                            emai1:         ${app1icationscope.mai1}                      /}s express';es              ii- ·hclJ.h>deJOi+l'c dD
                                                                                         h>é+"d4 sel'viée.




                                                                                          (!J4+",: 4 ól'deh> des+es                +1"'&
                                                                                          é i"rl'elevll.l1+e,:;




      AJor/}:       Iflf<lbre-"se tle 3ve.,         c:tlijíJ   JSP    l171íJ ICIJr)
                                                                           F           tle Ia.+tl) iJ.$SIW!
      «4 sf!rvle+          •••   é +4«1J +ra«v-;ifJ.1J    paf'a C c:tlijlJ   Jo.v#.. l.s+e        exen:Ci"6
      If<IlJs+rO,f'   elf<l '/;V41    pa.f'ff   da elas se jef'ada       eSffs    elelf<lel1+lJs
      11711J
          es1-lJ.lf<ltJsIf<IfJs1-f'tJ.l1dtJ-It.f!.o e:JijtJ          real 5*=1'0.«6PQra      éI   '/;val

      1-f'e.tlv;ttl..,s.     PaI' eXf""'Pló) ti Jedaf'Qg71lJ 'tive ef'Q <.%II).;1-?               ••   3; %> 1-cN1frSe
      st""'P/fslf<le"ff           1i1f; ••3;                                              .


                                                                                                                você está              •.. 329
teste preparatório




                                            fausa pata
                                            9 caté
                         7e4teP~-~7

    1Dado o elemento DD:
       47. <jsp-property-group>
       48.      <url-pattern>*.jsp</url-pattern>
       49.      <el-ignored>true</el-ignored>
       50. </jsp-property-group>


       o que o elemento     faz? (Escolha todas as que se aplicam.)

       O A. Todos os arquivos     com o mapeamento da extensão especificada
             devem ser tratados pelo container JSP como arquivos que respeitam a
             sintaxe XML.
       O B. Todos os arquivos      com o mapeamento da extensão especificada
             devem ter seus códigos EL avaliados pelo container JSP.
       O     C. Por padrão, NENHUM arquivo com o mapeamento da extensão
             especificada deve ter seus códigos Expression Language avaliados
             pelo container JSP.
       O     D. Nada. Esta tag NÃO é reconhecida pelo container.
       O     E. Embora esta tag seja válida, ela é redundante, pois o container já
             faz isso por padrão.




     2 Quais das diretivasabaixo representam uma resposta HTTP do tipo
       "image/svg"? (Escolha todas as que se aplicam.)

       DA. <%@       page   type="image/svg"    %>
       OB.<%@        page   mimeType="image/svg"       %>
       OC.<%@        page   language="image/svg"       %>
       OD.<%@        page   contentType="image/svg"         %>
        CJE.<%@      page   pageEncoding="image/svg"        %>




 330 capítulo 7
.3   Seja o JSP:

     1.   <%@ page import="java.util.*" %>
     2.   <html><body> The people who like
     3.   <%= request.getParameter(~hobby") %>
     4.   are: <br>
     5.   <% ArrayList al = (ArrayList) request.
     getAttribute(~names"); %>
     6.   <% Iterator it = al.iterator();
     7.      while (it.hasNext(»         { %>
     8.          <%= it.next() %>
     9.   <br>
     10. <% } %>
     11. </body></html>


     Que tipos de códigos encontramos nele? (Escolha todas as que se aplicam.)
     OA.EL
     O B. diretiva
     O C. expressão
     O D. template      text
     O E. scriptlet




4: Que declarações sobre o        jspInit () são verdadeiras? (Escolha todas as
     que se aplicam.)

     O A. Ele tem acesso ao Serv1etConfig.
     O B. Ele tem acesso ao Serv1etContext
     O C. Só é chamado uma vez.
     O D. Pode     ser anulado.




                                                                             você está
5 Que tipos de objetos estão disponíveis      para o método j splnit   () ?
       (Escolha todas as que se aplicam.)

       CJA.ServletConfig
       CJB.servletContext
       [JC.JspservletConfig
       [J D.JspServletContext
       [J E.HttpServletRequest
       [J F. HttpServletResponse




   6   Dado:

       <%@page isELIgnored="true"           %>

       o que acontece?   (Escolha todas as que se aplicam.)

       [J A. Nada. A diretiva page NÃO foi definida.
       CJ B. A diretiva anula a avaliação que o container JSP faz do código da
          Expression Language em todos os JSPs da aplicação.
       CJ C. O JSP que possui esta diretiva será tratado pelo container JSP como
          um arquivo que respeita a sintaxe XML.
       CJ D. O JSP que possui esta diretiva NÃO deveria possuir nenhum
          código da Expression Language avaliado pelo        container JSP.
       [J E. Esta diretiva apenas cancelará a avaliação da EL se o DD declarar
          um elemento <el-ignored>true</el-ignored>           com um padrão URL
          que inclui este JSP.




   1   Qual declaração referente aos JSPs é verdadeira? (Escolha uma.)

       [J A. Apenas o jsplnit () pode ser anulado.
       CJ B. Apenas o jspDestroy()     pode ser anulado.
       O  C. Apenas o _j spService () pode ser anulado.
       O D. O j splni t () e o j spDestroy () podem ser anulados.
       O E. O jsplni t (), o jspDestroy () e o _jspService () podem ser
          anulados.



332 capítulo 7
usando o JSP




 8 Qual das etapas do ciclo de vida do JSP está fora de ordem?
     O A. Traduzir    o JSP em servlet.
     O     B. Compilar o código-fonte do servlet.
     O     C.Call      jspService()
     O D. Instar       a classe servlet.
     DE.     Call    jsplnit()
     O     F.Call    jspDestroy()




 9   Quais das variáveis implícitas JSP são válidas? (Escolha todas as que se
     aplicam.)

     DA.      stream
     O     B. context
     O     c. exception
     O D. listener
     OE.application




10   Seja uma solicitação com dois parâmetros: um chamado "first", que
     representa o primeiro nome do usuário, e o outro chamado "Iast", que
     representa seu último nome.

     Qual código scriptlet JSP gera os valores para estes parâmetros?
     DA.      <%    out.println     (request. getParameter   ("first"));
           out.println(request.getParameter("last");              %>
     O     B. <% out.println(application.getlnitParameter("first"»);
           out.println(application.getlnitParameter("last"»);               %>
     O     c.<% println(request.getParameter("first"»;
           println(request.getParameter("last");             %>
     OD.<%          println(application.getlnitParameter("first");
           println(application.getlnitParameter("last"»;               %>




                                                                                 você está    ~   333
teste preparatório




  11 Dado:
        11.    He110 ${user.name}!
        12.    Your number is <c:out value="${user.phone}"/>.
        13.    Your address is <jsp:getProperty   name="user" property="addr"         />
        14.    <% if (user.isValid(»    {%>Youare valid!<% } %>

        Quais declarações são verdadeiras? (Escolha todas as que se aplicam.)

        O A. As linhas 11 e 12 (e nenhuma outra) contêm exemplos de elementos
              EL.
        O     B. A linha 14 é um exemplo de código scriptlet.
        O     C. Nenhuma das linhas deste exemplo contém um template text.
        O     D. As linhas 12 e 13 incluem exemplos de ações-padrão JSP.
        O     E. A linha 11 demonstra o uso incorreto da EL.
        O     F. Todas as quatro linhas deste exemplo seriam válidas em uma página JSP.




   12   Qual tag JSP exibirá o parâmetro de inicialização de contexto chamado
        "javax.sql.DataSource"?
        OA.<%=        application.getAttribute(~javax.sql.DataSource")           %>
        OB.<%=        application.getlnitParameter(~javax.sql.DataSource")          %>
        O C.<%=       request.getParameter(~javax.sql.DataSource")            %>
        OD.<%=        contextParam.get(~javax.sql.DataSource")             %>




   13   Quais declarações sobre desabilitar elementos scripting são verdadeiras?
        (Escolha todas as que se aplicam.)

        O A. Você não pode desabilitar scripting via DD.
        O B. Você só pode desabilitar scripting no nível da aplicação.
        O C. Você pode desabilitar scripting programaticamente, utilizando o
          atributo de diretiva de página isScriptingEnabled.
        O D. Você pode desabilitar scripting via DD usando o elemento
          <scripting-invalid>.




334     cap,itulo 7
14 Em      seqüência, quais são os tipos Java para os seguintes objetos implícitos
     JSP:app1ication,out,request,response,session?

     o A.     java. 1ang .Throwab1e
           java.1ang.Object
           java.uti1.Map
           java.uti1.Set
           java. uti1. List

     [JB.   javax.serv1et.Serv1etConfig
         java.1ang.Throwab1e
         java.1ang.Object
         javax.serv1et.jsp.PageContext
         java.uti1.Map

     [J C. javax.serv1et.Serv1etContext
        javax.serv1et.jsp.JspWriter
        javax.serv1et.Serv1etRequest
        javax.serv1et.Serv1etResponse
        javax.serv1et.http.HttpSession

     [JD.   javax.serv1et.Serv1etContext
         java.io.PrintWriter
         javax.serv1et.Serv1etConfig
         java.1ang.Exception
         javax. serv1et.RequestDispatcher




15 Qual      das opções representa um      exemplo     da sintaxe usada para importar
     uma    classe em um JSP?

     o A.     <% page      import="java.uti1.Date"        %>
     OB.<%@         page     import="java.uti1.Date"       @%>
     [J C.<%@       page     import="java.uti1.Date"       %>
     OD.<%          import    java.uti1.Date;   %>
     [JE.<%@        import     file="java.uti1.Date"      %>




16   Dado     o JSP:

     1. <%@ page        isELIgnored="true"      %>
     2. <%@    tag1ib        uri=~http://java.sun.com/jsp/jsy1/core''
     prefix="c" %>
     3. <c:set       var="awesomeBand"       va1ue="LIMOZEEN"/>
     4. $ {awesomeBand}


     Qual será a saída?

     o A.     ${awesomeBand}
     O     B. LIMOZEEN
     O     C. Nenhuma        saída
     O     D. Uma    exceção será enviada porque todas as diretivastaglibdevem
           preceder qualquer diretivapage.

                                                                                   você está
teste preparatório - respostas




                                              "fausa para
                                                   º caté
                                     1i!~-~7

    1Dado o elemento DD:
      47. <jsp-property-group>
      48.       <url-pattern>*.jsp</url-pattern>
       49.      <el-ignored>true</el-ignored>                            - lJr l>f'j';" C co.Plcela <) c:lcl./lc Jas

      50. </jsp-property-group>
                                                                         eXfl'ess'4es      íl...
                                                                                             fell> cClrf-o.tPlel' JSP         2..tJ.
                                                                         .R.I' fiJ.dl'';''J c cl1m-l-o.t#iU' calcl./ltI a f.L.

      o que o elemento faz? (Escolha todas as que se aplicam.)
      O A. Todos os arquivos com o mapeamento da extensão        especificada
             devem ser tratados pelo container JSP como arquivos que respeitam a
             sintaxe XML.
      O B. Todos os arquivos     com o mapeamento da extensão especificada
           devem ter seus códigos EL avaliados pelo container JSP.
       liZ C. Por padrão, NENHUM arquivo com o mapeamento da extensão
           especificada deve ter seus códigos Expression Language avaliados
           pelo container JSP.
       O   D. Nada. Esta tag NÃO é reconhecida pelo container.
       O E. Embora esta tag seja válida, ela é redundante, pois o container já
           faz isso por padrão.




    2 Quais   das diretivas abaixo representam uma resposta HTTP do tipo
       "image/svg"? (Escolha todas as que se aplicam.)

       DA. <%@           page   type="image/svg"    %>
       O     B. <%@ page        mimeType="image/svg"       %>
       IiZc.<%@          page   language="image/svg"       %>
       OD.<%@            page   contentType="image/svg"         %>    - lJr IJf'j';t; /) 4pl'esePl-l-o.   tJ.   s,-.,-I-axe
       O     E.<%@       page   pageEncoding="image/svg"        %>   ffJ.NI. es=l-a di'l'e-l-tVo..




336   CB{)ítLii'O    7
usando              o JSP




3 Seja o JSP:
  1.    <%@ page import="java.util.*" %>
  2.    <html><body> The people who Iike
  3.    <%= request.getParameter(~hobby") %>
  4.    are: <br>
  5.    <% ArrayList aI = (ArrayList) request.
  getAttribute(~names"}; %>
  6.    <% Iterator it = al.iterator(};
  7.         whiIe (it.hasNext()} { %>
  8.            <%= it.next(} %>
  9.    <br>
  10. <% } %>
  11. </body></html>


  Que tipos de códigos encontramos nele? (Escolha todas as que se aplicam.)
  DA.EL
  li2' B. diretiva                 - lJ';ó exis.f.e íL         '1es.f.e J-SP'   té••• (1"'11
                                                                                    t>s         d"1"e·h-vo. #'/0.      ",1./1
                                                                                                                    , ••



  li2' C. expressão                expl'fIss;es
                                   114 Ii...,hll
                                                        l1a~ !,...,has   3 BJ
                                                                          fI    .f.e""f'II1.f.e.f.ed
                                                   2) eJ '''5IcÓJ e!e•••e..,.f-cs scrip-h""j.
                                                                                                       P"'I' .f-"d,,'adó

  li2' D. template text
  li2' E. scriptlet




4 Que declarações     sobre o jspInit () são verdadeiras? (Escolha todas as
  que se aplicam.)

  li2' A.   Ele tem acesso ao ServletConfig.
  li2' B.   Ele tem acesso ao ServletContext
  li2' C.   Só é chamado uma vez.
  li2' D.   Pode ser anulado.




                                                                                                você está                       •    337
teste preparatório - respostas




    5 Que tipos de objetos estão disponíveis            para o método j spIni t () ?
          (Escolha todas as que se aplicam.)

          ~ A. ServletConfig
          ~ B. ServletContext
          CJ C.JspservletConfig                - Os JSPs          v/,'all1 stl'vle-l-s   siíJ'lf>les e ,til'   lSSti h""'"   acess<Ii
          CJD.JspservletContext                ati; ól6e-l-os siíJ'lf>les Sel'v1e-I-Coill; e Sel'vle+C<liilh",-I- •••
          CJE.HttpservletRequest               e e Yh<t POtlC<li edo "10 delo de vtlia p41'a !a141'1I10S s<libl't
                                                               c
          CJ F.HttpServletResponse             stillci-l-asêes     e I"es,os-l-as




   6 Dado:
          <%@page isELIgnored="true"           %>

          o que acontece? (Escolha todas as que se aplicam.)
          O A. Nada. A diretiva page NÃO foi definida.
          O B. A diretiva anula a avaliação que o container JSP faz do código da
             Expression Language em todos os JSPs da aplicação.
          CJ C. O JSP que possui esta diretiva será tratado pelo container JSP como
             um arquivo que respeita a sintaxe XML.
          ~ D. O JSP que possui esta diretiva NÃO deveria possuir nenhum código
             da Expression Language avaliado pelo        container JSP.
          O  E. Esta diretiva apenas cancelará a avaliação da EL se o DD declarar
             um elemento <el- ignored>true</ el- ignored> com um padrão URL
             que inclui este JSP.

                                                                 ;; es-A} l",col"l"e-l-lI<; <Jl''Ipe
                                                                                          p            li till'e-h"II11<;;.Ie-l-" "pe"J"s   6
                                                            16l '''c/llido.




      t   Qual declaração referente aos JSPs é verdadeira? (Escolha uma.)

          O A. Apenas   o j spIni t () pode ser anulado.
          O B. Apenas o jspDestroy() pode ser anulado.                   - Le...,bl'e-se                          tie
          O C. Apenas o _jspService () pode ser anulado.                  I
                                                                         e tl lilctl. tie 'fpe                     t/lI1
          ~ D. O jspInit()     e o jspDestroy()   podem ser anulados.    seI' fl.J1yltltió.
          O E. O j spIni t () , o j spDestroy () e o _j spService () podem ser
            anulados.



338   ca(.)itw'o    7
usando       o JSP




 8 Qual das etapas          do ciclo de vida do JSP está fora de ordem?

     D A. Traduzir o JSP em servlet.
     D B. Compilar o código-fonte do servlet.
     Iitr C.   Call _jspService       ()
     D D. Instar        a classe servlet.                                       -()
     DE.       Call    jsplnit()
     D      F.Call     jspDestroy()




 9   Quais das variáveis implícitas JSP são válidas? (Escolha todas as que se
     aplicam.)

     DA.       stream
     D B. context
     Iitr   c. exception                    - /}s efS4es,/}      8  e P "'';., exls-!--e"" ce"""

     O D. listener                          et.ie+<ls 'Ry-lictJ.<lS Cl",Q.,/"s pele ce",+al",el"
                                            pal"a 6S J-sPs.
     Iitr E.   application




10   Seja uma solicitação com dois parâmetros: um chamado "first", que
     representa o primeiro nome do usuário, e o outro chamado "last", que
     representa seu último nome.

     Qual código scriptlet JSP gera os valores para estes parâmetros?

     Iitr A.   <%     out.println    (request. getParameter             ("first"));
            out.println(request.getParameter("last"»;                           %>
     D B.      <% out.println(application.getlnitParameter("first"»;
            out.println(application.getlnitParameter("last"»;                                %>
     D      C.<% println(request.getParameter("first"»;
            println(request.getParameter("last"»;                        %>
     DD.<%           println(application.getlnitParameter("first"»;
            println(application.getlnitParameter("last"»;                             %>




                                                                                                   você está        ~     339
teste preparatório - respostas




  11 Dado:
       11. Helio       ${user.name}!
       12. Your       number    is <c:out     value=H${user.phone}HI>.
       13. Your       address    is <jsp:getProperty          name=HuserH       property=HaddrH              I>
       14. <% if       (user.isValid(»          {%>You    are valid!<%       } %>


       Quais declarações são verdadeiras? (Escolha todas as que se aplicam.)

       IilA.  As linhas 11 e 12 (e nenhuma outra) contêm exemplos de elementos EL.
       IilB. A linha 14 é um exemplo de código scriptlet.
       O   C. Nenhuma das linhas deste exemplo contém um template text.
       O D. As linhas 12 e 13 incluem exemplos de ações-padrão JSP.
       O   E. A linha 11 demonstra o uso incorreto da EL.
       Iil F. Todas as quatro linhas deste exemplo seriam válidas em uma página JSP.

                      - ft ópj4ó C e5-/-; t"lc,u'l"e-/-a;IUJI"'1/le/-ódo.5 45 '1pa-/-l"ó11"t.uflJsslle/WIkIYlf'14k
                                                                    -                                                        kx-/-.
                      - ft IJPf4ó P e5-/-: tIlCIJt'l"ff~ pól"flle a Íli7t.a 12 1l41Jli7cllllll/WIa4f4rrpaJI"41J JsP,
                      - ft IJPf4ó ~ es+: Ii7CIJI"N':+4;  plJl"'Il'e 4 f.L i?4 ili7t.4  é V:II(J4.


  12   Qual tag JSP exibirá o parâmetro de inicialização de contexto chamado
       "javax.sql.DataSource"?                                                                   <.JsPv 2.0;       p~.
       O   A.   <%=   application.getAttribute           ("javax. sql.DataSourceH)               %>
       IilB.<%=       application.getlnitParameter("javax.sql.DataSourceH)                              %>
       OC.<%=         request.getParameter("javax.sql.DataSourceH)                      %>

       O   D. <%=     contextParam.get("javax.sql.DataSourceH)                    %>         -    ft
                                                                                                   IJft/à.óg /WIós-/-t'O, 6lsó
                                                                                             ClJl"I"ffó dó ótJe+ó I'''''pll(:l1-ó
                                                                                             appllca+lói?




  13   Quais declarações sobre desabilitar elementos scripting são verdadeiras?

       (Escolha todas as que se aplicam.)                                                    <.JSPv2.0;           se{itJ   3.3.3)
       O A. Você não pode desabilitar scripting via DD.
       O B. Você só pode desabilitar scripting no nível da aplicação.
       O C. Você pode     desabilitar scripting programaticamente, utilizando o
           atributo de diretiva de página isScriptingEnabled.
       Iil D. Você pode desabilitar scripting via DD usando o elemento
           <scripting-invalid>.
                                                                 - ~cê s: pó"e desdllt+o.l"           ele/WIel'/+tJs
                                                                                                                   SCl"ip-hi75
                                                                peló PP. () ele/WIel7+ó <JsP-pl"ópel"-/-yróllf>
                                                                pósslbNt+a 311e.tesablltk/WIós 5CI"I.,:';:'''5 4'51117S
                                                                                                                e.••
                                                                Jsps; deltl7,i7,,(tlpaeil";es eie fJ/(Ls pal"IJ.Sí!N!/WI
                                                                ,,(esa!;tlt+a,,(as.



340    capítuío 7
usando oJSP




14   Em     seqüência, quais são os tipos Java para os seguintes objetos implícitos
     JSP:application,out,request,response,session?

     o     A. java. lang. Throwable
           java.lang.Object
           java.util.Map
           java. util. Set
           java.util.List

     O     B. javax.servlet.ServletConfig
           java. lang. Throwable
           java.lang.Object
           javax.servlet.jsp.PageContext
           java.util.Map

     ~c.      javax.servlet.ServletContext
           javax.servlet.jsp.JspWriter                            - IJ: 6pf';a   e
                                                                                 "'1J$+~a I) +SiM
           javax.servlet.ServletRequest                           de cada IJtje+1J ,....,.lIet+lJ.
           javax.servlet.ServletResponse
           javax.servlet.http.HttpSession

     O     D. javax.servlet.ServletContext
           java.io.PrintWriter
           javax.servlet.ServletConfig
           java.lang.Exception
           javax. servlet.RequestDispatcher




15   Qual das opções representa um         exemplo      da sintaxe usada para importar
     uma    classe em um       JSP?                                                       (JsPv2.0jp~, l-t/t/)
     DA. <%         page    import="java.util.Date"        %>
                                                                  - fJr$ IJpfaes lJr e b $';IJ lnv'lit1asj       P<31'3l1e
     OB.<%@          page    import="java.util.Date"        @%>   ape'ltl.S as declIJ.1"4jaes Jav(J, pade'"         vrl" el1+l'f!
     ~c.<%@         page     import="java.util.Date"        %>    (J,S+f4js <% ••. %:>.
     CJD.<%         import    java.util.Date;      %>             - rr 11.     "'e; f! I) lIPirCI)f!Xf!"'P'1)
                                                                           "pj44           ,                                   "
                                                                  sli,+tlJ<:e cl)l"l'e+a.
     O     E.<%@     import    file="java.util.Date"       %>
                                                                  -fJr            f.é



16   Dado       o JSP:

     1. <%@ page           isELIgnored="true"      %>
     2. <%@       taglib     uri=~http://java.sun.com/jsp/jsyl/core''
     pre:fix="c" %>
     3. <c:set var="awesomeBand"                value="LIMOZEEN"/>
     4.    ${awesomeBand}

     Qual será a saída?                                              - 0pf';a IJ:: (J, expl"f!SS';1) f.L. é 'nl)f'lldlJ.   e
                                                                     p4S$all -h:X+V41"'f!n-h:.
     ~ A. $ {awesomeBand}
     O     B. LIMOZEEN
     O     C.   Nenhuma      saída
     O     D. Uma     exceção será enviada porque todas as diretivastaglibdevem
           preceder qualquer diretivapage.

                                                                                             você está                ~      341
8 JSf sem scdpts

                Páginas sem scripts




    Fuja do scripting. Será que seus webdesigners precisam mesmo saber
    Java? Isso é justo? Será que eles pensam que quem programa em Java
    para servidores tornar-se-á, digamos, designer gráfico? E mesmo que a
    equipe seja só você, você quer mesmo um monte de bits e pedaços de
    códigos Java nos seus JSPs? Você sabe o que significa "um pesadelo
    na hora da manutenção"? Escrever páginas sem scripts não só é
    possível, como é mais fácil e mais flexível com a nova especificação
    JSP 2.0, graças à nova Expression Language (EL). Padronizada depois
    do JavaScript e do XPATH, os webdesigners sentir-se-ão em casa com
    a EL. E você também vai gostar (assim que você se acostumar). Porém,
    existem algumas armadilhas ... a EL se parece com o Java, mas não é.
    Às vezes, a EL se comporta de forma diferente de como comportar-se-ia
    a mesma sintaxe no Java. Portanto, fique atento!



                                                       este é um novo      ~   343
objetivos do exame oficial da Sun




Construir páginas JSP usando a                       Notas sobre a Abrangência:
Expression Language (EL) e as
Ações-padrão
                                                     Todos os objetivos sobre este assunto são
                                                     abordados completamente neste capítulo. E ele
7.1 Escrever um código snippet usando                é bem grande! Vá devagar neste capítulo, pois
    variáveis de alto nível na EL. Isto              temos muitos detalhes minuciosos a encarar.
      inclui as seguintes variáveis implícitas:
      pageScope, requestScope, sessionScope e
      applicationScope; param e param Values;
      header e headerValues; cookies e initParam.

7.2 Escrever um código snippet usando os seguintes
    operadores EL: property access (o operador".")
    e collection access (o operador "O").
7.3 Escrever um código snippet usando os
    seguintes operadores EL: operadores
    aritméticos, operadores relacionais e
    operadores lógicos.
7.4 Para funções EL: escrever um código snippet
    usando uma função EL; identificar ou criar a
    estrutura de arquivos TDL usada para declarar
    uma função EL; e identificar ou criar um
    código exemplo para definir uma função EL.
8.1    Dado um objetivo de projeto, criar um
      código snippet usando as seguintes
      ações-padrão: jsp:useBean (com os
      atributos "id", "scope", "type" e "class"),
      jsp:getProperty e jsp:setProperty (com
      todos os atributos combinados).
8.2 Dado um objetivo de projeto, criar um
    código snippet usando as seguintes ações-
    padrão: jsp:include, jsp:forward e jsp:param.
6.7 Dado um objetivo de projeto específico para
    a inclusão de um segmento JSP em outra
    página, escrever um código JSP que use o         Neste capítulo, vamos falar de AMBOS os
    mecanismo de inclusão mais apropriado            mecanismos de include: o <jsp:include>, citado
    (a diretiva include ou a ação-padrão             no objetivo 8.2, e a diretiva de página include,
    <jsp:include».                                   mencionada no objetivo 6.7 (a maioria dos
                                                     objetivos da seção 6foi abordada no capítulo
                                                     anterior sobre JSPs).


344              8
JSP sem scripts



Nossa aplicação MVC depettde dos atributos
Lembra na aplicação MVC original da cerveja, o Servlet controlador
interagia com o modelo (classe Java com a lógica do negócio) e criava
um atributo no escopo da solicitação antes de enviá-Ia à view JSP.
O JSP tinha que receber o atributo do escopo da solicitação e usá-Io para
gerar a resposta que seria enviada de volta ao cliente. Eis uma olhada
rápida e simplificada de como o atributo vai do controlador para a view
(imagine que o servlet se comunique com o modelo):

Código do servlet (controlador)
   public         void    doPost(HttpServletRequest                           request, HttpServletResponse    response)
                                                                                   throws IOException,  ServletException


             String         name       = request. getParameter                   ("userName")            _      usa o f{).,,:!i,:e+ro Je :>o/l'<::l+(u;';e
             request. setAttribute                         ("name", name);                               ~      de fef'h<íllb.l'ió Pb.I't1.Cl'iiu'


                                                                                                                S(;;ltCl';"o.g';o3í1f! esc"1M da
                                                                                                                <}a.+••l"v+o d~ tJ tJSP uSQ.":,


             RequestDispatcher                      view           request.getRequestDispatcher("/result.jsp");

             view. forward (request,                         response);                           ~                     t~,:o.*I~j~Q.a

                                                                                                                        fttu"t<   a vlew.




Código JSP (view)
   <html><body>                                                               Use "'*,4 eXft'ess';ó          Je sct'i'p+'~5       po.t'f!. 6b+ef'   <l
   Hello                                                                      o.+t'lbll+/'J   e exlbr-Io.    J'lo.resfos+o..
   <%= request.getAttribute("name")                                      %>
   </body></html>                                                             (t...el>lbl'e-se:       as express6es      Je sCl'tp+I~5

                                                                              SíWIt'i         o o.f'5f.1h<fl'l+Ó ptU'o. " h<H-eJ"




  Heno Paul


      '                                             f.I          n
           ef'a   c VIJ,/{)f' IIl"   o.+r"bl.ll-"          J'lfJ.h<e •




                                                                                                                        você está aqui              iI>   345
atributos non-Stríng



Mas, e se o atributo t'lão for utta Strit'lg, e
sitt utta it'lstât'lcia de Persot'l?
E não só uma Person, mas uma Person com uma
propriedade "name". Estamos usando o termo
"propriedade" na forma do JavaBean* não-enterprise
- a classe Person tem o par de métodos getNameO e
setNameO, que de acordo com a especmcação do JavaBean
quer dizer que Person tem uma propriedade chamada
"name". Não se esqueça de que a propriedade "name"
requer que a primeira letra, "n", seja alterada. Em outras                                  foo.Person
palavras, o nome da propriedade é o que você obtém ao
retirar o prefixo "get" ou "set" e transforma em minúscula
                                                                      publico String
a primeira letra subseqüente. Portanto, getName/setName
vira simplesmente name.                                               public void setName(String)




o código     servlet
   public    void       doPost(HttpServletRequest   request, HttpServletResponse    response)
                                                         throws IOException,  ServletException

            foo.Person p = new foo.Person();
            p.setName(~Evan");
            request.setAttribute(~person",   p);

            RequestDispatcher    view = request.getRequestDispatcher("result.jsp");
            view.forward(request,    response);




o código     JSP

    <htrnl><body>
    Person is: <%= request.getAttribute(~person")            %>
    </body></htrnl>

o que    QUEREMOS:                                        O que CONSEGUIMOS:


                                                           Person is: foo.
 Person is: Evan
                                                           Person@512d66


                                                                  01..••• (;bvtQIllf!"Jff    Q eXpl'eSS4lJ
                                                                                    /,~            ...
                                                                  d,QlIIlJ/I lJ IIIf'T'(;d(;7,aJI'Q(;

                                                                  +".5-htl'ljQ      d{J 4+1'1"11/1+(;
                                                                                                   •••


*Falaremos sobre JavaBeans daqui a pouco, mas por enquanto, tenha em mente que ele é só uma
classe Java simples, cujos getters e setters obedecem a uma convenção de nomes.

346                 8
JSP sem scripts



PrecisatMos de tMaiscódigo para obter o "atMe de Perso"
Enviar o resultado do getAttributeO para a declaração de exibir/escrever
não nos dá o que queremos - isto só roda o método toStringO do objeto. E
já que a classe Person não anula o ObjecttoStringO que foi herdado, bem,
você sabe o que acontece. Mas nós queremos exibir o name de Person.

o código    JSP

   <htrnl><body>

   <% foo.Person p = (foo.Person)             request.getAttribute(~personff);             %>
   Person is: <%= p.getName()  %>


   </body></htrnl>           ~ "'-.....   'xi"!;e
                                          c         <l   t"es;;!-rad<l
                                                                  J



                                          de je+AJo.!t'leO.



OU usando uma expressão

   <htrnl><body>

   Person   is:
   <%= «foo.Person)      request.getAttribute(~personff»                 .getName()   %>

   </body></htrnl>

                     o que   RECEBEMOS:



                       Person is: Evan




                  Mas aí recordamos aquele LEMBRETE ...
                     Aquele que pode ser resumido em
                              "Use Scripts e Morra"
                        Precisamos de outra técnica.




                                                                                       você está        ••   347
JavaBean ações padrão



Penot1    é UtMJavaJeat1,        logo, usaretMos
ações-padrão       de beat1
Com duas ações-padrão podemos elinllnar todo o script
do nosso JSP (lembre-se: o scripting inclui declarações,
scriptlets e expressões) e ainda exibir o valor da
propriedade name do atributo person. Não se esqueça
de que name não é um atributo - apenas o objeto
person é um atributo. A propriedade name é apenas
aquilo que é retomado do método getNameO de Person.




                                                            f                        s1-;;'w,os
Sem ações-padrão         (usando scripting)
                                                            t aS stw, fllle     f-


    <html><body>                                                //)."/''lil.o

   <% foo.Person p = (foo.Person)           request.getAttribute(~person");                            %>
   Person is: <%= p.getName()  %>

    </body></html>




Com ações-padrão         (sem scripting)

    <html><body>
   <jsp:useBean      id="person"       class="foo.Person"        scope="request"                  />
    Person   created   by   servlet:    <jsp:getProperty    name="person"                  property="name"   />
    </body></html>




348 capítulo 8
JSP sem scripts




At1alisat1do a <jsp:use&eat1> e a <jsp:getProperty>
Tudo o que realmente queríamos era a funcionalidade do <jsp:getProperty>,
pois queríamos apenas mostrar o valor da propriedade "name" de person. Mas
como o Container saberá o que quer dizer "person"? Se tivéssemos no JSP
apenas a tag <jsp:getProperty>, seria praticamente como se usássemos uma
variável não declarada chamada "person". O Container geralmente não faz
idéia do que você está falando, a menos que você inclua na página PRIMEIRO
uma <jsp:useBean>. A <jsp:useBean> é uma maneira de declarar e inicializar
o objeto bean real que você está usando em <jsp:getProperty>.




Declarando e inicializando um atributo bean com <jsp:useBean>

                                                                                              scope="request"/>




Obtendo o valor da propriedade          de um atributo bean com <jsp:getProperty>


   <jsp:getProperty              name="person"                              property="name"                                 -
                                                                                                                            />



                                                                            ~   Itiel1+f-lica
                                                                                                   T  é 11"lI'IetJa f'l'éfl'letJe.Gle
                                  IGleJ1h"ftco.    ti é~e-I-6 bellJ1
                                                                                (w S~1t.J               &l.IefÓS SlIr ti 5eml' e
                                                                                                1J.31.1tló
                                  relll, IS+";ftliJJCftiil':      Ctlll'l       seffll"       "lI! classe !;ee."l).
                                  " vali;;" tie    M     tilJl +1JlJ
                                                                                                                          u                //
                                                                                Alc+o.: eS+4 pl"épl'fetJt!tJe                11t:ll'le
                                  9Sf:I.IS(~5ea,,>.
                                                                                'l"ic ~"      J1fttlt: ~yel'       CCIl'lc fetilJ,jfJ
                                                                                'ltllll'le=fersa"!             tJes+tlI +1JlJ.
                                                                                1Jip;.cfl"ietiIJ.tie         ct.all'la- se 'lll"Xe

                                                                                Si'''''Plesil'le''rf-e fJ/?:I"Séll'/ tli ttleli'I'/i'tltl..
                                                                                CC"X" 11 dllss/?: eal' CIJ,I./SllllJ,-Iél'lI'IiI.
                                                                                                                   I




                                                                                                        você está                    to-        349
<jsp:useBean>




A <jsp:useJea.,>        tatMbétM pode CRIAR UtMbea.,!
Se <jsp:useBean> não puder encontrar um objeto atributo
chamado "person", ele pode construir um! É parecido com
a forma com que request.getSessionO (ou getSession(true))
funciona: ele primeiro procura por algo existente, mas caso não
o encontre, ele cria um.
Observe o código do servlet gerado e você verá o que está
acontecendo - tem um teste iflá! Ele procura por um bean
baseando-se nos valores de id e escopo na tag, e se não encontrar
um, ele cria uma instância da classe especificada em class,
atribui o objeto à variável id e a configura como um atributo no
escopo que você definiu na tag.



Esta tag


   <jsp:useBean id="person"                                class="foo.Person"
   scope="request" />

Transforma-se neste código no método -JspService()
                                                            !JedlJ.t'tJ. (/#a VlJf'i~';I'el baSfltJ.i'1,;/ó-se '1ó vu.lifJl'   de M,
    foo.Person     person   null; ~                          i es+tJ. V4t'I{.vel       3ve pet'lOl-+e 3ve

                                                             dó   sev JSP<.tp/clvslve                 (w+NJ.$    +~s       de
    synchronized     (request)   {                           N:flt'4#     4 eM.•




      person = (foo.Person)
   REQUEST _ SCOPE) ;
                                     jspx_page
                                                         ç.          1é11+a e/;+et'

                                                                             r
                                                                     v 1I1J.1'1(;.vel
                                                   context.getAttribute(nperson",

                                                                           AI
                                                                                            <)




                                                                     il<)cê ,;/ef,),lllM. '11<
                                                                                                 1J.+t'l!Jv+tJ P/li escilpiJ


                                                                                                  +~e o.+t'í"J,l/l     e
                                                                                                                PageContext.



                                                        JlA./tS; se AJ/ttJ I.,wllet' 11#
      if   (person      null) { ~                       i1<)lOe esclJp<)",
                                                                I1tJ




           _jspx~age_context.setAttribute(nperson",                       person,           PageContext.REQUEST_SCOPE);


                                        ~        ç:,),lJ.lhle~;      c<)p/fljf.lt'e   IJ   11<)';1'<)
                                                                                                  lIfJe-I-fJ ctJlOfJ1110
                                                    •        J                                   '"
                                                 lJ.+d!;v-rtJ     '1ó esc"pfJ ave vlIce tlefi'J'llll.




350 capitulo 8
JSP sem scripfs




 Isto pode ser uma coisa ruim
 - eu não QUERO ter um bean
 que não tenha seus valores de
propriedade configurados! Se o
Container cria um bean usando
  essa tag, o bean não terá
  valores de propriedade ...




                 Você pode usar a <jsp:setProperty>
                 Mas você já sabia que onde existe um get geralmente existe um set. A tag
                 <jsp:setProperty> é a terceira e última ação-padrão bean. É simples de usá-Ia:

                     <jsp:useBean   id="person"    class="foo.Person"    scope="request"      />
                     <jsp:setProperty    name="person"   property="name"   value="Fred"      />




                                                                        você está aqui...    351
<jsp:useBean>         com um      CO!PO



                                                                              Com o corpo de uma
A <jsp:useJeat1> pode ter Uitcorpo!                                          <jsP:UseBean>, você pode ter
Se você puser seu código set (<jsp:setProperty»   dentro do                   um CÓdigo que rode de forma
                                                                              Condicional. ••
corpo de <jsp:useBean>, a configuração da propriedade
torna-se condicional! Ou seja, os valores da propriedade                     SOMENTE se o atributo
serão configurados apenas se um nov
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets
Use a cabeça   jsp & servlets

Mais conteúdo relacionado

PDF
Use a Cabeça! Python_Português.pdf
PDF
Use a Cabeça Java - 2ª Edição.pdf
PDF
Aprendendo Kotlin na Prática
DOC
Minuta arrendamento opcao_compra
PPTX
Aspectos psicologicos do paciente oncológico
PDF
ONCOLOGIA
PPTX
Oncologia Enfermagem
PPTX
Diabetes Mellitus
Use a Cabeça! Python_Português.pdf
Use a Cabeça Java - 2ª Edição.pdf
Aprendendo Kotlin na Prática
Minuta arrendamento opcao_compra
Aspectos psicologicos do paciente oncológico
ONCOLOGIA
Oncologia Enfermagem
Diabetes Mellitus

Mais procurados (20)

PPTX
Doença celíaca
PPSX
Apresentação hipertensão
PPTX
Anemia e sindrome nefrótica
PPT
Propedeutica abdominal
PPTX
Aula 04 Semiologia Aparelho Respiratório.pptx
DOCX
teste-excel-pratico
PPTX
Aula 01 - Ms PowerPoint
PPTX
Monitorização da função pulmonar
PPTX
Síndromes vestibulares
PPTX
Informatica Básica - Sexta Básica
ODP
SLIDE SOBRE O LIBREOFFICE
PDF
Sinais meningeos 20
PPTX
Dor Torácica.pptx
PPTX
PACOTE OFFICE.pptx
PDF
Asma (Pediatria)
PPT
Semiologia vascular periférica
DOC
Fichas tecnicas promimp
PPT
Exame Neurológico: Tipos de Afasia
DOC
Semiologia questões e respostas
PDF
Fundamentos de armazenamentos de dados
Doença celíaca
Apresentação hipertensão
Anemia e sindrome nefrótica
Propedeutica abdominal
Aula 04 Semiologia Aparelho Respiratório.pptx
teste-excel-pratico
Aula 01 - Ms PowerPoint
Monitorização da função pulmonar
Síndromes vestibulares
Informatica Básica - Sexta Básica
SLIDE SOBRE O LIBREOFFICE
Sinais meningeos 20
Dor Torácica.pptx
PACOTE OFFICE.pptx
Asma (Pediatria)
Semiologia vascular periférica
Fichas tecnicas promimp
Exame Neurológico: Tipos de Afasia
Semiologia questões e respostas
Fundamentos de armazenamentos de dados
Anúncio

Semelhante a Use a cabeça jsp & servlets (20)

PDF
Use a Cabeça - PHP.pdf
PDF
Guia JEE com Frameworks
DOC
Dicas para fazer um bom trabalho
PPT
Produção de texto coletivo
DOC
Narrativa+em+capitulos
PPTX
Edilça
PPTX
Situação de aprendizagem avestruz
PPTX
Situação de aprendizagem avestruz
PPTX
Situação de aprendizagem avestruz
PPT
Qual a melhor forma para estudar em casa?
PPT
Qual a melhor forma para estudar em casa?
PPTX
Meu primeiro beijo power
PPTX
Meu primeiro beijo !
PDF
Orientações sobre as atividades de alfabetização módulo 1
PPT
Webquestsexualidade
PDF
Análise de Incidências no ENEM
PPT
Como fazer um trabalho de pesquisa
DOCX
Como escrever bem para blog
PPTX
Meu primeiro beijo power
PPTX
Meu primeiro beijo !
Use a Cabeça - PHP.pdf
Guia JEE com Frameworks
Dicas para fazer um bom trabalho
Produção de texto coletivo
Narrativa+em+capitulos
Edilça
Situação de aprendizagem avestruz
Situação de aprendizagem avestruz
Situação de aprendizagem avestruz
Qual a melhor forma para estudar em casa?
Qual a melhor forma para estudar em casa?
Meu primeiro beijo power
Meu primeiro beijo !
Orientações sobre as atividades de alfabetização módulo 1
Webquestsexualidade
Análise de Incidências no ENEM
Como fazer um trabalho de pesquisa
Como escrever bem para blog
Meu primeiro beijo power
Meu primeiro beijo !
Anúncio

Use a cabeça jsp & servlets

  • 1. "Sôci'êdade de Ensino Sunerior da PamffJa Elogios antecipados para o Use a Cabeça! Servlets & JSpTM "Este livro, Use a Cabeça! Servlets & JSP, é tão bom quanto o Use a Cabeça! EJB, que me fez rir E me garantiu 97% de aproveitamento na prova!" - Jef Cumps, Consultor de J2EE, Cronos "Para nossas aulas de Servlet/JSP, nós compramos mais de dez livros, sem encontrar nenhum, de fato, satisfatório para nossas necessidades de ensino ... Até que encontrarmos esta 'jóia' pedagógica que você tem agora nas mãos! Os livros da série Use a Cabeça! nos tornaram melhores professores." - Philippe Maquet: Instrutor Sênior da Loop Factory, Bruxelas Elogios para o Use a Cabeça! EJBTM e para o formato da série Use a Cabeça! "A tecnologia Java está em todos os lugares - em telefones celulares, carros, câmeras, impressoras, jogos, PDAs, ATMs, smart cards, bombas de gasolina, estádios, equipamentos médicos, webcams, servidores, você escolhe. Se você desenvolve software e não conhece Java, definitivamente, está na hora de você mergulhar de cabeça - Use a Cabeça!." - Scott McNealy, Chairman, Presidente e CEO, Sun Microsystems (Nota do departamento de marketing: isto foi o melhor que você conseguiu do Scott? Veja se consegue fazer com que ele acrescente algo do tipo: "Se nós tivéssemos os livros da série Use a Cabeça! há dois anos, ainda podíamos ter aquela ilusão ...'~). "Um livro incrivelmente agradável. Dividido e interconectado como uma rede de conhecimentos. Como professor da Purdue University, com especialização em desenvolvimento avançado de software utilizando tecnologias baseadas em Java, estou em constante busca por materiais de apoio que ofereçam motivação e uma linguagem compreensiva direcionada para o exame, mas que ao mesmo tempo não desestimulem os alunos. O livro 'Use a Cabeça! EJB' preenche estes requisitos facilmente! Livros como estes são extremamente raros. Incluí este livro como um dos textos essenciais para as futuras turmas do curso de graduação avançada que eu dou de 'Desenvolvimento de Aplicações para Empresas'. Parabéns para os autores; continuem com o excelente trabalho!" - Professor Dan Gill, Departamento de Tecnologia de Computadores, Purdue University. "Além do estilo envolvente que o levará do nível de leigo ao status de guerreiro aclamado no Java, o livro Use a Cabeça! Java traz um grande número de questões práticas, que outros títulos tratam como o temível 'exercício para o leitor ... ' Ele é inteligente, irônico, descolado e prático - existem poucos livros com estas características e que são capazes de ensinar sobre serialização de objetos e protocolos de execução em rede ao mesmo tempo." - Dr. Dan Russel, Diretor de Pesquisas Experimentais e Científicas com Usuários, IBM Almaden Research Center (e professor de Inteligência Artificial na Stanford University). Que maneira maravilhosa de aprender!!! EU NÃO CONSIGO LARGAR ESTE LIVRO!!! Meu filho de 3 anos acordou à Ih40 da manhã, e eu o colÇ>queide volta na cama segurando o livro e uma lanterna, e continuei lendo por mais uma hora. - Ross Goldberg "O Use a Cabeça! Java, escrito por Kathy e Bert, dá às suas páginas impressas uma aparência GUI como você jamais viu. De um jeito diferente e descolado, os autores transformam a aprendizagem em Java em uma empolgante experiência, do tipo 'qual será a próxima surpresa?'" .- Warren Keuffel, Revista Software Development.
  • 2. Parabéns pelo formato Use a Cabeça! "É rápido, irreverente, divertido e envolvente. Cuidado - você pode realmente aprender alguma coisa!" - Ken Arnold, ex-Engenheiro Sênior da Sun Microsystems e co-autor (com James Gosling, criador do Java) do livro "The J ava Programming Language" "Eu passei no exame SCBCD com 94% de aproveitamento. Realmente, o 'P! EJB' é demais! Eu li o livro todo em 10 dias ..." - Basavaraj Devershetty ( " ... a única maneira de saber o valor de um tutorial é saber se ele realmente ensinará bem. Use a Cabeça! Java é excelente para ensinar. Tudo bem, eu pensei que ele fosse bobinho ... mas, me dei conta de que estava aprendendo os tópicos totalmente, à medida que avançava pelo livro." "O estilo do Use a Cabeça! Java tomou meu aprendizado, digamos, mais fácil." - slashdot (análise do site honestpuck) "Eu jamais poderia imaginar que alguém pudesse rir enquanto lesse um livro de TI! Usando o material do Use a Cabeça! EJB eu consegui uma ótima pontuação (91 %) e estabeleci um recorde mundial como o mais jovem SCBCD, com 14 anos de idade." - Afsah Shafquat (o mais novo SCBCD do mundo) "Esse livro é tão bacana que me deu vontade de CHORAR! Estou chocado." - Floyd Jones, Escritor Técnico Sênior/Garoto da piscina, BEA "Se você quer aprender Java, não procure mais: bem-vindo ao primeiro livro técnico com características GUI! Com seu formato revolucionário e elaborado com perfeição, o livro oferece vantagens que outros títulos sobre Java simplesmente não conseguem ... Prepare-se para um passeio realmente extraordinário pelo universo Java." - Neil R. Bauman, Diretor Executivo e capitão da Geek Cruises (www.GeekCruises.com) "Se existe alguém no mundo familiarizado com o conceito do 'Use a Cabeça!', este sou eu. Este livro é tão bom que eu me casaria com ele na TV!" - Rick Rockwell, comediante. O noivo original do programa "Quem Quer Se Casar com um Milionário?" ("Who Wants to Marry a Millionaire"), da FOX Television "O Use a Cabeça! Java é como o Monty Python meets the gang offourl ... o texto está tão bem dividido entre quebra-cabeças e histórias, questionários e exemplos, que você obtém uma abrangência quehenhum livro de informática conseguiu até agora." - Douglas Rowe, Comunidade de Usuários de Java, Columbia. "'Use a Cabeça! Java' ... dá um novo significado à frase de marketing da O'Reilly: 'Existe um O'Reilly para isso'z. Eu o escolhi, pois muitas outras pessoas que eu admiro o classificaram como 'revolucionário' e eu descrevi uma técnica totalmente diferente para este livro. Eles estavam (estão) certos ... Sem fugir do típico formato da O'Reilly, eles conseguiram um formato científico, mas bem aceito. O resultado é divertido, irreverente, atuiü, interativo e brilhante ... A sensação de ler este livro é a de estar sentado bem próximo aos alto-falantes em uma sala de reunião, aprendendo - e rindo - com os colegas ... Se você quer ENTENDER Java, compre logo o seu." - Andrew Pollack, www.thenorth.com
  • 3. Sociedade de Ensino Superbr da Paat1ira "Lembra quando você estava no jardim de infância? Não? Bem, e quando você aprendeu pela primeira vez o alfabeto? É dificillembrar? Bem, não faz mal. Lendo o Use a Cabeça! lava, você vai voltar a se divertir enquanto aprende ... Para aqueles que se interessam por aprender novas linguagens de programação e não vieram da área de ciência da computação ou da programação, este livro é uma preciosidade ... Ele torna divertido o aprendizado de uma linguagem dificil de computação. Espero que existam mais autores interessados em quebrar o velho e corriqueiro modelo 'tradicional' do estilo de escrever. Aprender linguagens de computação deveria ser prazeroso e não oneroso." - Judith Taylor, Comunidade de Usuários da Maeromedia, Southeast Ohio. "Há poucos dias, recebi minha cópia do Use a Cabeça! lava, de Kathy Sierra e Bert Bates. Eu ainda estou no começo do livro, mas o que me encantou foi que, mesmo estando com sono naquela primeira noite, me peguei pensando: 'tudo bem, só mais uma página e vou dormir.'" - JoeLitton "FINALMENTE, um livro de lava escrito tal qual eu escreveria se tivesse sido eu. Falando sério, este livro simplesmente arrasa qualquer outro livro de software que eujá li... É muito dificil escrever um bom livro ... É preciso muito tempo para explicar os assuntos, em uma seqüência natural e cujo foco é o leitor. É muito trabalho. Muitos autores, notoriamente, não estão prontos para o desafio. Parabéns à equipe do Use a Cabeça! EJB por este trabalho primoroso! P.S. Quando vai sair o projeto Use a Cabeça! l2EE? E o Use a Cabeça! Desenvolvedor de Componentes para a Web? E como eu faço para que meu videocassete grave umjogo de futebol enquanto estou trabalhando?" - Wally Flint "Se você é relativamente um iniciante em programação e está interessado em lava, eis o seu livro ... Abordando tudo - desde objetos para a criação de interfaces gráficas de usuário (GUl),tratamento de exceções (erros), redes (sockets) e multitarefas, até como agrupar suas pilhas de classes em um único arquivo de instalação -, este livro é completíssimo ... Se você gostar do estilo, estou certo de que irá adorar o livro assim como eu. Espero que a série Use a Cabeça! possa ser estendida a vários outros assuntos!" - LinuxQuestions.org "Quando eu li o 'Use a Cabeça! lava', do mesmo autor, eu pensei que é impossível escrever outro livro (aquele sobre EJB também) de uma forma tão brilhante. Porém, agora eles nos surpreenderam com este livro ainda mais legal. Os livros da série Use a Cabeca! tornaram-se algo necessário (QUASE UMA EXIGÊNCIA) em todos os assuntos. Eu queri~ ser uma criança para poder aprender tudo da maneira como ensina este livro." - Anshu Mishra Eu trabalhei com EJB há cerca de 4 anos e o achei uma bagunça às avessas. Depois de ler as especificações 2.1 e 2.0, eu descobri que é apenas uma t*** 3 fumegante que ficou maior. Seu livro respondeu à maioria das incontáveis perguntas que martelavam meu cérebro de amendoim e permitiu- me passar na prova com uma pontuação de 92% ... Vencendo facilmente aquele colega de 14 anos de idade por 1 ponto. :-) Muito obrigado. - Jim Steiner "Eu me VICIEI nos contos do livro, nos códigos com anotações, nas entrevistas preparatórias e nos exercícios para o cérebro." - Miehael Yuan, autor, Enterprise J2ME
  • 4. se a Cabeca Servlets ...:> & JSPTM Segunda Edição Não seria fantástico se existisse um livro sobre Servlets que fosse mais interessante do que apagar spam da sua caixa de mensagens? Talvez isso seja uma ilusão ... Bryan Basham Kathy Sierra Bert Bates Rio de Janeiro.2008
  • 5. Use a Cabeça Servlets & JSpTM © Alta Books Editora - Starlin Alta Con Com Ltda 2008 Do original Head First Servlets and JSPTM. Authorized translation of the English edition of Head First Servlets and JSPTM 2st Edition © 2008 O'Reil/y , Media,lnc. ISBN: 978-0596102340 This translation is published and sold by permission ofO'Reil/y Media, Inc., the owner of ali rights to publish and sell the some. Todos os direitos reservados e protegidos pela Lei 5988 de 14/12/73. Nenhuma parte deste livro, sem autorização prévia por escrito da editora, poderá ser reproduzida ou transmitida sejam quais forem os meios empregados: eletrônico, mecânico, fotográfico, gravação ou quaisquer outros. Todo o esforço foi feito para fornecer a mais completa e adequada informação, contudo a editora e o(s) autor(es) não assumem responsabilidade pelos resultados e usos da informação fornecida. Recomendamos aos leitores testar a informação, bem como tomar todos os cuidados necessários (como o backup), antes da efetiva utilização. Este livro não contém CD-ROM, disquete ou qualquer outra midia. Erratas e atualizações: Sempre nos esforçamos para entregar a você, leitor, um livro livre de erros técnicos ou de conteúdo; porém, nem sempre isso é conseguido, seja por motivo de alteração de software, interpretação ou mesmo quando alguns deslizes constam na versão original de alguns livros que traduzimos. Sendo assim, criamos em nosso site, www.altabooks.com.br. a seção Erratas, onde relataremos, com a devida correção, qualquer erro encontrado em nossos livros. Avisos e Renúncia de Direitos: Este livro é vendido como está, sem garantia de qualquer tipo, seja expressa ou implícita. Marcas Registradas: Todos os termos mencionados e reconhecidos como Marca Registrada e/ou comercial são de responsabilidade de seus proprietários. A Editora informa não estar associada a nenhum produto e/ ou fornecedor apresentado no livro. No decorrer da obra, imagens, nomes de produtos e fabricantes podem ter sido utilizados, e desde já a Editora informa que o uso é apenas ilustrativo e/ou educativo, não visando ao lucro, favorecimento ou desmerecimento do produto/fabricante. Produção Editorial: Editora Alta Books Coordenação Editorial: Roberto Baptista Barroco Tradução: Eveline Vieira Machado Revisão: Fernanda Rigamond Revisão Técnica: Helder Borges Diagramação: Equipe Alta Books Impresso no Brasil o código de propriedade intelectual de 10 de Julho de 1992 proibe expressamente o uso coletivo sem autorização dos detentores do direito autoral da obra, bem como a cópia ilegal do original. Esta prática generalizada nos estabelecimentos de ensino, provoca uma brutal baixa nas vendas dos livros a ponto de impossibilitar os autores de criarem novas obras. Editora Alta Books Rua Viúva Claudio, 291 - Jacaré Rio de Janeiro - RJ CEP 20551-010 Tel: 21 3278-8069 Fax: 21 3277-1253 www.altabooks.com.br altabooks@altabooks.com.br
  • 6. Esse livro é dedicado a todos aqueles que decidiram que EL implicit object
  • 7. os autores Os "procurados" da série Use a Cabeça! (e deste livro) Bryan Basham Beart Bates Bert é um antigo desenvolvedor Kathy gosta de teoria da Bryan tem mais de vinte e arquiteto de software, mas aprendizagem e assuntos anos de experiência em um período de 10 anos em relacionados à mente desde a desenvolvimento de software, inteligência artificial o fez época em que era designer de incluindo um período com se interessar por teoria da jogos (ela escreveu jogos para software de automação aprendizagem e treinamento a Virgin, MGM e Amblin') e avançada usando técnicas via computador. Ele passou a desenvolvedora em I.A2 Grande de I.A na NASA Ele primeira década de sua carreira parte do formato da série Use também atuou em uma como desenvolvedor viajando a Cabeça! foi desenvolvido consultoria, desenvolvendo pelo mundo e ajudando clientes enquanto lecionava Interatividade aplicações comerciais em 00 como a rádio Nova Zelândia, Usando Novas Midias, no personalizadas. Atualmente, o The Weather Channel e a programa de extensão de Bryan é Desenvolvedor de rede de entretenimentos Arts Estudos em Entretenimento Cursos da Sun, com ênfase and Entertainment Network da Universidade da Califómia nos princípios de design em (A&E) em suas transmissões. (DCLA). Recentemente, se Java e em 00. Ele já trabalhou Atualmente, ele é membro da tomou instrutora-chefe da em diversos cursos de Java equipe da Sun responsável pelo Sun Microsystems e ensina os da Sun, incluindo JDBC, desenvolvimento de diversos instrutores de Java a divulgarem J2EE, Servlets e JSP, além de exames de certificação em Java, as mais novas tecnologias Desenvolvimento de Software incluindo o recente SCWCD. desta linguagem. Além disso, utilizando 00. Ele foi também Bert é um antigo e incorrigível desenvolve diversos exames o primeiro designer dos exames aficionado pelo GOl e vem para certificações Sun, incluindo SCWCD, nas versões original trabalhando há bastante o SCWCD. Junto com Bert e atual. tempo em um programa. O Bates, ela tem aplicado Bryan pratica o Zen Budismo, Java há de se tomar uma extensivamente os conceitos da joga Ultimate Frisbee, adora linguagem expressiva o série Use a Cabeça! no ensino som e pratica o ski telemark. suficiente para que ele finalize de milhares de desenvolvedores. seu projeto. Ele é um bom Ela fundou uma das maiores guitarrista e, atualmente, está comunidades em Java no experimentando o banjo. mundo virtual, a javaranch. Sua mais recente aventura com, premiada em 2003 e 2004 foi a compra de um cavalo com o Prêmio Produtividade em islandês, o que deverá trazer Desenvolvimento de Software. novos desafios aos seus Ela adora correr, esquiar, montar conhecimentos na área de a cavalo, andar de skate e treinamento ... ciências esotéricas. VIII
  • 8. conteúdo (Sumát19) Introdução XIX Por que usar Servlets & JSPs: uma introdução 1 Arquitetura da aplicação web: visão geral de alto nível 37 Minitutorial do MVC: praticando com o MVC 67 Sendo um servlet: request e resposta 93 Sendo uma aplicação web: atributos e listeners 147 Estado de conversação: sincronizando o bean/entidade 223 Sendo um JSP: escrevendo códigos em JSP 281 Páginas sem scripts: escrevendo JSPs sem scripts 343 As tags customizadas são poderosas: usando a JSTL 439 Quando nem a JSTL é o bastante: desenvolvendo tags customizadas 499 Distribuindo sua aplicação web: distribuição da aplicação web 601 Mantenha em segredo, mantenha seguro: segurança da aplicação web 649 O poder dos filtros: wrappers efiltros 701 Padrões de Design Enterprise: padrões e Struts 737 Apêndice A: TestePreparatório Final 791 Índice 865 Introdução Seu cérebro pensando em Servlets. Aqui está você tentando aprender algo, enquanto seu cérebro lhe presta o favor de certificar-se de que tal aprendizado não será interrompido. Ele pensa, "é melhor reservar espaço para coisas mais importantes, como qual animal selvagem evitar e se esquiar sem roupa é ruim mesmo". Então, como você vai induzi-lo a pensar que sua vida depende do conhecimento em Servlets? A quem se destina este livro? XX Nós sabemos o que seu cérebro está pensando XXI Metacognição XXlll Domine seu cérebrp xxv O que você precisa para este livro XXVI Passando no exame de certificação XXVlll Os revisores técnicos XXX Agradecimentos XXXI IX
  • 9. 1 Por que usar servlets & JSPs? As aplicações web estão na moda. Quantas aplicações GUI você conhece que são usadas por milhões de usuários em todo o mundo? Como desenvolvedor de aplicações web, você não precisará se prender aos problemas de distribuição presentes em toda aplicação standalone e irá distribuir sua aplicação a qualquer pessoa que possua um browser. Mas você precisará dos servlets e dos JSPs, pois as velhas e estáticas páginas HTML são tão, digamos, "1999". Saiba como mudar do sUe na web, para a aplicação na web. Principais elementos do fluxo Objetivos do Exame 2 de solicitação: • O método HTTP (a ação de se~ executada) • A~<rinaqueseráacessada O que os servidores web e os clientes fazem e como conversam • (umaURL) Osp:mi:mctrosdofurmulãrio(curoo entre si 4 argtIIIlell!oSparamnrnéloOO) Guia rápido de HTML 7 solicitação HTTP O que é o protocolo HTTP? 10 A anatomia das solicitações HTTP GET ePOST e das respostas HTTP 16 Localizando páginas web usando URLs 20 Cliente Servidor Servidores web, páginas estáticas e cm 24 Principais elementos do fluxo de resposta: Desmistificando os Servlets: escreva, distribua e rode um servlet 30 • Um código de .umIS (no caso de uma solicitação bem sucedida) TIpo de conteúdo (tc."to, i~oem, HIML, ctc_) JSP foi o que aconteceu quando alguém apresentou o Java ao HTML 34 • O conteúdo (o HTML real, a imagem, etc_) Arquitetura da aplicação web Os servlets precisam de ajuda. Quando uma solicitação chega, alguém tem que instar o servlet ou, pelo menos, alocar uma thread para tratar a solicitação. 2 Alguém tem que chamar ou o método doPostO ou o método doGetO do servlet. Alguém precisa levar a solicitação e a resposta para o servlet. Alguém precisa gerenciar a vida, a morte e os recursos do servlet. Neste capítulo, vamos estudar o Container e dar uma primeira olhada no padrão MVC. Serv!et Objetivos do Exame 38 O que é um Container e o que ele oferece? 39 (Controlador ' Como fica o código (o que toma um servlet um servlet) 44 JSP iJSP 1 Nomeando os servlets e mapeando-os a URLs usando o DD História: Bob Constrói um Site de Encontros (introdução ao MVC) 46 50 JCVQ Visão geral e exemplo de MVC (Model- View-Controller) 54 antigo View Modelo 1, Um Deployment Descriptor (DD) "funcionando" 64 Ba",o de Dad,,, Como o J2EE cabe nisso tudo 65 x
  • 10. conteúdo Minitutorial do MVC 3 Criando e distribuindo uma aplicação MVC. Chegou a hora de colocar a mão na massa e escrever um formulário HTML, um controlador de servlet, um modelo (classe Java simples), um deployrnent descriptor XML e uma view em JSP. É hora de criar, distribuir e testar. Antes, porém, você deverá configurar seu ambiente de desenvolvimento. Em seguida, você terá que configurar o seu ambiente de distribuição, de acordo com as especificações do servlet e do JSP, e as exigências do Tomcat. Concordo, esta é uma aplicação pequena ... Porém, quase NÃO existe aplicação que seja tão pequena e use o MVC. Especffico para o Tomcat Este nome de diretÓf'io root" que o Torncat o •context também representa usa quando estó resolvendo URLs. Nós r::::a ~ ! Esta parte da estrutura de diretórios é exigido Objetivos do Exame 68 exploraremos detalhes conceno em maiores este no copít1Jloobre Distribuição. s l;;;J '-; seu diretónoeablllxo estar ;~ I {' pelo Tomcat diretamente j d~ve do home. Vamos construir uma aplicação MVC: primeiro o design 69 -~8)~_OOOmedaapricação. Criando os ambientes de desenvolvimento e distribuição 72 Criando e testando o HTML para o formulário inicial dos Servlets j- '-' l§l ,!J. Criando o Deployment Descriptor (DD) 77 parteda •• pecifj~ção~l ! _ 1"""" ~" ~ Este arquivo web.xmJ h~TEMQ~Eestarem l __ _ _ z;; WEB-INF Criando, compilando, distribuindo e testando o servlet de controle 81 Específico Aplicação da 8,- -: ~ •. A estrutura deste pacote é Design, criação e teste do componente modelo 82 - - .' .' A menos que você esteja Otimizando o controlador para chamar o modelo ~i _~ ~~(~:~~a~:e~t~i:O ~; __". :~:~~~~u:n=;~o 1 _~ .. ,'- , _ -- _-- maIs tarde). você DEVE colocar o Criando e distribuindo o componente view; (isto é um JSP) 87 g 8 i [pacote de estrutura de diretórios irnediatamente abaixo de WEB- ~> _si"", INF/classes. Otimizando o servlet de controle para chamar o JSP 88 Sendo um servlet 4 Servlets vivem para servir clientes. A função de um servlet é receber uma solicitação do cliente e devolver uma resposta. A solicitação talvez seja simples: "traga-me a página de Boas-vindas". Ou pode ser complexa: "Finalize o processo do meu carrinho de compras."A solicitação carrega dados cruciais e o código do seu servlet tem que saber como encontrá-Ios e utilizá-Ios. E ele tem que saber como enviar uma resposta. Ou não ... Objetivos do Exame 94 Os Servlets são controlados pelo Container 95 Cada solicitação roda em uma thread separada! 101 A verdadeira função do servlet no tratamento das solicitações 105 A história da solicitação não-idempotente 112 O que determina se você recebeu uma solicitação GET ou POST? 117 Enviando e usando parâmetro( s) 119 o servlet usa os dados NÃO Idempotente do POST para atualizar Então, essa foi a Solicitação ... vejamos agora a Resposta 126 ~ ~ <_ .... ~:":: LJ M wz .... -----8 .. ObanCOde ..... QdOS. d .•.. Você pode configurar headers de resposta, você pode adicionar ~~ Cliente ~ /servlet ':::~ irO servJet WW'. de volta uma resposta envia com uma página gerada em HTML D headers de resposta 133 Redirecionamento de servlets faz o browser trabalhar 136 Revisão: HttpServletResponse 140 XI
  • 11. Sendo uma aplicação web 5 Nenhum servlet vive sozinho. Nas aplicações web atuais, vários componentes trabalham em conjunto por um objetivo. Temos os modelos, os controladores e as views. Temos os parâmetros e os atributos. Temos as classes helper. Mas, como juntar os pedaços? Como permitir que os componentes compartilhem informações? Como você oculta informações? Como você torna uma informação thread-safe? Seu trabalho pode depender destas respostas. Objetivos do Exame 148 Os Parâmetros Init dão uma força 150 Como um JSP consegue obter os parâmetros init do servlet? 155 Os parâmetros init do contexto dão uma força 157 Comparando o ServletConfig com o ServletContext 159 Ela quer um ServletContextListener 166 9rset Tutorial: escreva um ServletContextListener simples 168 ,,, Compile, distribua e teste o seu listener 176 ~set Acessível apennspamoquelescomoc:essoQ_HttpSessionespecifico A história completa, uma análise do ServletContextListener 178 Atributos de SOUctTAÇÃO Listeners: eles não servem apenas para os eventos de contextos 180 O que é exatamente um atributo? 185 AAPI Atributo 189 O escopo de contexto não é thread-safe! 192 Como tomamos os atributos do contexto thread-safe? 194 Testando a Sincronização 195 Os atributos de Sessão são thread-safe? 198 Os males do SingleThreadModel 201 Apenas os atnbutos da Solicitaçãoe as variáveis locais são thread-safe! 204 Atributos da Solicitação e request dispatching 205 XII
  • 12. conteúdo (sumário) Estado de conversação 6 Os servidores web não têm memória curta. Assim que eles lhe enviam uma resposta, eles esquecem quem você é. Na próxima vez que você fizer uma solicitação, eles não o reconhecerão. Eles não se recordam do que você solicitou no passado e nem do que eles enviaram como resposta. Nada. Porém, algumas vezes você precisa manter o estado de conversação com o cliente durante várias solicitações. Um carrinho de compras não funcionaria se o usuário tivesse que escolher seus produtos e finalizar a compra de uma única vez. Objetivos do Exame 224 Esperamos que seja uma conversa (como as sessões funcionam) 226 IDs de sessão, cookies e outros fundamentos das sessões 231 06of.if-f,-",",,-!--r.~""~'- Reescrita de URL: uma alternativa 237 "'~= ~"ú'ú ..•.•. Quando as sessões envelhecem; dando adeus às sessões ruins 241 Posso usar cookies para outras coisas além das sessões? 250 Os principais momentos de um HttpSession 254 Não se esqueça do HttpSessionBindingListener 256 A migração da sessão 257 Exemplos de listener 261 Sendo um JSP Um JSP torna-se um servlet. Um servlet que você não cria. O Container olha o seu JSP, o traduz em código-fonte Java e o compila em uma classe servlet de Java completa. Porém, você tem que saber o que acontece quando o código que você escreveu em JSP se transforma em código Java. Você pode escrever códigos Java em JSP, mas será que você deveria? E se não for um código Java, o que você pode escrever? Como ele jaz a tradução para o código Java? Veremos seis diferentes tipos de elementos JSP ~ cada um com seu próprio propósito e, sim, sintaxe única. Você aprenderá como, por que e o que escrever no seu JSP. E você aprenderá o que não escrever. Objetivos do Exame 282 Criando um JSP simples usando o "out" e uma diretiva de página 283 Expressões, variáveis e declarações em JSP 288 Hora de ver. um servlet gerado a partir do JSP 296 ~' ., ,. ._.~. A variável out não é o único objeto implícito 298 ">.,. MyISP-.J<pSc1vlet O Ciclo de vida e a inicialização de um JSP 306 Já que estamos falandosobre isso ... as três diretivas 314 Scriptlets considerados perigosos? Eis a EL 317 Mas, espere ... ainda não vimos as ações 323 XIII
  • 13. Páginas sem scripts 8 Fuja do scripting. Será que seus webdesigners precisam mesmo saber Java? Será que eles pensam que quem programa Java para servidores tomar-se-á, digamos, designer gráfico? E mesmo que a equipe seja só você, você quer mesmo um monte de bits e pedaços de códigos Java nos seus JSPs? Você sabe o que significa "um pesadelo na hora da manutenção"? Escrever páginas sem scripts não só é possível, como também é mais fácil e mais flexível com a nova especificação JSP 2.0, graças à nova Expression Language (EL). Padronizada depois do JavaScript e do XPATH, os webdesigners sentir-se-ão em casa com a EL. E você também vai gostar (assim que você se acostumar). Porém, existem algumas armadilhas ... a EL se parece com o Java, mas não é. Às vezes, a EL se comporta de forma diferente de como comportar-se-ia a mesma sintaxe no Java. Portanto, fique atento! Objetivos do Exame 344 Quando os atributos são beans 345 Ações-padrão: useBean, getProperty, setProperty 349 Você sabe fazer referências polimórficas para beans? 354 atributo param dá uma ajuda 360 Convertendo propriedades 363 A Expression Language (EL) salva o dia! 368 Usando o operador ponto (.) para acessar propriedades e mapear valores 370 O [c:catch] dá a você mais opções (Lists, arrays ...) 372 .""'<0""" .•.••••.••• '''<1''''<:; '9"",'~.,,<!~~",-,.~.". _~d~. Mais detalhes dos operadores ponto e [ ] 376 Os objetos implícitos da EL 385 Funções EL e tratando o "null" 392 Os pedaços reutilizáveis do template - dois tipos de "include" 402 A ação-padrão <jsp:forward> 416 Ela não conhece as tags JSTL (uma visão rápida) 417 Revisando as ações-padrão e o include 417 XIV
  • 14. conteúdo As tags customizadas são poderosas 9 Em alguns casos, você precisa de mais do que a EL ou ações-padrão. E se você quisesse fazer um loop através dos dados de um array, exibindo em seguida um item por linha em uma tabela HTML? Você sabe que poderia escrever isso em dois segundos, usando um loop for em um scriptlet. Mas você está tentando evitar os scripts. Sem problema. Quando a EL e as ações-padrão não forem suficientes, você pode usar tags customizadas. Elas são tão fáceis de usar em um JSP quanto as ações-padrão. Melhor ainda, alguém já escreveu boa parte das tags de que você mais provavelmente precisará, e as juntou na JSTL (JSP Standard Tag Library, ou Biblioteca de Tags JSP Padrão). Neste capítulo, aprenderemos a usar tags customizadas, e no capítulo seguinte, aprenderemos a criar as nossas próprias tags. Objetivos do Exame 440 Fazendo loops sem scripts; <c:forEach> 446 Controle condicional com o <c:i:f> e o <c:choose> 451 Usando as tags <c:set> e <c:remove> 455 Com a <c:import>, há três maneiras de incluir conteúdo 460 Customizando o que você inclui 462 Fazendo o mesmo com <c:param> 463 A <c:url> para todas as suas necessidades de hyperlink 465 Crie suas próprias páginas de erro 468 A tag <c:catch>. Semelhante a try/catch ... mais ou menos 472 E se você precisar de uma tag que NÃO esteja na JSTL? 475 Preste atenção ao <rtexprvalue> 480 O que pode existir no corpo de uma tag 482 O tag handler, o TLD e o JSP 483 A taglib <uri> é apenas um nome, não um local 484 Quando um JSP usa mais de uma biblioteca de tags 487 () .H-ritr.rl'c.te #fler+4.f';tJ ,lll.prN.ltLlsi JÇ' <c;forEach ,"------ var="1i.stElement" items="${movi.es}" > va.r=-mov.ie" items="${1i;,...tE:J.ezent}" <td>${llICIVie}</td> '-- > </c:f:~~ lIJoo.{(as fi.:N.js. 5i!"'!~5 5tte .j"nll1 (I:!-""jV;,,!DS 'u fI,+"tJ,,,,+a </c:forEach> V;jr- J<!l /"* exhl'~c. MatrL,,{Ievoiutions !«:so,!h"''''f,,''~iro s,'''''J,n---'7'j KillBilI BoondockSaints Àmelie ReturnoflheKing MeanGirls xv
  • 15. Quando nem a JSTL é o bastante ... 10 Em alguns casos, a JSTL e as ações-padrão não são suficientes. Quando você precisa de algo customizado, e não quer voltar aos velhos scripts, você pode escrever os seus próprios tag handlers. Dessa maneira, os seus desenvolvedores de páginas poderão usar a sua tag nas suas páginas, enquanto todo o trabalho duro é feito nos bastidores, na sua classe tag handler. Mas há três maneiras diferentes de se criar os seus próprios tag handlers, então, há muito o que aprender. Dessas três, duas foram introduzidas com o JSP 2.0 para tomar a sua vida mais fácil (Simple Tags e Tag Files). Objetivos do Exame 500 Tag Files: iguais ao include, só que melhores 502 Onde o Container procura por Tag Files 509 Tag handlers simples 513 Uma tag Simples com um corpo 514 E se o corpo da tag usar uma expressão? 519 Você ainda precisa saber sobre os tag handlers Clássicos 529 Um tag handler Clássico bem pequeno 531 O ciclo de vida Clássico depende dos valores retomados 536 A interationTag lhe permite repetir o corpo 537 Valores-padrão retomados pela TagSupport 539 A interface DynamicAttribute 556 Com BodyTag, você tem dois novos métodos 563 E se você tiver tags que funcionam conjuntamente? 567 Usando a API PageContext para tag handlers 577 Distribuindo sua aplicação web Finalmente, sua aplicação está pronta para o horário nobre. As suas páginas 11 estão finalizadas, seu código está testado e ajustado, e o prazo de entrega era há duas semanas atrás. Mas, para onde vai isso tudo? Tantos diretórios, tantas regras. Que nome você dá aos seus diretórios? Qual nome o cliente pensa que eles têm? O que é que o cliente realmente solicita, e como o Container sabe onde procurar? Objetivos do Exame 602 Referênciaaumbeanlocal Principal tarefa da distribuição: onde entra o quê? 603 612 ~" Arquivos WAR 616 ~ Como o mapeamento de servlets REALMENTE funciona =~?::::::~;~:::. Configurando arquivos de boas-vindas no DD 622 Configurando páginas de erro no DD 626 ~ ~ Configurando a inicialização de servlets no DD 628 __ -êCriando um JSP compatível com XML: um Documento JSP 629 XVI
  • 16. conteúdo Mantenha em segredo, mantenha seguro 12 Sua aplicação web está emperigo. O perigo espreita em cada canto da rede. Você não quer os Caras Maus xeretando nas transações da sua loja virtual, roubando números de cartões de crédito. Também não quer os Caras Maus convencendo o seu servidor de que eles na verdade são os Clientes Especiais Que Recebem Grandes Descontos. E você não quer ninguém (amigo OU inimigo) olhando dados confidenciais dos empregados. Será que o Jim, do departamento de marketing, precisa mesmo saber que a Lisa, do departamento de engenharia, ganha três vezes mais do que ele? As Dez Melhores Razões para realizar a Sua segurança declaratwamente 'Iil lJmpaucomais deprátirocomXML 11ÕrJfazmal a 11inguém. Objetivos do Exame 650 O :~:U~::te, as.~eclarações casamnaturalmente O Top 4 em segurança de servlets 653 deparrame;oSd~~ ':mp~O) já existentesno Como Autenticar no Mundo HTTP 656 e Fica multo bem no seu curriculo. As Dez Melhores Razõespara realizara sua segurançadeclarativamente 659 o ~~:: ~;~~asmais ::j~~:ma flexíveis, G Está no exame. Quem implementa a segurança em uma aplicação web? 660 e Permite aos dcsenvoh-edores de aplicações IeUtJlizarem senlets, mesmo sem acesso ao código-fonte. Autorização: funções e restrições 662 O É legal, simplesmente. Autenticação: quatro sabores 677 OS QUATRO tipos de autenticação 677 Protegendo a segurança dos dados em trânsito: HTTPS em ação 682 Como implementar confidencialidade e integridade de dados caso a caso e declarativamente 684 o poder dos filtros Os filtros lhe permitem interceptar a solicitação. E se puder interceptar a solicitação, você poderá também controlar a resposta. E, melhor de tudo, o servlet nem percebe o que aconteceu. Ele nunca ficará sabendo que alguém intercedeu 13 entre a solicitação do cliente e a invocação do método serviceO do servlet pelo Container. O que isso significa para você? Mais férias. Porque o tempo que você levaria reescrevendo apenas um dos seus servlets pode ser despendido, em vez disso, escrevendo e configurando um filtro com a capacidade de afetar todos os seus setvlets. Adicionar tracking das solicitações do usuário a todos os servlets da sua aplicação? Sem problema. Manipular o output de cada servlet da sua aplicação? Sem problema. E você não precisa nem sequer tocar no código do servlet. •.•... --_ • a pilha ·181'" •• a pilha 9 e a pilha e a pilha a pilha o Objetivos do Exame Construindo um filtro para o monitoramento das solicitações O ciclo de vida de um filtro Declarando e ordenando filtros Comprimindo o output com um filtro no lado da resposta 702 707 708 710 713 o Conta;tle<" ""'P<Jn"otrlétodo ~;::o::-,. Os wrappers são demais 719 ~i<eOdo S••••leM I""" o ~~::~~~é êiªª::: O código do verdadeiro filtro de compressão 722 fircl,m-.e ""tilo,; Conta;ner-nMlÜQa ",t;rndodo.pilll<l. respost"- Código do wrapper de compressão 724 XVII
  • 17. Padrões de Design Enterprise 14 Alguém já fez isso antes. Se estiver começando agora a desenvolver aplicações web em Java, você tem sorte. Poderá se beneficiar do saber coletivo das dezenas de milhares de desenvolvedores que já trilharam esse caminho e sobreviveram para contar. Usando tanto os padrões de design específicos do J2EE quanto outros padrões, é possível simplificar o seu código e a sua vida. E o padrão de design mais significativo para aplicações web, o MVC, possui até mesmo um framework absurdamente popular, o Struts, que ajudará você a criar um servlet Front Controller flexível e de fácil manutenção. Você deve a si mesmo tirar vantagem do trabalho dos outros para que possa despender mais tempo nas coisas mais importantes da vida ... Objetivos do Exame 738 O poder do hardware e do software por trás dos padrões 739 Revisão dos princípios do design de software... 744 Padrões para dar suporte a componentes de modelos remotos 745 Visão geral da JNDI e da RMI 747 O Business Delegate é um "intermediário" 753 Simplifique os seus Business Delegates com o Service Locator 759 Hora de usar um Transfer Object? 761 Nosso primeiro padrão revisitado ... MVC 762 Sim! É o Struts (e o Front Controller), em poucas palavras 767 Refatorando a aplicação Beer para o Struts 770 Revisão sobre padrões 778 fausa pata º caté o Teste Preparatório final. É isso, 69 perguntas. A aparência, os assuntos abordados e o nível de dificuldade são praticamente idênticos aos da prova oficial. Nós sabemos. Teste preparatório final 791 Respostas 828 o 1 índice 865 XVIII
  • 18. 1 Introdução Como usar este livro?
  • 19. Use a Cabeça JSP A quem se destina este livro? Se você responder "sim" a todas estas perguntas: (1) Você sabe Java? (não precisa ser um guru) ® Você gosta de consertar - você aprende fazendo, ao invés de apenas ler? Você deseja aprender, compreender, lembrar dos servlets e dos JSPs e passar no exame SCWD for Java EE 1.5? ® Você prefere uma conversa descontraída em uma festa a palestras acadêmicas sem graça e tediosas este livro é para você. este livro não é para você. Quem provavelmente deveria manter-se longe deste livro? Se você responder "sim" a alguma destas perguntas: (!) Você é totalmente inexperiente em Java? Você não precisa estar em um nível avançado, mas, definitivamente, deve ter alguma experiência. Se não tiver, pegue um exemplar do Use a Cabeça! Java agora mesmo. Hoje! E só então retome a este livro. ® Você é um desenvolvedor Java "forçado" em busca de um livro de consulta? ® Você é um veterano em J2EE em busca de técnicas ultra-avançadas e "como-fazer" específicos para servidores, projetos para empresas e códigos complexos, robustos e reais? @ Você tem medo de experimentar coisas diferentes? Você prefere fazer um canal no seu dente a misturar listras num tecido xadrez? Você acha que um livro técnico perde a credibilidade se os componentes Java tiverem aparência humana? este livro não é para você. xx
  • 20. introdução Nós sabemos o que você está pensando. "Como este livro de programação pode ser sério?" "Com tantas ilustrações?" "Eu consigo realmente aprender desta forma?" E nós sabemos o que seu cérebro está pensando. Seu cérebro clama por novidades. Está sempre procurando, examinando e esperando por algo diferente. Ele foi criado assim e o ajuda a se manter vivo. Atualmente, é pouco provável que você vire o lanchinho de um tigre, mas seu cérebro continuará em alerta. Nunca se sabe. Então, como seu cérebro faz para lidar com todas as coisas rotineiras, comuns e normais com as quais você se depara? Tudo o que ele puder fazer para impedir que tais coisas interfiram no seu real trabalho: registrar o que interessa. Não faz mal guardar as coisas fúteis; elas nunca passarão pelo filtro que retém o que "obviamente não importa". Como seu cérebro reconhece o que é importante? Suponha que você tire um dia para fazer uma caminhada e um tigre pule na sua frente. O que acontece com a sua cabeça e o seu corpo? Os neurônios disparam. As emoções são ativadas. As reações químicas explodem. E é assim que seu cérebro reconhece ... Isto pode ser importante! Não esqueça! Mas, imagine que você está em casa, ou em uma biblioteca. É um local seguro, acolhedor e sem tigres. Você está estudando. Preparando-se para um exame. Ou tentando aprender um assunto técnico e difícil, que seu chefe acredita que levará uma semana, dez dias no máximo. Só um problema. Seu cérebro está tentando lhe fazer um grande favor. Ele está tentando assegurar-se de que aquele conteúdo, obviamente irre1evante, não vá confundir os poucos recursos. Recursos estes que seriam melhores se usados para armazenarem coisas realmente importantes. Como tigres. Como o perigo do fogo. Ou como você nunca mais deveria praticar snowboard de short. E não existe um jeito simples de dizer ao seu cérebro, "Ei cérebro, muito obrigado, mas nào importa se o livro é tedioso, ou o quanto estou registrando agora na escala Richter emocional, eu realmente quero que você guarde estas coisas por aqui." você está ~ XXI
  • 21. Use a Cabeça JSP Então, o que é necessário para se aprender algo? Primeiro, você precisa absorver e depois se certificar de que não irá esquecer. Não tem nada a ver com enfiar coisas na sua cabeça. Baseando-se nas últimas pesquisas em ciência cognitiva, neurobiologia e psicologia educacional, o ato de aprender envolve muito mais que textos em uma página. E nós sabemos o que faz o seu cérebro funcionar. Alguns princípios de aprendizagem da série Use a Cabeça: Dê ênfase à parte visual. As imagens são muito mais fáceis de serem memorizadas do que palavras soltas e tomam o aprendizado muito mais produtivo (aumenta em até 89% a memória e o aprendizado usando a técnica da transferência). E facilita a compreensão. Ponha as palavras dentro ou próximas às respectivas figuras, em vez de no rodapé ou em outra página e os leitores serão até duas vezes mais capazes de solucionar os problemas relacionados com aquele conteúdo. precisa chamar um método no servidor Use um estilo próprio e em forma de conversa. Em estudos recentes, o desempenho dos alunos nas provas realizadas após aprenderem a matéria, melhorava em 40% se o conteúdo falasse diretamente ao leitor usando a primeira pessoa, com um estilo ~ ( serviço remoto RMI que simulasse uma conversa em lugar do tom formal. Conte histórias em vez de dar palestras. Use a linguagem coloquial. Evite ser muito sério. Em que você prestaria mais atenção: em uma companhia interessante na festa ou em uma palestra? Faça o aluno refletir. Em outras palavras, nada acontece na sua cabeça a menos que você exercite muito os seus neurônios. O leitor precisa estar motivado, atraído, curioso e inspirado para resolver problemas, tecer conclusões e gerar um novo conhecimento. E para isso você precisa de desafios, exercícios e perguntas que estimulem o raciocínio, além de atividades que envolvam ambos os lados do cérebro e os múltiplos sentidos. Prenda - e segure - a atenção do leitor. Todos nós já pensamos "eu realmente gostaria de aprender isto, mas eu não consigo me manter abstrac acordado depois da primeira página". Seu cérebro presta atenção a coisas roam () ; que são extraordinárias, interessantes, estranhas, atraentes e inesperadas. f, / Aprender um assunto novo, difícil e técnico não precisa ser chato. Seu cérebro aprenderá muito mais rápido se o assunto for interessante. c.óM !)WI pM'l.fb-rV!i!'5Udi, Mexa com a emoção do leitor. Agora nós sabemos que sua capacidade de recordar algo depende enormemente do seu conteúdo emocional. Aquilo que você se preocupa, você se recorda. Você se recorda quando sente algo. Não, nós não estamos falando de histórias de sofrimento entre um menino e seu cão. Estamos falando de emoções como a surpresa, a curiosidade, a diversão, o "caramba!. .." e aquela sensação de "Eu sou o cara!" que vem quando você consegue matar uma charada, aprender algo que todos acham difícil ou perceber que sabe uma coisa que o "bam-bam-bam" da engenharia não sabe. XXII
  • 22. introdução Metacognição: pensando sobre pensar Se você realmente quer aprender - e aprender mais rápida e definitivamente -, preste atenção em como você presta atenção. Pense em como você pensa. Aprenda como você aprende. A maioria de nós não fez cursos de metacognição ou teoria do aprendizado enquanto crescia. Esperam que aprendamos, mas raramente nos ensinam a aprender. Supomos que se você está segurando este livro, você quer aprender servlets e, provavelmente, não quer perder muito tempo. Considerando que você fará a prova, você terá que lembrar do que leu. Logo, precisa entender o que foi lido. Para obter o máximo deste livro - ou de qualquer outro livro ou forma de aprendizado -, dê responsabilidades ao seu cérebro. Faça-o ficar atento a este conteúdo. O truque é fazer com que seu cérebro encare como Realmente Importante o novo material que você está aprendendo. Crucial para o seu bem-estar. Tão importante quanto um tigre. Caso contrário, você estará constantemente em conflito, com o seu cérebro dando o melhor de si para não assimilar o assunto novo. Então, como você FAZ para que seu cérebro considere os servlefs um tigre faminto? Existem as formas lenta e tediosa e a mais rápida e efetiva. A forma lenta é a pura repetição. É claro que você sabe que será capaz de aprender e relembrar até mesmo o assunto mais estúpido se o ficar repetindo. Com uma repetição intensa seu cérebro diz, "isto não parece importante para ele, mas ele fica olhando para a mesma coisa repetidamente, então eu imagino que deva ser". A maneira mais rápida é fazer qualquer coisa que aumente sua atividade cerebral, principalmente atividades de tipos diferentes. O que foi dito na página anterior é uma grande parte da solução e foi comprovado como forma de ajudar seu cérebro a trabalhar em seu favor. Por exemplo, estudos demonstram que colocando as palavras dentro das figuras que elas representam (em vez de soltas na página, como uma explicação ou dentro do texto) faz com que seu cérebro entenda como as figuras e as palavras se relacionam, ativando mais neurônios. Mais neurônios ativados significa mais chances do cérebro entender que determinado assunto merece atenção e, possivelmente, deve ser registrado. O estilo interativo também ajuda, pois as pessoas tendem a prestar mais atenção quando percebem que estão em uma conversa, já que se espera que ela;s acompanhem até o final. O interessante é que seu cérebro não se importa necessariamente que a "conversa" seja entre você e um livro! Por outro lado, se o estilo de escrever for seco e formal, seu cérebro entenderá isso do mesmo modo que você o faria se estivesse em uma palestra numa sala repleta de participantes indiferentes. Porém, as figuras e o estilo que simula uma conversa são só o começo. você está ~ XXIII
  • 23. Use a Cabeça JSP Eis O que NÓS fizemos: Ro<:hd'~ttltf Nós usamos figuras, pois seu cérebro está adaptado ao que é visual, não texto. Para ele, uma imagem vale 1.024 palavras. E quando figuras e textos trabalham juntos, nós inserimos o texto na imagem, pois seu cérebro funciona melhor quando o texto está dentro daquilo a que se refere, I diferente de estar numa observação ou escondido em algum lugar no texto. Nós usamos a repetição. Dizemos a mesma coisa de formas distintas e através de meios diferentes - e múltiplos sentidos -, para aumentar as chances de o assunto ser registrado em mais de uma área cerebral. W<wd<;::ligners~ Quthere ..• Nós usamos os conceitos e as figuras de maneira inesperada, pois seu cérebro é ativado quando encontra uma novidade. E usamos figuras e idéias com pelo menos algum conteúdo emocional, pois seu cérebro está predisposto a dar mais atenção à bioquímica das emoções. Aquilo que te faz sentir algo tende a ser mais facilmente lembrado, ainda que esta sensação não passe de um pouco de humor, surpresa ou interesse. Nós usamos um estilo próprio que simula uma conversa, porque seu cérebro tende a prestar maior atenção quando acredita que você está participando d~ uma conversa e não assistindo passivamente a uma apresentação. E assim que funciona mesmo quando você está lendo. Nós incluímos mais de 40 atividades, pois seu cérebro está habituado a aprender e a relembrar mais quando você faz alguma coisa do que quando você lê a respeito. E colocamos exercícios dificeis, porém possíveis de serem feitos, pois é como a maioria das pessoas prefere. Nós usamos métodos diferentes de aprendizado, pois você poderia preferir os procedimentos passo a passo, enquanto outra pessoa poderia preferir entender primeiro as figuras grandes, enquanto outras, simplesmente ver os exemplos de códigos. Mas, independentemente da sua própria preferência de aprendizado, todos se beneficiam vendo o mesmo conteúdo representado sob múltiplas formas. Nós colocamos assuntos para serem usados por ambos os lados do seu cérebro, pois quanto mais você usar do seu cérebro, mais chances terá de aprender e lembrar, além de mais tempo de concentração. Já que colocando para funcionar um lado do cérebro significa geralmente a oportunidade do outro lado descansar, você poderá produzir mais por mais tempo. E nós incluímos estudos de caso e exercícios que apresentam mais de um ponto de vista, pois seu cérebro está adaptado a aprender mais intensamente, quando forçado a fazer avaliações e julgamentos. Nós inserimos desafios com exercícios eperguntas que nem sempre têm respostas diretas, pois seu cérebro está mais propenso a aprender e lembrar quando tem que se esforçar por algo. Pense nisso - você não consegue manter seu corpo em forma apenas observando as pessoas na academia. Porem, nós fizemos o melhor possível para garantir que, quando você estiver trabalhando duro, será pelas coisas certas. E que você não estará desperdiçando nenhum dendrito a mais, tentando entender um exemplo complicado ou analisando um texto dificil, repleto de jargões, ou então, extremamente resumido. Nós usamos pessoas nas histórias, nos exemplos, nas figuras, etc. Afinal, você é uma pessoa e seu cérebro dá maior atenção a pessoas do que a coisas. Nós usamos a técnica do 80/20. Entendemos que se você pretende ser um PhD em JSP, este não deve ser seu único livro. Logo, não falamos sobre tudo. Apenas da matéria que você realmente precisará. XXIV
  • 24. introdução Eis O que VOCÊ pode fazer para dominar seu cérebro Então, fizemos a nossa parte. O resto é com você. As dicas a seguir são o ponto de partida. Preste atenção no seu cérebro e descubra o que serve e o Jef!cá/'h , que não serve para você. Experimente novidades. d ! " f: C<J!Y4{1P - ; ~" ,J1?1tJ;«elf'tI. (). "i!I Pó/'r", (1) Vá devagar. Quanto mais você entender, menos terá que memorizar. ® Fale. Em voz alta. Falando, você ativa uma parte diferente do Não leia apenas. Pare e pense. Quando o cérebro. Se você estiver tentando entender livro perguntar algo, não pule para a resposta. algo ou aumentar sua chance de recordar Imagine que alguém esteja realmente lhe mais tarde, leia em voz alta. Melhor ainda, fazendo a pergunta. Quanto mais você forçar o tente explicar isto para outra pessoa em voz seu cérebro a pensar, melhores serão as chaTIces alta. Você aprenderá mais rápido e talvez de aprender e recordar. observe idéias que você não havia percebido que estavam ali enquanto lia. ® Faça os exerCÍcios. Faça anotações. suas próprias Q) Ouça seu cérebro. Nós os colocamos no livro, mas se nós Observe se o seu cérebro não está ficando resolvermos, vai parecer que alguém está sobrecarregado. Se você se pegar passando fazendo a ginástica para você. E não basta a mão na superficie do livro ou esquecendo olhar os exercícios. Use um lápis. Está o que acabara de ler, é hora de uma provado que a atividade fisica, enquanto se pausa. Uma vez que você ultrapasse um estuda, pode melhorar o aprendizado. determinado ponto, você não aprenderá mais rápido se tentar "enfiar" mais informação @) Leia a seção "Perguntar não ofende". na cabeça e poderá até comprometer o Ou seja, todas elas. Elas não são barras processo. laterais opcionais. Elas s ão parte do conteúdo principal! Não as pule. ® Sinta algo! Seu cérebro precisa saber que isto é @ Antes de ir dormir, faça desta a sua última importante. Envolva-se com as histórias. Crie suas próprias legendas para as fotos. leitura. Ou pelo menos a última que lhe exija racioCÍnio. Dar um sorriso amarelo quando uma piada não tem graça ainda é melhor do que não Parte do aprendizado (especialmente a esboçar reação. transferência para a memória de longa duração) acontece depois que você fecha o livro. Seu cérebro necessita do seu próprio tempo para maior processamento. Se você ® de acabar o livro. Faça o Teste Preparatório Final só DEPOIS puser uma informação nova durante este Se você fizer o teste muito cedo, você não tempo de processamento, o que você acabou terá uma idéia clara da sua preparação para de aprender será perdido. o exame. Espere até sentir que você está quase pronto e então faça o teste em, no @ Beba água. Muita água. máximo, 135 minutos - o tempo verdadeiro Seu cérebro funcionará melhor se receber doSCWCD. um belo banho. A desidratação (que pode . acontecer bem antes de você sentir sede) reduz a função cognitiva. A cerveja, ou algo mais forte, será bem-vinda quando você passar no exame. você está •• XXV
  • 25. Use a Cabeça JSP o que você precisa para este livro: Além do seu cérebro e um lápis, você precisa do Java, do Tomcat 5 e de um computador. Você não precisa de nenhuma outra ferramenta de desenvolvimento como o Integrated Development Environment (IDE). Definitivamente, recomendamos que você não use nada além de um editor simples até terminar o livro. Um IDE que reconhece servlet e JSP poderá privá-l o de algum detalhe realmente importante (e que cairá na prova). Por isso, é melhor você evitar desenvolver todo o bean manualmente. Uma vez que você realmente entenda o que está acontecendo, poderá utilizar uma ferramenta que automatize alguns dos passos para a criação e distribuição do servlet/JSP. Se você já sabe como usar o Ant, poderá usá-lo após o capítulo 3 para ajudar na distribuição. Porém, não recomendamos usar o Ant até que você tenha memorizado completamente a estrutura de distribuição da aplicação web. OBTENDO O TOMCAT --------, Caso ainda não possua o Java SE v1.5 ou superior, você vai precisar (de preferência 1.4). Se você não tem ainda o Tomcat 5, obtenha-o em: http://tomcat.apache.org/ Selecione "Tomcat v5.5" no menu Downloads no lado esquerdo da home page. • Pagine até a seção "Binary Distributions" (Distribuições Binárias) e faça o download da versão escolhida. Se não souber, então, selecione a distribuição "Core" (Básico); é tudo que você precisa. Salve o arquivo de instalação em uma pasta temporária. Instale o Tomcat. Para Windows, dê um duplo-clique no arquivo install.exe e siga as instruções do assistente de instalação. Para os outros sistemas, descompacte o arquivo de instalação no diretório onde você quer que o Tomcat resida. Para facilitar as instruções do livro, renomeie para "tomcat" o diretório home do Tomcat (ou configure um cognome "tomcat" que aponte para o home verdadeiro do Tomcat). Configure as variáveis de ambiente para JAVA_HOME e Java 2 Standard Edition 1.5 TOMCAT HOME, da mesma forma como você normalmente Tomcat 5 faz em sua máquina. O exame abrange as Você deve ter uma cópia das especificações, embora não seguintes especificações: precise delas para passar no exame. Até o lançamento deste livro, as especificações eram: • Servlets 2.4 Servlet 2.4 (JSR #154) http://jcp.org/eng/jsr/detail?id=154 JSP 2.0 (JSR #152) http://jcp.org/eng/jsr/detail?id=152 ·JSP 2.0 JSTL 1.1 (JSR #52) http://jcp.org/eng/jsr/detail?id=52 Vá até a página JSR e clique em Download Page para o • JSTL 1.1 lançamento mais recente. Teste o Tomcat rodando o script tomcat/bin/startup (startup. sh para os sistemas Linux/Unix/OSX). Digite na barra de endereços do seu browser: http://localhost:8080/ e você verá a página inicial do Tomcat. XXVI .~ ...
  • 26. introdução Coisas de última hora que você precisa saber: Isto é uma experiência de aprendizado e não um livro de referência. Nós retiramos deliberadamente tudo que pudesse atrapalhar o caminho do aprendizado, independentemente do que estejamos trabalhando no livro. E, desde o primeiro instante, comece do começo, pois o livro faz considerações quanto àquilo que já foi visto e aprendido. fJS{Ufl6S VI?, fJMI-. Nós usamos diagramas simples e parecidos com UML. f! m~Ji/tllt:M.,lt~ h!4,(~ Embora exista uma grande chance de você já saber UML, isto não é cobrado no exame e não é um pré-requisito para o livro. Então, você não terá que se preocupar em aprender servlets, JSP, JSTL e Diretor UML ao mesmo tempo. getMovies Nós não cobrimos todos os detalhes minuciosos da especificação. getOscars () O exame é muito detalhado, mas, nós também somos. Porém, se getKevin existe um detalhe na especificação que não é cobrado no exame, só BaconDegrees() o citaremos se for importante para a maioria dos desenvolvedores de componentes. O que você precisa saber para começar a desenvolver componentes web (servlets e JSPs), e o que precisa para passar no exame, cobre cerca de 85%. Nós incluímos algumas coisas que não caem na prova, mas sinalizamos para que você não se preocupe em memorizá-Ias. Nós criamos o verdadeiro exame, portanto, sabemos onde você deverá concentrar sua energia! Se houver a possibilidade de um mínimo detalhe figurar em uma questão da prova, mas se o esforço para aprendê-Io realmente não valha a pena, provavelmente ou o omitiremos, ou o abordaremos sucintamente, ou o colocaremos em uma questão do teste preparatório. As atividades NÃO são opcionais. Os exercícios e as atividades não são meros adicionais; eles são parte do conteúdo principal do livro. Alguns estão lá para ajudar na memorização, outros para ajudar na compreensão, enquanto outros o ajudarão a aplicar o que você aprendeu. Não pule nada. A redundância é intencional e importante. Uma coisa que é claramente diferente em um livro da série Use a Cabeça! é que nós queremos muito, muito, muíto que você entenda. E gostaríamos que você terminasse o livro lembrando o que aprendeu. A maioria das informações e dos livros de referências não tem, necessariamente, a retenção e a lembrança como objetivos, mas aqui você verá alguns conceitos aparecerem mais de uma vez. Os códigos-exemplos são os mais resumidos possíveis. Nossos leitores têm relatado o quanto é frustrante ler minuciosamente 200 linhas de códigos procurando por aquelas duas linhas que eles precisam. A maioria dos exemplos deste livro é exibida dentro dos menores contextos possíveis, para que a parte que você precisa fique clara e simples. Não espere que o código seja robusto ou completo. Esta é sua tarefa para quando terminar o livro. Os exemplos aqui são escritos especialmente para aprender e nem sempre são totalmente funcionais. Alguns exemplos de código para o livro estão disponíveis em www.altabooks.com.br você está aqui ~ XXVII
  • 27. fazendo a prova Sobre o exame SCWCD (para Java EE 1.5) o exame SCWCD atualizado é chamado de "Sun Certified Web Component Developer for Java Platform, Enterprise Edition 5" (CX-310-083), mas não fique confuso com o título. O exame atualizado ainda é designado para o Java EE vIA, para o servlet v2A e as especificações JSP v2.0. Primeiro tenho que passar no SCJP? Sim. O exame Web Component Developer, exame Business Component Developer, exame Mobile Application Developer, exame Web Services Developer e exame Developer requerem que você seja um Sun Certified Java Programmer. Quantas questões? Você terá 69 questões quando fizer o exame. Ninguém têem as mesmas 69 questões; existem muitas versões diferentes do exame. Mas todas têm o mesmo grau de dificuldade e o mesmo equilíbrio de tópicos. No exame real, espere ver pelo menos uma questão do objetivo de cada exame e existem alguns objetivos nos quais você terá mais de uma questão. Quanto tempo tenho para completar o exame? Você tem três horas (180 minutos). A maioria das pessoas não acha que isso é um problema, pois essas questões não são longas, complicadas, complexas. A maioria das questões é muito curta, tem múltipla escolha e você sabe a resposta ou não. Como são as questões7 Elas são quase exatamente como as nossas perguntas simuladas do exame, com uma grande diferença - o exame real informa-o quantas respostas estão corretas, nós não. Contudo, você verá algumas perguntas do tipo arrastar e soltar que não podemos fazer aqui. Mas as questões com arrastar e soltar são apenas o modo interativo de coincidir uma coisa com outra. Quantas tenho que responder corretamente? Você deve ter 49 questões corretas (70%) para passar no exame. Quando terminar de responder a todas as questões, mantenha o cursor do mouse sobre o botão Done (Terminado) até que tenha coragem de clicá-Io. Em cerca de seis nanossegundos, você saberá se passou (claro, você passará). Por que os exames simulados no livro não informam quantas opções escolher para a resposta correta? Queremos que nossos exames sejam apenas um pouco mais difíceis que o exame real, para lhe dar uma idéia mais verdadeira para saber se você está pronto para fazer o exame. As pessoas tendem a ter notas mais altas nos exames simulados do livro porque refazem o mesmo teste mais de uma vez e não queremos que você tenha uma falsa sensação de sua aptidão para o exame. Os leitores têm informado que a pontuação consegui da no exame real é muito próxima da pontuação que eles têm no exame simulado final neste livro. XXVIII introdução
  • 28. o que acontece depois de fazer o exame? Antes de deixar o centro de teste, obtenha o relatório de seu exame. Ele mostra um resumo de sua pontuação em cada área maior e se passou ou falhou. Guarde-o! É sua prova inicial de que você foi certificado. Em poucas semanas depois do teste, você receberá um pequeno pacote da Sun Educational Services que inclui seu certificado impresso real, uma carta de felicitação da Sun e um adorável alfinete de lapela informando Sun Certified Web Component Developer em uma fonte tão pequena que você poderia declarar ser certificado em qualquer coisa que quisesse e ninguém poderia ler para saber a diferença. Não inclui a bebida alcoólica que você estará querendo depois de passar no exame. Quanto custa e como me registro? O exame custa US$200. E é por isso que você precisa deste livro ... para assegurar que passará na primeira vez. Você registra-se através do Sun Educational Services, fornecendo o número de seu cartão de crédito. Em troca, receberá um número de voucher, que usará para agendar um encontro em um Prometric Testing Center mais próximo de você. Para obter detalhes on-line e comprar um voucher do exame, comece em:bttp://www.sun. com/training/certificationi. Se estiver nos Estados Unidos, estará marcado. Se não, poderá selecionar um país na barra de menus à direita. Como é o software do exame? É bem simples de usar - você tem uma questão e responde-a. Se não quiser responder, poderá pulá-Ia e voltar para ela mais tarde. Se a responder, mas não estiver certo e quiser voltar para ela se tiver mais tempo, poderá "marcar" uma questão. Assim que tiver terminado, verá uma tela que mostra todas as questões que você não respondeu ou marcou, para que possa voltar para elas. Bem no início do exame, você obterá um pequeno tutorial sobre como usar o software, onde conseguir um pequeno teste prático (não sobre Servlets). O tempo gasto no tutorial não conta como o tempo gasto no exame SCWCD. O relógio não iniciará até que você tenha terminado o tutorial do software de exame e estiver pronto para começar. Onde posso encontrarum grupo de estudo e quanto tempo levará para me preparar? O melhor grupo de análise on-line para este exame é aquele que os autores presidem! (Deus, quais são as probabilidades?) Pare em j avaranch. com e vá para Big Moose Saloon (é onde estão todos os fóruns de discussão). Você não pode perder. Sempre haverá alguém para responder suas perguntas, inclusive nós. JavaRanch é a comunidade Java mais amistosa na Internet, portanto, você será bem-vindo não importando o nível em que estiver no Java. Se você ainda precisar ter o SCJP, iremos ajudá-Io com ele também. Quanto tempo leva para ficar pronto para o exame depende muito de quantos servlets e experiência JSP você tem. Se você for novo. nos servlets e no JSP, poderá precisar de 6 a 12 semanas, dependendo de quanto tempo pode dedicar a cada dia. Aqueles com muitos servlets recentes e experiência JPS geralmente poderão estar prontos em até três semanas. você está ~ XXIX
  • 29. a equipe de revisores Beta testers & Revisores Técnicos lA"fi.iS d"'$ u f •.• de ~a,beld$!JT'rt.b'Jc'(';s f>4!JJ'" Céwsa desh Itvrcó, IV';" 1"+(;5f'~f~d", ("'4S +õ'ó ''''Pórhwl-e &1/4",1-" "$ "'1I+r"s) -I /1-",1'+ L"",dhe de: J""'5 ---.----/ A"drew 1Lf.""k/,{Jtlse fl.ee,l-ish (~ lA.adafta XXX introdução
  • 30. introdução J.tU' ct'~J.t.f<} Outras pessoas a quem ~: Na O'Reilly: Nossos maiores agradecimentos a Mike Loukides na O'Reilly, por iniciar tudo e ajudar a dar forma ao conceito Use a Cabeça em uma série. Adoramos ter um editor que é um Verdadeiro Java. E um grande agradecimento à força motriz por trás do Use a Cabeça, Tim O'Reilly. Felizmente para nós, ele sempre está pensando no futuro e gosta de ser uma influência destruidora. Obrigado a Kyle Hard "a mamãe da série" Use a Cabeça inteligente por descobrir como o Use a Cabeça encaixa-se no resto dos livros de computador. Nossos revisores intrépidos: Tudo bem, então, o livro levou um pouco mais de tempo do que tínhamos planejado. Mas sem o gerente de revisão JavaRanch Johannes deJong, ele teria ficado assustadoramente atrasado. Você é nosso herói, Johannes. E nossos agradecimentos especiais a Joe Konior cujo feedback em cada capítulo foi quase do mesmo tamanho do capítulo. Estamos profundamente agradecidos pelo esforço inexorável e experiência (e alegria) de Philippe Macquet. Todos os três autores adoram-no tanto que queremos casar com ele ... mas isso seria estranho. E estamos muito gratos a Andrew Monkhouse pelo feedback técnico e ajuda nas traduções sutis do inglês para a língua australiana. Jef Cumps, sua interpretação MP3 da canção "setHeader" foi impressionante (exceto talvez por ser um pouco emo) e seus comentários técnicos foram realmente úteis. Dave Wood trabalhou com afinco em tudo e foi carinhoso ao apontar para as primeiras páginas e dizer: "Isso não é o estilo Use a Cabeça". Também tivemos um feedback excelente dos moderadores JavaRanch Jason Menard, Dirk "cara de peixe" Shreckmann, Rob Ross, Ernest Freidman-Hill e Thomas Paul. E como sempre, agradeço especialmente ao chefe javaranch.com, Paul Wheaton. Agradecimentos especiais aos seguintes revisores técnicos pela segunda edição: Bear Bibeault, Theodore Casser, UlfDittmer, Preetish Madalia, Sergio Ramirez, Oliver RoeU, Neeraj Singhal e Collins Tchoumba. Perguntas do examine simulado Se você se encontrar balançando a cabeça em uma questão simulada JSP particularmente capciosa, não nos culpe - culpe Marc Peabody! Obrigado Marc por ajudar a manter todos os candidatos SCWCD em alerta. Marc passa uma quantidade enorme de seu tempo livre moderando no JavaRanch, onde é conhecido por estimular os usuários Ranch a construir misturas horríveis de suas tecnologias Java EE inocentes. você está ~ XXXI
  • 31. mais reconhecimentos Tem mais gente ainda* Por Bryan Basham Eu poderia começar agradecendo à minha mãe, mas isso já foi feito antes ... Meu conhecimento em desenvolvimento web com Java tem como base algumas aplicações de média escala que escrevi, mas esta base foi melhorada e refinada por anos de debate em Java como instrutor da Sun, usando um e-mail com um nome fictício. Em particular, gostaria de agradecer a Steve Stelting, Victor Peters, Lisa Morris, Jean Tordella, Michael Judd, Evan Troyka e Keith Ratliff. Muitas pessoas ajudaram a lapidar meu conhecimento, mas estes seis foram as facas que melhor me esculpiram. Como em todos os projetos de livro, os últimos três meses foram muito dificeis. Gostaria de agradecer à minha noiva, Kathy Collina, por ter sido paciente comigo. Eu quero agradecer a Karma e Kiwi (nossos gatos) pelas sessões de lambidas tarde da noite e as pancadas no teclado. Por último, e mais importante, tenho que agradecer à Kathy e ao Bert por sugerirem que levássemos adiante o projeto. Kathy Sierra é mesmo única no mundo. Seu conhecimento em metacognição e design educacional só se comparam à sua essência criativa que transborda nos livros desta série. Eu tenho trabalhado com educação há cinco anos e praticamente tudo o que aprendi foi com a Kathy ... Oh, não se preocupe com minha mãe; ela receberá uma grande dedicatória em meu próximo Use a Cabeça!. Eu te amo, mãe! Por Kathy e Bert Isso foi tão sentimental, Bryan, ohhhh ... (Não que a Kathy não goste de rasgar uma seda). Mas, concordamos quando fala sobre sua noiva. Mas não por ela ter sentindo saudades suas, enquanto jogava Ultimate o verão todo e nós trabalhávamos feito cachorro em nossos Powerbooks 1. Mas você realmente fez disso uma experiência recompensadora, Bryan, e hoje é o melhor(NA) co-autor que já tivemos! Chega quase a assustar o quanto você é calmo e feliz o tempo todo. Todos nós adoramos a equipe que trabalha duro nos exames de certificação da Sun, em especial a Gerente de Certificação em Java, Evelyn Cartagena. Queremos agradecer também a todos os colegas que ajudaram a desenvolver as especificações dos JSRs para Servlet e JSP. o * grande número de agradecimentos é porque estamos testando uma teoria de que todos os mencionados na seção de agradecimentos do livro comprarão pelo menos uma cópia, talvez mais, contando os parentes e tudo. Se você quiser estar na seção de agradecimentos do nosso próximo livro, e se tiver uma família grande, escreva-nos. 1Ponto de esclarecimento: O Bryan foi o único co-autor que nós tivemos, mas isto não diminui em nada a nossa intenção. XXXII
  • 32. Por que usar Servlets & JSPs? As aplicações web estão na moda. Claro, as aplicações GUI podem usar aquelas coisas exóticas do Swing, mas quantas aplicações GUI você conhece que são usadas por milhões de usuários em todo o mundo? Como desenvolvedor de aplicações web, você não precisará se prender aos problemas de distribuição presentes em toda aplicação standalone e irá distribuir sua aplicação a qualquer pessoa que possua um browser. Porém, para construir uma aplicação web poderosa mesmo, você precisa do Java. Dos servlets. Dos JSPs. Pois as velhas e estáticas páginas HTML são tão, digamos, "1999". Hoje, os usuários esperam por sites dinâmicos, interativos e customizáveis. Aqui, você aprenderá como mudar do site na web, para a aplicação na web. este é um novo ca~)ítuio
  • 33. objetivos do exame oficial da Sun Visão geral dos Servlets & JSP Notas sobre a Abrangência: 1.1 Para cada um dos Métodos HTTP (como Os objetivos deste capítulo são abordados GET, POST, HEAD e assim por diante): completamente em outro capítulo, então, considere este capítulo como uma base, Descrever os beneficios do Método em primeira mão, para o que virá adiante. HTTP Em outras palavras, não se preocupe Descrever as funcionalidades do Método em terminar este capítulo sabendo (e HTTP lembrando) de itens especificos destes Listar os triggers que podem levar um objetivos; apenas use isto como uma base. Cliente (geralmente um browser) a usar Se você já domina estes assuntos, poderá o método simplesmente dar uma olhada rápida e passar para o capítulo 2. Também jaz parte do Objetivo 1.1, mas não será Você não encontrará nenhuma pergunta no abordado neste capítulo: teste prático sobre estes assuntos até que Identificar o método HttpServlet que você chegue ao capítulo mais especifico, corresponda ao Método HTTP onde eles serão abordados. 2 capitulo 1
  • 34. introdução e arquitetura rodos queretM UtM website Você tem uma idéia fantástica para um website. Para aniquilar com os concorrentes, você precisa de uma arquitetura flexível e escalonável. Você precisa de servlets e JSPs. Antes de começarmos a construção, vamos dar uma olhada na rede mundial de computadores, a uma distância de aproximadamente 40k pés. O que mais nos importa neste capítulo é como os clientes e servidores web se comunicam entre si. Provavelmente, as muitas das páginas a seguir serão uma revisão para você, principalmente se você já é um desenvolvedor. Contudo, teremos a chance de definir algumas das terminologias que usaremos no decorrer do livro. A- we!I c4"Sls-!--f: f!1t ;l!t.;;es de clte".f-es (,/sa"dlJ brlJWSfJ'SCtl""lJ lJ llA.o;llla {}V 6 Sa.lard fi! serllt;/{}rff!S (;'6;/0.";/6 apUctlj;;es C61ttl6 A-ptlct.e); ClJ"ec.f-a;/lJS tl+NJ.V;S ;/e redes ClJltIltl e wtreless. 1JI)SS6 "''de+tv6 ; ClJ"s.f-I'Vll' Vlttl tlpllca{ã6 ave lJS clle,,-I-es 44 red41' ;/6 ItV,,;/lJ p6S S8..." tlces sal'. í "ôS +6N78.1''''''S es.f-vpt;/lJ..."e,,-I-e rlcf/'JS. Cliente a terra você está aquí I; 3
  • 35. servidor Web o que o seu servidor web faz? Um servidor web recebe uma solicitação e devolve algo para o cliente. Um browser permite ao usuário solicitar um recurso. O servidor pega a solicitação, encontra o recurso e retoma com algo para o usuário. Algumas vezes este recurso é uma página HTML. Outras, umafigura. Ou um arquivo de som. Ou até mesmo um documento PDF. Não importa - o cliente solicita uma coisa (recurso) e o servidor a envia de volta. A menos que o recurso não esteja lá. Ou pelo menos, não está onde o servidor esperava encontrá-Io. Certamente, você já está bem familiarizado com o erro "404 Not Found" - a resposta que você recebe quando o servidor não pode encontrar o que ele acha que você solicitou. Quando dizemos "servidor", estamos querendo dizer ou a máquina física (hardware), ou a aplicação do servidor web (software). Ao longo do livro, se a diferença entre o hardware e o software do servidor importar, nós diremos explicitamente a qual dos dois (hardware ou software) nos referimos. /} sali'cl.fa{i6 JÍ6 clle~ C611#1VI () l1ólVle e el1Jel"eS6 (li. (J}t.f-); JIJ.3l1t1fJ alie fJ cltewh! es.f: fl"6ClIl"lJ.l1Ja. ~ C3" ~ bel"fi./lVlel1h; 6 sel'vti/tJl" ~ hlVl IVIlIt-.f6 C6#1htdtJ fbJe seI' 1Vlfi.I1JÍIí.Jb ffi.NJ. tJ / lISVfJ.l't'"b.tsh 1__.1 (;tJ#1-rrtllJfJ f6Je ser f~''''fJ.S; JPíbs ~ e <':Jv.fl"<':Js l'eCVI'SfJs. ~ /} l"espas.ffJ. Ja sel"lI,i/t'J1" C6#1#1VI a J.oclIlVlel1.fa vel"JaJell'tJ !ve tJ dtewh stJlicr.f6l1 (6V VIVI C:iiil51) de el"l"õ se I) feJti/6 1146fvJel'sel" fl"l)cessad6). 4 1
  • 36. introdução e arquitetura o que UtM cliettte web faz? Um cliente web permite ao usuário fazer solicitações ao servidor, exibindo para ele o resultado do pedido. Quando falamos em clientes, no entanto, geralmente queremos dizer ao mesmo tempo o usuário e o browser (ou um dos dois) . O browser é o software (como o Netscape ou o Mozilla) que sabe se comunicar com o servidor. A outra grande tarefa do browser é interpretar o código HTML e exibir a página ao usuário. Então, a partir de agora, quando usarmos o termo cliente, geralmente não nos preocuparemos se estamos falando do usuário ou do browser. Em outras palavras, o cliente é o browser jazendo aquilo que o usuário solicitou. o usuário clica em um o browser formato a o servidor encontra link no browser. a página solicitada. solicitação e a envia para ~ o servidor. G1J •. 'P: ~ ------=7 I I . I ;"1'" Usuário Browser Servidor o browser consegue o HTML e o traduz em o servidor formato a formato visual para o resposta e a envia para o usuário. cliente (browser). -~I~I Servidor você está aqui ~ 5
  • 37. HTMLeHTTP Os clietttes e os servidores conhecelt HfML e HffF HTML Quando um servidor responde a uma solicitação, ele geralmente envia algum tipo de conteúdo para o browser, para que este possa exibi-Io. Os servidores geralmente enviam instruções para o browser escritas em HTML (HyperText Markup Language). O HTML diz ao browser como apresentar o conteúdo ao usuário. Todos os browsers sabem o que fazer com o HTML, embora algumas vezes um browser mais antigo possa não entender partes de uma página que tenha sido escrita usando as versões o B1ML Int9tma a9 mais recentes do HTML. bt9"'vTset 9m9 e)Úblt 9 C ;d ;c c9nteU 9 a9 Usuatl9. HTTP A maioria das conversas que ocorre na web entre clientes e servidores é mantida através do o BTTP é 9 pt9t9c919 'Lue 95 protocolo HTTP, que possibilita clIentes e 9S set""Id9tes usam conversas de request e resposta simples. O cliente envia uma patq se C9munkatem. solicitação HTTP e o servidor retoma uma resposta HTTP. Conclusão: se você é um servidor web, você fala HTTR o set""ld9t USq9 BTTP pata Quando um servidor envia uma página HTML ao cliente, o faz en""'i!U' B1ML íW clIente. 9 usando o HTTP. (Você verá os detalhes de como tudo isto funciona nas próximas páginas.) (Para Sua Informação: HTTP significa Protocolo de Transferência de Hipertexto.) 6 capitulo 1
  • 38. introdução e arquitetura G-uia rápido de HfML Quando você desenvolve uma página, você usa o HTML para descrever que aparência a página deve ter e como deve se comportar. o HTML tem dúzias de tags e centenas de atributos de tag. O objetivo do HTML é, a partir de um documento texto, adicionar tags que dirão ao browser como formatá-Io. Abaixo estão as tags que usaremos nos diversos capítulos a seguir. Se você precisar de um conhecimento completo em HTML, recomendamos o livro HTML & XHTML The Definitive Guide. Tag Descrição <!- ~> onde você põe seus comentários <a> âncora - geralmente para colocar um hyperlink ) <align> alinha os comentários à esquerda, à direita, centralizado ou justificado <body> define os limites do corpo do documento <br> (1'éc/IliCQ.llle/ll+ej Q.S pular linha <.ce/ll+el'") e <.aIi5/1l") Cf).II'f).1IIt <center> centraliza o conteúdo '" elll fÀesustJ ctJll'I a <form> define um formulário (que geralmente oferece 'i.0) lIItas eS+Q.lllttJs uSQ./IlfÀtJ-as elllt um campo para a entrada de dados) /IltJS StJS eXt!.l!'fi(JS; <hl> o cabeçalho de primeiro nível sel'elllt 1t'141"$ sil!'fles fÀt. • StJ4S <head> define os limites do header do documento st.l'elt'l llilfJ.S l'espec+tv4S <html> define os limites do documento HTML / a.fé p61'ZUe <input type> define um tipo de entrada em um formulário es-ra asvl• Il <p> um novo parágrafo IfrM~,) <title> o título do documento HTML você está 7
  • 39. escrevendo HTML o que você escreve ... (o HfMU Imagine que você está criando uma página de login. O HTML simples poderia se parecer com isto: <html> <!- Um HTML exemplo - > 4::-- {J1f Ce.lf!ifl1+:1'/4 /frML <head> <title>A Login Page</title> tt +~<.I~> es+: fJ.11/"I1t.adfJ. del1+l't:. </head> de viria +~<.a.lijl1> de tfJ.I':51'fJ.1t:.; 4 11Ít de cõ/e.C41' ti 1Ít~elf!i IrItu's õV <body> If!ifl14S lJl1de 3vel'flrlõ.s'. (Lelrlbl'e- se; ® <hl align="center">Skyler's Login Page</hl> +~<'Q.1I511> fJJvflrl JfSVS(J; © <p align="right"> <img src~"SKYLER2.jpg" width="130" r height="150"/> fJ. seI' !Ma) tC JeciÇ/ihl.lJS vSQ-la tlJl' ser sl~/es lf!iitS Je @ </p> <form action="date2"> Name: <input r () sel"vld type~"text" pal'a. ó 3Va./ el1i1I&lI'f!1rI6Sa. s()llct+fJ.f'li4. name~"paraml"/><br/> A's +~S ~tfJ.f'fI. tV/lU' sel'velrl h"l1t.as. Password: <input type="text· 'ame="param2" I><br I><br I><br I> "-- ()ptJl"+Vl1alrlel1+eJ I 1a./aN;lrIlJs ""(/,1"$ <center> IÓI"IrIVIQI'14S; irias pal'a I'esvlrlir; ó 1JI'IJIf;Isel' <input type="SUBMIT"I> cgp+VI'fJ.1' éI l"I1pV+ JIJ VSV:1"14 e l"e+IJI"I1:-I", Qtl ® </center> sel'vtJIJI'. </form> </body> </html> ......•••.•.....•.••••.....••........•.•..............••.........••........•.• : o : : Você só vai precisar dos conhecimentos mais básicos : · : · · emHTML. . : . . · · . . : 0. HTML "pipoca" durante todo o exame. Mas você não : : está sendo testado em HTML. No entanto, você vai se deparar com o : : HTML no contexto de várias perguntas. Portanto, você precisará ao menos : · : · de uma idéia do que está acontecendo quando vir um HTML simples. .............................................................................. . . : 8 capítulo 1
  • 40. introdução e arquitetura o que o browser cria ... o browserlê todo o código HTML, cria a página e a transforma em imagem para o usuário. I ® @ ----.:'Iame: Password: ® você está 9
  • 41. o protocolo HTTP o que é o protocolo HffP? o HTTP roda no topo do TCP/IP. Se você não está familiarizado com estes protocolos de rede, temos aqui um curso rápido: O TCP é responsável por garantir que um arquivo enviado de um nó da rede para outro chegue íntegro ao seu destino, ainda que o arquivo Principais eleme esteja dividido em blocos no momento do solicitação: ntos do fluxo de envio. O IP é o protocolo de sustentação que transfere/roteia os blocos (pacotes) de ~ O método RTTP _ um host para o outro no seu caminho até o executada) (a açao de ser destino. Ou seja, o HTTP é outro protocolo de rede que tem características específicas ~ A página qu ' para web, mas ele depende do TCP/IP para e sera acessada ( obter a solicitação e a resposta completas de ~ Os parâmetros do [o' , . uma URL) um lugar para o outro. A estrutura de uma argumentos para nn?lano (como ummetodo) conversa HTTP é uma seqüência simples de Solicitação/Resposta; um browser solicita e um servidor responde. solicitação HTTP ~ resposta HTTP Servidor Principais elementos do fluxo de resposta: ~ Um código de status (~o caso de uma solicitação bem suced1da) i~ Tipo de conteúdo (texto, imagem, HTML, ~ O conteúdo (o HTML real, a imagem, etc.) etc.) .......................................................................... · · Você não precisa memorizar a especijicação do HTTP. · · Se você quer mesmo saber (felizmente, o exame não espera que · · · você queira), o protocolo HTTP segue o padrão IETF, RFC 2616. O Apache é um exemplo de servidor Web que processa solicitações HTTP. O Mozilla é um exemplo de browser que dá ao usuário o mecanismo para · · · realizar solicitações HTTP e visualizar os documentos retomados pelo servidor. · · · ...................................................................................... 10
  • 42. introdução e arquitetura o HfML é parte da resposta HffF Uma resposta HTTP pode conter o HTML. O HTTP acrescenta a informação do headerno topo de qualquer que seja o conteúdo da resposta (em outras palavras, aquilo que retoma do servidor). Um browser HTML usa aquela informação de header para ajudar no processamento da página HTML. Considere o conteúdo do HTML como um dado que foi colado dentro de uma resposta HTTP. solicitação HTTP resposta HTTP 1 Servidor ~Va.l7d4 6 bl"ówsel" el'Jumfl"a a +f4j <"+11'I1> abel"-!-v"4; ele el7+l"a.ell'l lI'Iód6 de de pI"4CeSSall'le~4 d6 I/rK.4.L e ex'-!!e a </head.> / / p~lP;a ." t/SVfJ.I"it>. <bOdy> <img src== ... > ~val'Jdó ó bl"ówsel" el'Jcól'J-!-I"Qll'la v </bOdy> </htm.l> -!-~ de Iw..~e..., ele jel"a óV+l"a sóllct-!-a{ióltrrp pal"14,,. bvscal" 6 l"ecvl"sóespecllteadlJ. / AJes-h ca.SIJ; 6 bl"ówsel" !al"a. Vll'la.SejVl'Jda sóllcl+a.{ió I/rrp pal"a ób-h" a 1w..4jell'l descl"i+. l'Jaf~ <1"""5>. você está 11
  • 43. Métodos HTTP Se esta é a resposta, o que consta na solicita cão ? A primeira coisa que você encontrará é o nome do método HTTP. Estes não são métodos Java, mas a idéia é semelhante. O nome do método informa ao servidor o tipo de solicitação que está sendo feita e como o resto da mensagem será formatada. O protocolo HTTP possui diversos métodos, mas os que você usará com mais freqüência são o GET e o POSTo o usuário dica em um Iink para uma o browser envia um HTiP GET ao nova página. servidor, pedindo ao servidor que CONSIGA a página. ~ J Usuário Browser POST O usuário digita em um O browser envia um HTiP POST ao 11I formulário e dica no servidor passando para o servidor o ·i!':1lt botão enviar. que o usuário digitou no formulário. ~ I Usuário Browser 12 capítulo 1
  • 44. introdução e arquitetura o &Ef é uma simples solicita~o, o POSf pode enviar dados do usuário o GET é o método mais simples do HTTP e seu principal trabalho na vida é pedir ao servidor que consiga um recurso e enviá-Io de volta. Tal recurso pode ser uma página HTML, um JPEG, um PDF, etc. Não importa. O objetivo do GET é conseguir alguma coisa do servidor. O POST é uma solicitação mais poderosa. É como se fosse um GET ++. Com o POST, você pode solicitar algo e, ao mesmo tempo, enviar os dados de um formulário para o servidor (mais adiante neste capítulo, veremos o que o servidor pode fazer com esses dados). Nã9 ex1stem retguntas idl9téls r: E com relação aos outros métodos HTTP além do GET e do POST? 1: Estes são os dois métodos mais usados por todo mundo. Mas, existem alguns raramente usados (e os Servlets podem tratá-Ios), tais como HEAD, Espere um momento ... Eu poderia jurar que vi TRACE, PUT, DELETE, OPTIONS e CONNECT. solicitações GET que enviavam alguns dados por parâmetros ao Você realmente não precisa saber muito sobre estes servidor. outros para o exame, embora você possa encontrá- los em alguma pergunta. O capítulo A Vida e a Morte de um Servlet aborda o resto dos detalhes dos métodos HTTP que você poderá precisar. você está 13
  • 45. HTTPGET É verdade ... você pode enviar algutls dados COI11 o HffF G-Ef Mas você pode não querer. As razões para usarmos o POST no lugar do GET incluem: G) O total de caracteres no GET é realmente limitado (dependendo do servidor). Se o usuário digitar, digamos, um trecho extenso em uma caixa de entrada do tipo "Procurar", o GET pode não funcionar. @) Os dados que você envia através do GET são anexados à URL, lá em cima, na barra de endereços do browser; portanto, seja o que for, ficará exposto. Melhor não colocar a senha ou outra informação sensível como parte de um GET! ® Devido ao item 2 acima, o usuário não pode adicionar aos seus favoritos a página que envia um formulário, se você usar o POST em lugar do GET. Dependendo de sua aplicação, você pode querer ou não que os usuários sejam capazes de armazenar a página resultante do envio de um formulário. U7" A- . sepQ,('Q,c cQ,/fI!,I;.,I.e {JS d pal"~e+('cs Ccs dadtls ex+rQ,s). () +tl+1).1 de dadlJs ôlle vtlcê pede (;"'1/1"41" a+l"Q,vés dlJ tf:ré IIÍf'l+ad6 e explis+6 f4alll e/fl!,clÍf'a 11(J!Jr(Jwser; para +"dlJ /fI!,v'Id(J ver, JfI'I+(JS; f(J('/fI!,o./fI!, s+rl~j (J, A- (J}t.l- (JI"ij'~Q,1 f4",l-es dcs da (JJel- ófle é el1vi'4da Ctl/fl!,a st:.lici+a{i.ó. pQ,('~dl"cs ex·f.ras. 14 capítulo 1
  • 46. introdução e arquitetura At1atotMia de utMa solicitação HffF G-Ef o caminho até o recurso e quaisquer parâmetros adicionados à URL estão incluídos na "linha de solicitação". () calVlií'l!." paJ"a " NtcVJ"S/i '10 sf!f'vldcJ". ~ bl"cwseJ" es-f:Pf'tJ-flJcõ/t, A- veJ"são do SfJ!iél..fa'ldlJ. õ ~~ GET /seiect! seiectbeer'l'aste. J sp·?co.tor=aarK!itaste=mal ty HTTP/ 1.1 ).. Host: www.wickedlysmart.com User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:l.4) Gecko/20030624 Netscape/7.1 Accept: text/xml,application/xml,application/xhtml+xml,text/ Os l.eo.df!J"sdO. html;q~0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/ S("tcl-h'yã", gif;q=0.2,*/*;q~0.1 Accept-Language: en-us,en;q~0.5 Accept-Encoding: gzip,defiate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Ei servidor ... PEGUE aí para mim a página que se encontra em / select/selectBeerTaste.jsp e, ah sim, aqui estão os parâmetros para você: color = dark & toste = malty. E depressa. solicitação HTTP U---~ Servidor você está 15
  • 47. HTTPPOST At1atotftia de utfta solicitação HffP POSf As solicitações HTTP POST são designadas para serem usadas pelo browser em solicitações complexas para o servidor. Por exemplo, se o usuário acabou de preencher um longo formulário, a aplicação poderá querer que todos os dados do formulário sejam adicionados a um banco de dados. Os dados a serem enviados de volta ao servidor são conhecidos como "corpo da mensagem" ou "payload" e podem ser bem extensos. ti- VE'l'sâ'" dIJ fl',,-I-ót;óIIJ ôllE' ti bI"6WSE'1' es-I-~ stlfiCl-l-a,uló. Rost: www.wickedlysmart.com User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en- US; rv:l.4) Gecko/20030624 Netscape/7.1 Os t.eg,del"s da Accept: text/xml,application/xml,application/xhtml+xml,text/ html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/ StJltcr-l-Il.Sâ',,· jpeg,image/gif;q=0.2,*/*;q~0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,defiate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive !Jes.f.1J.lIej tlS flJ.l'v,.e.f.l'tJs E's.f."itl 4~1I1~ O Cor'fD da ~ 'lI) 11;'0.1 d" ctll'ftJ eJ ftJl'.f.fJ.".j.I)) '1â'IJ Ilc41/1i lI1e'lS~f~ aljlll/lifJ.s Çcolor=dark&taste=malty 1i'lI1l-l-4des dQ. l/Iial1E'/rQ.311eItcIJ.I'I"b.l/Iil1l1al1d" ul u ve~es cl.all1fJ.dtJde ( se usa 1Ii111 bf.:'; e fl'E'ci'sal/li seI' c(Jl<)cadlJs 114 N _.f'Dj'<)lJ.d • /I;,t.a de SlJ/tct+-aflJ.c. Ei servidor ... por favor COLOQUE Claro, eu vou procurar este isto no recurso localizado em: recurso (na verdade, uma pequena / advisor / selectBeer Taste. aplicação) e quando eu achar, do. Não se esqueça de olhar na entregarei OS dados enviados parte interna do corpo os dados no corpo da solicitação que você importantes que estou enviando. enviou. solicitação HTTP u----::.; Servidor 16 1
  • 48. introdução e arquitetura A.,atolMia de ulMaresposta HffF e que .,egócio é esse de "MIME typeN1 Agora que já vimos as solicitações do browser para o servidor, vamos dar uma olhada no que o servidor envia de volta como resposta. Uma resposta HTTP é composta de header e corpo. A informação do header informa ao browser o protocolo que está sendo usado, se a solicitação obteve êxito e que tipo de conteúdo está incluído no corpo. O corpo possui o conteúdo (por exemplo, o HTML) que o browser exibirá. A vel"s~" d4Pl"4.f.4C"/4 f) C:'dijÓ de S.f.a..f.ClS ~Cle., Sf!l"vtiJ.,1"we6 es+: Hr-rp pal"ti. a ClSa'ld4. Jeesf6s+a.. a iJ ••••versã., hx.f.(J ti., C:'dijtJ .1- HTTP/1.1 :.t ~tie 200 OK s.f.a+Cls. Set~Cookie: JSESSIONID=OAAB6C8DE415E2E5F307CF334BFCAOC1; Path~/testEL i.etJ.deI"Sde _~ f) va/tJl" d6 t.eadel" Jeesp4sh Hrrp' Content-Length: 397 "' I ;;te N!Sp6SrfJ. pa.I"a 6 Date: Wed, 19 Nov 2003 03:25:40 GMT / Server: .Apache-Coyote/1.1 C4~'1-1--I;fe e ctJl'lt.ecl'J" Connectlon: close .:6•••• If4zJ4,f. +jpe. () 4 !fA.ZIf4f. -Iype 1'I'J/41"1J'lfJ. fJ.4bl"tJwsel" 3t1e -hj>o tie dfJ.titJô bl"(Jwsel" es+: p41"4 I"ecebel"J1'41"43C1e' es+e f"ssa sdel" CõlJ'l" / pl"óces sa-/(J. /t.efal"e 3C1e' valtJl"para 6 (JIf4I!fA.f. +jfe' I"III:/el"e- se QfJS1Ia./"I"es11'$+4"6S '16 "eadel" ACCfp+ da sôltd-h.{i.(J Hrrp' (Observe (J !.eadel" l1a s6Iict+a{i.., PO.:s-rJIt. ":;I'I'Ja al1+el"161") o a resposta HTTP Cliente Servidor está 17
  • 49. solicitação e resposta ( o !H'óWSft' cria v~a , i SfJltct-fo.{i6 Itrrp iG,!'( '-V GET /test1/Beer1.html HTTP/1.1 Host: www.wickedlysmart.com User-Agent: Mozilla/5.0 (Macintosh ... Beerl.html <html><body> <hl align~eenter>Beer Login Page</hl> <form> Seleet a beer type or buy beer ~5era lI~a making supplies?<p> resf>t:Js+a <input type~radio name~seleet Itrrp' o ~erVitl<J1' e"JC6"J+r~ value~Seleet> Seleet a beer<br> 4 f>~/"'Q ••• <input type~radio name~select value=Buy> Buy supplies<br><br> <center> <input type~SUBMIT> </eenter> </form> </body></html> HTIP/1.1 200 OK Set-Cookie: ... <html><body> <hl align~eenter>Beer Login Page</hl> <forro> Seleet a beer type or buy beer . . . lJr f"f!Sf><JS.f.l1. Itrrp é eJ1vtatila 46 1 /;l'fJwser. lJr c/tel7+-e ~v4rtila fJ.I7Si;'S14~el7+-e jVf! SVo. -frtJ.I7S14í4Ó s~a Beer Login Page reallj14tila C.:l~ Sclcrt a beer type o. huy beer making supplics? sue,!SS.:l. o Select a bcer O BllY supplies 18 1
  • 50. introdução e arquitetura GETou POST? Para cada descrição, circule POST ou GET, dependendo de que método HTTP você usaria para implementar isso funcionalmente. Se você achar que pode ser ambos, circule os dois, mas esteja preparado para defender suas respostas ... POST GET Um usuário digitando um login e uma senha. POST Um usuário solicitando uma nova página via hyperlink. Um usuário em uma sala de bate-papo enviando uma resposta. Um usuário dica no botão "next" para ver a próxima página. Um usuário dica no botão de "logout" num site seguro de um banco. Um usuário dica em "Voltar" no browser. Um usuário envia um formulário com nome e endereço para o servidor. Um usuário faz uma escolha em um botão de seleção. você está 19
  • 51. Anatomia da URL URL. O que quer que você faça, t1ãO prot1ut1cie "Ean". Quando você procura a letra U no dicionário de acrônimos ocorre um congestionamento ... URI, URL, URN, onde isso termina? Por enquanto, vamos focar nas URLs, ou Uniform Resource Locators (Localizadores Uniformes de Recursos), que você conhece e ama. Todo recurso na web tem seu endereço único próprio, no padrão URL. Jeec(Jl',u,; t:J 17"""e d" C617-H!~d" Sel7dlJ s6Ilcl+lJ.dlJ. ~de seI' (J*11J. ?~/;'IJ. ~1'+4: I íS+4 I' ?41'-H! da fiJt.L. Hr14.L.; V"" Sf!I''11le+" v""a e "PCI6'10.I, fiíf'l tl17IC(J Sel'vitÍ61' i'íf'ltJ.jf!") P!JF; íf'I~Si'ca; v!Je(J stI?"I'+a v:I'i'1J.Sf61'+o.s, IV I I, 6(1 3(1IJ.I1;Vf!1' tW+1'1J.C6iSIJ. Pr.o+tJctJl,,: Il7ltu'íf'l11. U""4 ~/ico.f46 e tde'l-r'fI,co.Jo. 3ve 6 sel'lIitÍlJl' S(lelrfJ. 1'61' tlíf'lo.1'01'+0., Se vtlcê 'lã" f4.:l sel'vií/cl' (pai dl's?"17tbtli'fJ.I'. Se es+a especilical' tlíf'lo.p61'+4 f!íf'I ?I'Õ+CC(J16 de Pf4I'-H! "pcl6l7allól' t!Jíf'll-h«a; cOíf'ltll7lctJ.5';" (l7es-H! SVo. uJt.L.J IJ. fÓI'+4 80 seI': tl IJ. ""o.i6I'i'8. d6S sel'lIitÍÓl'es I' f4til'';6 I' eJ CÓI;,ettie'l-H!l/1Iel7+e J CIJ.S{JJ Hrrp'> I{ atle Iro. fl'lJC(lN.1' PCI' I;'dex,t.+"", sel'lJ. tlS4dtJ, eS+4 e fJ. "I'+fJ.-?f4Jl'ãó ? f41'fJ. ÓS sel'vitÍól't!,S wd, j fCI' ?f4dl'';C, , http://www.wickedlysmart.com:8~/beeradvice/select/beerl.html Sel'vlt1iJl': t:J t I ' 17t>íf'lf!lmc" ti" sel'lIlt1t'J1' Ca""I"'II<"; t:J ca"",;,t.6plJ.l"a a ItJcalt;,ã6; I ~ 11 IISICtJ pelt'J 3vo.I vtJce es-ra fl'tJCtll'fJ.I7J.D, '16 sel''Ilt1"I'; J(J I'f!C(lI"StJ ô(Je es+a sel7d" st:Jltct+aJlJ. 1"" vlr.fvJe de a 1S-H! 1761/11e 8.f6'1-f-1J. f41'fJ. Víf'I ~l7i'c6 el7tiel'f!j6 IP. t:Js e'lJel'ej.Ds IP íf'Iaiól'iit dos sel"!/l«lJl'es wd I/1I(M$ I "sã" '16!/t:JS I't!dal" fi 171)( IJ. Sl;,-f-alcf! thl1l)( l7t1íf'1el'i'u~s e as stlíf'le"" fJ. xxx. u .•• f J 41;,Ja e (JsadIA. al"a descl"evel" as f jj}';;;'IJ.fJ.1Il , ~ce p6de f!specl/l'c1A1' (líf'I f!"'Itiel'(j6 fIP 8.f.(li"eíf'l V('tJ tie tll/1I'16íf'1f! íf'IlJ.S t,tel'aI"3(Ji'tJ.s Je Jlre+:l"ibs. Q I J (Jíf'I170l/1le beíf'l íf'Ia.ts IlJ.crl de le*1bNJ.t', e ; 20 capítulo 1 ~~c
  • 52. introdução e arquitetura , Os '7VIlflt!1"4S lIfI~i"$ c(mt.eeM"s Je p61"+as rcpparI), tJ.Sapli"ctii;;t!s Uma porta TCP é apenas um número IIfIfJ.I"$ llIIfIV'7S 3"e N,,:i8.11f1 C ellfl St!I"VM4I"fS Um número de 16 bits que identifica um programa específico no hardware do Telnet servidor. o software do seu servidor de intemet (HTTP) roda na porta 80. Isto é padrão. Se você possui um servidor de Time Telnet, ele rodará na porta 23. FTP? 21. Servidor de e-mail POP3? 1l0. SMTP? 25. O Time server fica na 37. Considere as portas como identificadores únicos. Uma . porta representa uma conexão lógica para um determinado 110 software rodando no hardware do servidor. Só isso. Você não pode virar o seu gabinete e encontrar uma porta TCP. Por um motivo, você tem 65536 delas em um servidor HTTPS POP3 (O a 65535). Além disso, não conectamos dispositivos físicos nelas. Elas são apenas números representando uma aplicação para servidor. (J SfJ.'7Jtl V"'IJ. apltefJ.S';(J 1'41" p41"+a., li'" Sem os números das portas, o servidor não teria meios de S(!l"Vti/(Jf' ptlJe fff' 11.-# 'S-S-3(. saber a qual aplicação o cliente gostaria de se conectar. E já apli'ca{;;es Jtfel"fl1ffs I NultJ.I1JtJ que cada aplicação deve ter seu próprio protocolo, imagine (e"'!?tlf'1J. S!jl), ptJS sl'lIel f'If:lJIJ.f' o problema que você teria sem estes identificadores. E se o seu browser, por exemplo, fosse parar no servidor POP3 11<4/"$ VII<4apltCf<f';6 111), Je II<es",~ em vez do servidor HTTP? O servidor de e-mail não sabe P6f'+fJ. se elas VSIJ.N!1IfI PI"(J+(Jc6ItJS analisar uma solicitação HTTP! E mesmo que soubesse, JI"$-h"'+tJS) • o servidor POP3 não sabe nada sobre disponibilidade de páginas HTML. Se você está escrevendo serviços (programas de servidores) para rodar na rede de uma empresa, você deve checar com o administrador de sistemas quais portas já estão sendo usadas. Seu administrador poderá dizer, por exemplo, que você não Os númet9s das p91tas pode usar nenhuma porta inferior a, digamos, 3000. de O a 10Z3 sã9 o; 1 0d pata ser" lÇ95ja C9hneCl 9S TO (Inclu'iud9 a -PrIncIpalpélta h9S - a p9tta 80)$ Nã9 use estflS p9ttas 9S sen ti pt9h"tamas pattlculates! você está 21
  • 53. diretório web site A estrutura de diretórios para um site Apache simples Nós falaremos mais sobre o Apache e o Tomcat mais adiante, mas por enquanto vamos admitir que nosso site simples esteja usando o Apache (um servidor web bastante popular, de código aberto e que provavelmente você já está usando). Como parecer-se-ia a estrutura de diretórios para um site chamado www. wickedlysmart.com, hospedando duas aplicações, uma dando conselhos sobre esquiar e a outra, sobre assuntos relacionados à cerveja? Imagine que o Apache esteja rodando na porta 80. Marcamos cada uma das páginas .html com uma letra (A, B, C, D) para o exercício na próxima página. I I ípuiex.t.-r1ti1 e 4 f>~/"'4- I '" I p4dl'IJ.C 3ue Sel'4 (J"" Sf!I'Vtd61' 1Jrf>b.ct.eIJ.ss{J""tl': <) J.+dlJcs (;<)1'1I6 l'e-/-':JN1IJ.d4 4<) USU:I"iJ d d'I"e+;l'liJ-1'4l;f>fJ.NJ. +6tÂas 4S aplí'c4í';es tÂd 3ue díjt+6U WliI/liI/. / sel'vtiJ{<)I'. wtcked'jsIf!41'+.C6""/ I1IJ seu PNlliI/Sel'. lJr f4S+a-l'li.t;pfl.l'fJ. fi. apliClJ.ji!l !Jeel'lJrdvtce. ~ v: • <~bd> Index.html 22 capitulo 1 ~"
  • 54. introdução e arquitetura Apontando as URLs para o conteúdo Observe a estrutura de diretórios da página ao lado e escreva a URL que levaria você a cada uma das quatro páginas .html marcadas com as letras A, B, C e D. Nós fizemos a primeira (A) para você, porque é assim que nós somos. Para o exercício, considere que o Apache esteja rodando na porta 80. (As respostas estão no rodapé da próxima página.) Fará com que o servidor retome para você a página index.html no ponto ® Fará com que o servidor retome para você a página index.html no ponto ® Fará com que o servidor retome para você a página index.htrnl no ponto © Fará com que o servidor retome para você a página selectBeer.html no ponto ® você está 23
  • 55. páginas estáticas Servidores Web aiMaiMservir páginas Web estáticas lT pflbma esf:atma Jma .1 o ." (J apenas tep9usa lá dentt9 d9 d1tet9t19. O setv''id9t a enc9ntta e a dev'9Ive pata 9 clIente C9m9 está. '19d9 () clIente 'Vê a mesma ís.f-as f>~/"I1t1.SV';fJ di,;'e.f-(J f>tU'Q.(J 4f1i'clJ.g';fJ dle'1ff) eXfA..f-a.htt'1ff C"ht(J alie f"ddo. 1M elas f6f"alit c"/(JctAdas '1() sel''r/liA.rJf''. S,!f"IIi"JtJf" servidor Mas e se eu quiser, digamos, que a hora atual apareça na minha página? E se eu quiser uma página com conteúdo dinâmico? Eu não poderia ter algo como uma variável dentro do meu HTML? f. se 3l1lSel'htóS , f!'1cD.i'xo.f" o.'5l1hta CiHSo. V4f"1fJ.llel [ da f>~I"l1a HrKA.L? <html> <body> The current time i8 [insertTimeOnServer]. </body> </html> c- MMM'M,C~GqJÀ8lligr~'cOllipGGr~qA,CG D- MMM'M,C~GqJÀ8lligr~'cOllipGGr~qA,CG8GJGC~8GJGC~BGGr'p~llirl B- MMM·M'C~GqJÀ8lligr~·cOlli8~"uàVqA'CG J 24
  • 56. introdução e arquitetura Mas algutHas vezes você precisa de tHais do que só o servidor Mas como isso vai ajudar? Meus clientes são todos clientes web. O browser só conhece o servidor ... ou seja, ele não vai ser capaz de chamar aquela outra aplicação. o ó servidor outra aplicação do servidor Isto não é problema. Eu cuidarei de entregar a solicitação à aplicação helper correta. Aí, eu pego a resposta da aplicação e entrego de volta ao cliente. Na realidade, o cliente nunca precisa saber que outra pessoa participou do trabalho. outra aplicação do servidor você está 25
  • 57. quando um servidor não é o bastante Vuas coisas que o servidor não faz sozinho As Páh1nclSInstantâneélB Se você precisa de páginas instantâneas (páginas criadas dinamicamente e que não existiam antes da solicitação) e nã9 eXIstem antes de da capacidade para escrever/salvar dados no servidor (que l' significa escrever em um arquivo ou banco de dados), você ser te'lta a s91'lc'ltaç-ã9.E não pode contar apenas com o servidor. C9m9 tqz.er uma pâblna 1 Conteúdo dinâmico B11t[., de tepente. A aplicação que roda no servidor disponibiliza somente páginas estáticas, porém uma outra aplicação "assistente", A s91'lc'ltayã9cbet;a. q com a qual o servidor pode se comunicar, pode construir páginas dinâmicas instantaneamente. Uma página dinâmica apllcaç-ã9 beIpet ~~escteve" poderia ser qualquer coisa, desde um catálogo até um 9 BINIL, e 9 setVld9t weblog, ou até mesmo uma página que escolha imagens aleatoriamente para exibi-Ias. tet9tna a9 clIente. Quando em vez disto: Você quer isto: <html> <html> <body> <body> The curent time is The curent time is always 4:20 PM [insertTimeOnServer] on the server on the server </body> always 4:20 PM </html> on the server </body> </html> 2 Salvando os dados no servidor Quando o usuário envia os dados em um formulário, o servidor analisa os dados e pensa: "E aí? Eu devo me preocupar?". Para processar esses dados, salvá-Ios em um arquivo ou banco de dados, ou até mesmo para usá-Ios na criação da página de resposta, você precisa de outra aplicação. Quando o servidor recebe uma solicitação para uma aplicação helper, ele considera que aqueles parâmetros são destinados ao assistente. Assim, o servidor passa os parâmetros, fornecendo à aplicação uma forma de gerar uma resposta ao cliente. 26 capítulo 1
  • 58. introdução e arquitetura o fernto t1ão-Java para uttta aplicação helper que roda tiO servidor é o "C&I~~ A maioria dos programas CGI é escrita como scripts em Perl, mas várias outras linguagens podem servir, incluindo o C, o Python e o PHP. (CGI significa Common Gateway Interface - Interface de Passagem Comum -, e não nos importamos por que ele é chamado assim.) Usando o CGI, veja abaixo como funciona uma página dinâmica que possui a data atual do servidor. o servidor o usuário dica em um ~-, link que tem uma URL, que chama um CGI em aplicação vez de uma página do servidor estática. Cliente ..Cliente ) aplicação do servidor servidor parâmetros aplicação helper A aplicação do servidor "vê" que a solicitação é para o programa assistente, então o servidor abre e roda o programa. A aplicação do servidor envia junto os parâmet- ros do GET ou POST. servidor A aplicação helper constrói a nova página (que tem a data atual inserido) e devolve o HTML ao servidor. ~)Cliente aplicação helper Para o servidor, o HTML da aplicação helper é uma página estática. servidor A aplicação helper é [J aplicação do servidor fechada e o cliente recebe de volta uma página HTML contendo a data atual, agora estática, como parte você está aqui ~ 27
  • 59. dois lados, CGI e Ser,;iets Os Servlets e o CG-I aruaIM COlMOuIMa aplicação helper no servidor Preste atenção na conversa dos nossos dois faixas- pretas sobre os prós e os contras do CGI e dos Servlets. CGI Servlets o CGI é melhor que os Servlets. Nós criamos os Com todo o respeito, mestre, existem muitas scripts CGI em Perl na nossa empresa, pois todo vantagens em se usar o Java, em vez do Perl, para mundo sabe PerI. essas coisas que você quer fazer com o CGI. Eu acho que é legal usar Java, se você souber. Desempenho, por exemplo. Com o Perl, o Mas certamente, não valerá a pena para nós servidor tem que rodar um processo superpesado mudar para Java. Não há nenhuma vantagem. para todas as solicitações que sejam para este recurso! Você está me desafiando? Em quais assuntos? Ah, sim, mas os Servlets ficam carregados e as solicitações dos clientes para um recurso do Isto não é diferente do Java ... O que você chama Servlet são tratadas como threads de um único de JVM? Cada ocorrência da JVM não é um Servlet em execução. Não existe overhead ao processo superpesado? carregar a NM, as classes e tudo mais ... Eu vejo que você esqueceu muita coisa. Eu não esqueci, mestre. Mas não são todos os Atualmente, os servidores web são capazes servidores que podem fazer isso. Você está se de manter um único programa Perl rodando referindo a um caso isolado que não se aplica entre as solicitações dos clientes. Por isso, seu a todos os programas CGI em PerI. Porém, os argumento de que ele é mais pesado não vale Servlets serão sempre mais eficientes quando isso de nada. ocorrer. E não vamos esquecer que um Servlet pode ser um cliente J2EE e um programa CGI em Perl não. Do que você está falando? Qualquer coisa compatível com o CORBA pode ser um cliente J2EE. Eu não quero dizer um cliente para um programa J2EE, e sim um cliente que é um J2EE. Um Servlet rodando em um container J2EE pode Chega, estou atrasado para minha aula de Pilates. participar da segurança e das transações com Mas não pense que acabou. Vamos terminar isso enterprise beans e existem ... mais tarde. continua ... Eu duvido que todos saibam PerI. Eu gosto do Perl, mas todos somos programadores Java aqui na empresa; então, preferimos Java. 28 capítulo 1
  • 60. introdução e arquitetura o I/Sil~l'íé. J.iji.f(J, t/W(J, u~l-. Solicitação ~ Resposta 11 HTTP/U Complete as caixas GET /test1lBeer1.htm . WicKedysmart.com escrevendo o que acontece Host. www· '1 /5 o (Macintosh ... user-Agent: Mozl a . durante cada passo no processo. Esta é uma cópia da página 18. Ou seja, <htrnl><body> ao terminar, volte lá para <hl align=center>Beer Login Page</hl> comparar suas respostas. <forro> Seleet a beer type ar buy beer making supplies?<p> <input type=radio name=select value=Select> Select a beer<br> <input type=radio name=select value=Buy> Buy supplies<br><br> <center> <input type~SUBMIT> </center> S·d~i ervl or </form> </body></html> 1 HTIP/1.1 2000K Set-Cookie: ... <html><body> <hl aIign=center>Beer Login Page</hl> <Íorrn> SeIeet a beer type or buy beer ... A- c!ie#i-fe fJ.5t/tJ.1'ç(fi. a#iSl(jSfA~e#i-fe ~tlf st/a .ff'fI.#isa{i(J Beer Login Page S~(J, f'f4'l-;l'J.tifl. c.o~ St/Cf!S SlJ. Select a beer type or buy beer making .supplies? O Selccr a beer C Buy $upplíes você está 29
  • 61. uma rápida olhada nos servlets Servlets Desmistificados (criar, distribuir, executar) Pois é, os novatos em servlets já podem parar de prender a respiração; aqui está um guia rápido para criar, distribuir e executar um servlet. Este guia pode gerar mais perguntas que respostas - não se assuste! Você não precisajazê-Io neste exato momento. É O apenas uma rápida demonstração para tutorial mais não conseguem / esperar. O próximo capítulo inclui um aqueles que detalhado/ Construa esta árvore de diretórios (em qualquer lugar, exeeto sob o tomcat). Ch1Servletjava weh.xml 8 Crie um servlet chamado ChlServlet.java e o coloque no diretório sre (para simplificar este exemplo, não colocaremos o servlet em um pacote; mas após este, todos os outros exemplos com servlet neste livro estarão em pacotes). import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public void doGet(HttpServletRequest request, HttpServletResponse response) public class ChlServlet throwsextends HttpServlet IOException { { ~ PrintWriter out ~ response.getWriter(); ou t .pr in tln ("<h tml> " + rrrJl4.L IPJSf;l"it/.t) "<body>" + vw, PI"t)51"fJ.""'(J. Java. '" J ";. e"", J 'l" "<hl align~center>HF' s Chapterl Servlet</hl>" + ;1"1J!t) + "<br>" + today + "</body>" + "</html>"); IV! java.util.Date today ~ new java.util.Date(); "46 ti! w,es""'(J? 8 Crie um deployment descriptor (DD) chamado web.xml e ponha-o no diretório ete. c.<J"Jsi'tI.eN4;es l-a'J.f-e S: 1Ry>4/'•• - (J :b!J pfJ.l"tI.c!J.t/.fJ. "'" <?xml version="l.O" encoding-"ISO=8851-1" ?> <web-app xmlns=''http://java.sun .com/xml/ns/j 2ee" apliClJ.yfltJ web. xmlns: xSi= ••ttp://www.w3.org/200l/XMLSchema-instance h -(JltlJ!Jpt)t/.eJ.ecllU.1J.1.. •• xsi:schemaLocation~''http://java.sun.com/xml/ns/j2ee/ !. V8.1"14Ssel'v Ie.,-s. I http://java.sun.com/xml/ns/j2ee/web-app 2 4.xsd" version="2.4/> - (JIt <:'sel'lIle-!-'JIJ.w,e> <servlet> 4 1J.""'41'1'1J. e/e"",e",-!-a <servlet-name>Chapterl Servlet</servlet- name> <:.sel'lIle-!-> 4tJ ele""'e,,-!-a <servlet-class>ChlServlet</servlet-class> <:.sel'v1e-!-lttJ.pp'-"5 >. </servlet> - (J1t<:'sel'lIle-!-clfJ.ss> é </servlet-mapping> IJ. clfJ.Sse J4VIJ.. <servlet-name>Chapterl Servlet</servlet- name> - 11"", <:'fll"l-pfJ.fflM> é <url-pattern>/Servl</url-pattern> (J ",,,,,,,,e afie" dle,,-h flSfJ. </servlet-mapping> </web-app> 1'41'4 a s4IiCi-!-tJ.{i6. 30 capítulo 1
  • 62. introdução e arquitetura o Construa esta árvore de diretórios abaixo do diretório tomcat existente ... o Do diretório projectl, compile o servlet... o nome da aplicação web servlet-api.jar -d classes src/ChlServlet.java (IS+6 +V1I16é VII'I ~"l'c6 Ct)II'IIU'I1I14) ~ [%javac -classpath /your path/torncat/common/lib/ (o arquivo Chl Servlet.class vai terminar em projectl/classes) o Copie o arquivo ChlServlet.class para WEB-INF/classes, arquivo web.xml para o diretório WEB-INF. eo fi Rode o Tomcat a partir do diretório tomcat ... %bin/startup.sh Ch1Servlet.class o Abra seu browser e digite: http://localhost:8080/chl/Servl deve aparecer: HF's Chapterl Servlet Tue Feb 10 15:01:24 MST 2004 @) Por enquanto, toda vez que você atualizar ou uma classe de servlet, ou o deployment descriptor, dê um shutdown no Tomcat: %bin/shutdown.sh você está aqui •. 31
  • 63. HTML em um println() não rola I ••• I Sem ofensas, mas existe f. 4SSI"" IJ 'l.(le lI.:lce CI'I"!A t:>(J,f;1i14 (11104 r " dli1M-.tc(J,e~ (I~ sel'lIle.f-. +ello 3ye alguma coisa SERIAMENTE errada com esta figura sobre I~cê servlets ... tentando enfiar o ex"!!ll' .f-yJ() pal'fJ. y~fJ. salda ex+eI''JfJ. ('JfJ. HTML dentro de um printlnO?? Isso não pode estar correto.. .A J. ' L .A J V!!I'91"'14l1e) I$S4 e plJ.l''TT:."1(;, I'espas-r(;, JlrrO rr r ••• j' &' /I"r ...Iev_ ,.. . ....~('.".I.). out.println(~<html> ~ + ~<body>" + ~<hl>Skyler's Login Page</hl>" + ~<br>" + today + ~</body>" + ~</html>"); Na verdade, tehtar fort1atar o HfM. dehtro de Ut1out.prihtlhO hO servlet é pior aihda. Esta é uma das piores partes (não, a pior parte) dos servlets. Enfiar tags HTML, devidamente formatadas, dentro do printlnO, só para que você possa inserir variáveis e métodos de chamadas é simplesmente uma crueldade. Nem pense em inventar coisas, ainda que pouco sofisticadas. r: Não pode ser tão ruim assim ... Por que eu não posso simplesmente copiar uma página HTML inteira do meu editor, como o Dreamweaver, e colar dentro do printlnO? Não é só para eu ser capaz de ler o código lá dentro? 1: Obviamente, você ainda não tentou fazer isso. Que bom. Sim. Eu faço minha página em um editor decente (ou até mesmo um simples arquivo de texto seria mais fácil que no meu código Java) e, então, faço um copiar/colar rapidinho no printlnO e pronto! Pena que você vai receber 1.378 erros de compilação. Lembre-se de que você não pode ter um carriage return (retorno de carro) de verdade dentro de uma String literal. E já que estamos falando de Strings ... o que dizer do seu HTML com todas aquelas aspas duplas? 32 capítiulo 1
  • 64. introdução e arquitetura Oh, se pelo menos existisse uma maneira de colocar o Java dentro de uma página HTML, em vez de colocar o HTML dentro de uma classe Java. Ela ttão cottheee o JSP <html> <body> DptJ.!Is+;;; se p4.t'ece CIJIM <hl>Skyler's Login Page</hl> <br> VIM pf.'1pe.l1tJ "fIM l1ó <%= new java.util.Date() %> 1Mf./~ Je VIM H-rA4.L?! </body> </html> sky/erlogin.jsp Uma página JSP é bem parecida com uma página HTML, com a diferença de que você pode inserir Java (e coisas relacionadas ao Java) dentro da página. Portanto, é realmente semelhante a inserir uma variável no seu HTML. você está aqui ~ 33
  • 65. o Java encontra o HTML = JSP JSP foi Oque acottteceu quatldo alguéttt apresetltou o Java ao HfML Itlserir o Java tiO HfML é a solução para dois probletttas: 1 Nem todos os designersque fazem páginas em HTML conhecem Java Os desenvolvedores de aplicação sabem Java. Já os designers de páginas sabem HTML. Com o JSP, os desenvolvedores Java fazem a parte Java, enquanto que os desenvolvedores HTML fazem as páginas. 2 Formatar o HTML dentro de uma String literal é REALMENTEterrível Inserir um HTML, mesmo que levemente complexo, dentro de um argumento em um printlnO é esperar que ocorra um erro de compilação. Pode ser que você tenha que fazer um trabalho enorme para formatar o HTML, de forma que ele funcione no browser do cliente, mas satisfaça as regras do Java para aquilo que ele for designado a fazer na String. Você não pode ter, por exemplo, carriage returns, embora a maioria dos HTMLs que você baixa e edita terá carriage returns de verdade na fonte. As aspas podem significar um problema também - muitas tags HTML usam aspas antes e depois dos valores para atributos, por exemplo. E você sabe o que acontece quando um compilador dá de cara com as aspas duplas ... ele pensa "este deve ser o final da String literal". Naturalmente, você pode voltar e substituir suas aspas duplas pelos escape codes ... mas isso tudo aumenta demais a chance de erros. r: Espere ... ainda tem algo de errado aqui! A vantagem número 1 diz que "nem todos os designers de páginas sabem Java ...", mas quem cria páginas em HTML ainda tem que escrever o Java dentro da página J5P! O J5P alivia o programador Java de escrever o HTML, mas ele não ajuda, de fato, o designer que cria o HTML. Poderia ser mais fácil escrever o HTML em um J5P, em vez de num printlnO, mas o profissional que escreve o HTML ainda terá que saber Java. I: Parece que sim, não parece? Mas com a nova especificação para o JSP - e seguindo alguns conselhos -, o desenvolvedor da página incluirá, de Java mesmo, muito pouco (ou nenhum) no JSP. Eles terão que aprender alguma coisa ... mas algo como colocar labels que de fato chamem os métodos Java, em vez de escrever o código Java real na página mesmo. E terão que aprender a sintaxe JSP, mas não a linguagem Java. 34 capítulo 1
  • 66. introdução e arquitetura HTTP significa HyperText Transfer Protocol (Protocolo para Transferência de Hipertexto), e é o protocolo de rede usado na Web. Ele roda no topo do TCP/IP. O HTTP usa um modelo solicitação/resposta - o cliente faz uma solicitação HTTP e o servidor web devolve uma resposta HTTP, que o browser então calcula como tratá-Ia (dependendo do tipo de conteúdo da resposta). Se a resposta vinda do servidor for uma página HTML, o HTML é adicionado à resposta HTTP. Uma solicitação HTTP inclui a solicitação URL (o recurso que o cliente está tentando acessar), o método HTTP (GET, POST, etc.) e (opcionalmente) os dados de parâmetros do formulário (também chamado de "query string"). Uma resposta HTTP inclui um código de status, o tipo de conteúdo (também conhecido por MIME type) e o conteúdo real da resposta (HTML, imagem, etc.). Uma solicitação GET anexa dados do formulário no final da URL. Uma solicitação POST inclui dados do formulário no corpo da solicitação. Um MIME type informa ao browser que tipo de dados ele deverá receber, para que o browser saiba como tratá-Ios (processar o HTML, mostrar o gráfico, tocar a música, etc.). URL significa Uniform Resource Locator (Localizador Uniforme de Recursos). Todo recurso na web tem seu próprio e único endereço neste padrão. Ele começa com o protocolo, seguido pelo nome do servidor, um número de porta opcional e geralmente um caminho específico acompanhado do nome do recurso. Opcionalmente, ele também pode incluir uma query string, se a URL for para uma solicitação GET. Os servidores web são bons em disponibilizar páginas HTML estáticas, mas se você precisa de dados gerados dinamicamente na página (como a hora atual, por exemplo), você precisará de algum tipo de helper que possa trabalhar com o servidor. O termo não-lava para estas aplicações assistentes (freqüentemente escritas em Perl) é CGI (que significa Common Gateway Interface - Interface de Passagem Comum). Colocar o HTML dentro de uma declaração println( ) é terrível e suscetível a erros, mas os lSPs solucionam este problema ao permitir colocar lava em uma página HTML, em vez de colocar o HTML dentro de um código lava. você está 35
  • 67. A arquitetura da aplicação web Os servlets precisam de ajuda. Quando uma solicitação chega, alguém tem que instanciar o servlet ou, pelo menos, criar uma nova thread para tratar a solicitação. Alguém tem que chamar ou o método do PostO ou o método doGetO do servlet. E, claro, esses métodos possuem um argumento crucial - os objetos request e response HTTP. Alguém precisa levar a request e a response para o servlet. Alguém precisa gerenciar a vida, a morte e os recursos do servlet. Esse alguém é o Container. Neste capítulo, vamos ver como sua aplicação roda no Container e daremos uma primeira olhada na estrutura de uma aplicação usando o padrão de projeto Model View Controller (MVC). este é um novo capítulo ll> 37
  • 68. objetivos do exame oficial da Sun 06jetivgs IS!!hS.i ....- - - A Arquitetura das Aplicações de Alto Nível Notas sobre a Abrangência: 1.1 Para cada Método HTTP(como GET, POST, HEAD e assim por diante), descrever o Todos os objetivos nesta seção serão abordados seu propósito e as características técnicas completamente em outros capítulos. Portanto, considere este capítulo como uma base para o que do protocolo do Método HTTP, listar virá depois. Em outras palavras, não se preocupe os triggers que podem levar o cliente em terminar este capítulo sabendo (e recordando) (geralmente um browser) a usar o Método assuntos especificos destes objetivos. e identificar o método HttpServlet que corresponde ao Método HTTP. Não existirá nenhuma pergunta sobre estes assuntos nos testes práticos, até que você chegue ao capítulo especifico em que eles serão abordados. 1.4 Descrever o propósito e a seqüência de eventos Aproveite este material legal, simples e que do ciclo de vida do servlet: (l) carregar a servirá de base enquanto você pode! classe do servlet, (2) instanciar o servlet, (3) PORÉM .. você precisa conhecer estes assuntos chamar o método init, (4) chamar o método para prosseguir. Se você já tem alguma service, e (5) chamar o método destroy. experiência com servlet, poderá simplesmente pular as páginas, olhar as figuras, jazer os exercícios e avançar para o capítulo 3. 2.1 Construir a estrutura de arquivo e diretórios de uma aplicação que contenha (a) conteúdo estático, (b) páginas JSP, (c) classes do servlet, (d) o deployment descriptor, (e) bibliotecas de tags, (f) arquivos JAR, e (g) arquivos de classe Java; e descrever como proteger os arquivos de recurso do acesso HTTP. 2.2 Descrever o propósito e a semântica para cada um dos seguintes elementos do deployment descriptor: instância do servlet, nome do servlet, classe do servlet, parâmetros de inicialização do servlet e a URL que aponta para o respectivo servlet. 38 capíitulo2
  • 69. arquitetura de alto nív~1 o que é um Container? Os servlets não possuem um método mainO. Eles estão sob o controle de outra aplicação Java chamada Container. o Tomcat é um exemplo de Container. Quando sua aplicação web (como o Apache) recebe uma solicitação para um servlet (ao contrário de, digamos, uma antiga e estática página HTML), o servidor entrega a solicitação não ao servlet em si, mas para o Container no qual o servlet é distribuído. É o Container que entrega ao servlet a request e a response HTTP, e chama os métodos do servlet (como o doPostO ou o doGetO). servidor código Y Java aplicação do Container web servidor você está aqui 11> 39
  • 70. ti vida sem servlets E se você tivesse o Java e não tivesse nelt servlets, net1 Oontaineres? E se você tivesse que escrever um programa em Java para tratar as solicitações dinâmicas que chegam na aplicação do servidor (como o Apache), mas sem um Containet como o Torncat? Em outras palavras, imagine que não exista nada como os servlets e tudo que você tem são as bibliotecas principais do J2SE? (É D O claro que você pode admitir que tem a possibilidade de configurar a aplicação do servidor para que ela possa chamar a sua aplicação Java). Tudo bem, você ainda não sabe bem o que o Container faz. Apenas imagine que você precise de um suporte ao lado do servidor para uma aplicação e tudo o que você tem é um Java antigo e comum. Liste algumas das funções que você teria que implementar numa aplicação J2SE Se não existisse o Container: "'U!J9UI~m ~p Olu~UIu~:)ml~ll'iud~ "'dSf ~llodns 'sllol OUIO:) US~O;) S lUlllY IUl~nb 'u6U1un1l~slUlu~m~ldm~ 'spu~.nn ~p lOPU~;)U~l~ll lU!J;) :s~~AJssodSUlsods~lI mn 40 capitulo 2
  • 71. arq'uít,'Jtwra de alto nível o que o Cotttait1er oferece? Nós sabemos que é o Container que gerencia Gta'i.cts a9 C9nt:Unet, VOCÊ p9de se C9noonttélt e roda o servlet, mas por quê? Vale a pena o overhead extra? mais na 1.1" " 9hICa d9 seu .. pt9ptl9 neh9c19, em ve;z de o container oferece uma maneira simples para seus se pte9cupat em esctey'et servlets se comunicarem com seu servidor. Você não c9dIh9s pata thteads, precisa construir um ServerSocket, escutar uma porta, sehutétn,?a e tede. criar tráfego, etc. O Container conhece o protocolo entre o servidor e ele mesmo, para que seu servlet não tenha que se preocupar com uma API entre, digamos, VOCÊ tem 'Lue.- étnallz.éu' c o servidor Apache e o código da sua própria aplicação. t9da a sua enetgIa na Tudo o que você tem que se preocupar é com a lógica Ctla,?ã9 de uma 19ja y'Iltual do seu próprio negócio, que está contida em seu Servlet tabu19sa pata embalélhens (como aceitar um pedido na sua loja virtual). de p1â5tlc9-b91ha e deIxat . .. . .- 9S sety'I,?9S de SUP91te, O Container controla a vida e a morte dos seus servlets. C9m9 a sehutétn,?a e 9 Ele cuida de carregar as classes, instanciar e inicializar Pt900SSament9 JSf, pélta 9 " os servlets, chamar os métodos do servlet e tornar C9ntUnet. as instâncias do servlet aptas a coletar o lixo. Com o Container no controle, você não precisa se preocupar tanto com o gerenciamento dos recursos. O Container cria Agora, tudo o que eu tenho que automaticamente uma nova thread em Java para cada me preocupar é como vender me suado plástico-bolha, em vez de request do servlet recebida. Quando o servlet conclui a escrever todos aqueles códigos execução do método de serviço HTTP para a solicitação para as coisas que o Container fará daquele cliente, a thread termina (isto é, morre). Isto não para mim ... significa que você está liberado da segurança do thread - você ainda pode ter problemas de sincronização. Porém, contar com o servidor para criar e gerenciar as threads para o O as várias solicitações ainda nos poupa de muito trabalho. Certeza de segurança Com um Container, você pode usar um deployment descriptor XML para configurar (e modificar) a segurança, sem ter que escrever direto no código da classe do seu servlet (ou qualquer outro). Pense nisso! Você pode gerenciar e alterar sua segurança sem tocar, ou recompilar, seus arquivos-fonte em Java. Suporte ao .,ISP Você já sabe como os JSPs são legais. Bem, quem você pensa que se encarrega de traduzir aquele código JSP em Java de verdade? É claro. O Container. está 41
  • 72. o Container Co~o o Comaitter trata u~a solieita~o Vamos economizar alguns dos cartuchos para mais tarde, mas aqui está um breve esquema: o o usuário dica em um link que contém uma URL para um servlet, container em vez de uma página estática. -, Cliente • o container "vê" que a request é para um servlet e então ele cria dois objetos: 1) HttpServletResponse 2) HttpServletRequest response -. Cliente o container encontra o servlet correto baseado na URL da request, cria ou aloca uma thread para essa request, e passa os objetos request e response para a thread do servlet. 42 capítulo 2
  • 73. arquitetura de alto nível , I I j i ~ O container chama o método serviceO do I ! C1J • containe~~er~let servlet. de request, do tipo Dependendo] " 1,1,: __ <--::::.J o método serviceO chama ou o método request • '"/ 1 doGetO, ou o método response. serviceO doPostO· Para este exemplo, consideraremos que a request foi um HTTP GET. -. Cliente o container response servlet I O I serviceO ,J. doGetO O método doGet gera uma página dinâmica e a insere no objeto response. Lembre- se, o container ainda tem uma referência do objeto response! O thread termina, o container converte o objeto response container em uma response HTTP, envia de volta ao cliente e apaga os objetos request e response. res~ re~ você está aqui ~ 43
  • 74. o código do servtei Cotto fica O código (o que toma utt servlet UttservletJ PrintWriter out ~ response.getWriter(); java.util.Date today = new java.util.Date(); out.println(ft<html> ft + "<body>" + ft<hl style="text-align:center>" + .•. ftHF's Chapter2 Servlet</hl>" + 4ce pl:Jtle c6J?se5uir u~ "<br>U + today + ft</body>" + PrlPi-PNl't-t-e1' dó ótJe+ó ft</html>"); ~ue 6 seu sel'vle+ I'ecebe d6 C6111+tJ.fPiel'. ti+lit"3e l:JPrlJ?.fWl'l-t-e1' pt1.Nl escl'evel' -t-eX+6 #rJlA.L J?() tltJe+6 l'esptJlIIse. Me; p<Jde "'I""f:1' I "" r r 1._ (j(l-rI't1.S 6pf6es de sQlda ale~ tltJ Prll1-PNl'lhl') pal'(J, escl'evel'.) hx+" ffrJlA.L) dija~6sll u~1.l f~(lf'aJ e~ vej de u~ Nã9 exIst~m f eth'untél5 Idl9téls r: Você foi muito superficial ao explicar como o container encontrou o servlet r: e Eu me lembro de ter visto o doGetO o doPostO, mas na página anterior você correto ... ou seja, como uma URL se mostrou o método serviceO? De onde ele relaciona com um servlet? O usuário tem surgiu? que digitar o caminho exato e o nome do arquivo de classe do servlet? I: Seu servlet herdou isso do HttpServlet, que herdou isso do GenericServlet, que I: Não. Mas esta é uma boa pergunta. herdou isso do ... ahhh, nós veremos muita Mas ela nos leva a um Assunto Bem Grande hierarquia de classes no capítulo Sendo um (mapeamento de servlet e padrões de URL). Servlet; portanto, aguarde só um pouquinho. Portanto, daremos apenas uma rápida olhada nas próximas páginas, mas veremos muito mais detalhes adiante (no capítulo sobre Distribuição). 44 2
  • 75. arq'uitE,1fW"a de alto nível Você está se perguntat1do COlMO o Contait1er et1cotttrou o Servlet ... De alguma forma, a URL que chega como parte da solicitação do cliente é mapeada para um servlet específico no servidor. Este mapeamento de URLs para servlets pode ser tratado de várias formas e é um dos assuntos fundamentais que você irá lidar como desenvolvedor de aplicação. A solicitação do usuário deve mapear para um servlet específico e cabe a você entender e (geralmente) configurar este mapeamento. O que você acha? EXERCITE Como o Container deveria mapear os servlets para as URLs? o usuário faz alguma coisa no browser (clica num link, clica no botão "Enviar", digita uma URL, etc.) e espera-se que esta ação envie a solicitação para um servlet especifico (ou outra aplicação como o JSP) que você construiu. Como isso pôde acontecer? Para cada um dos seguintes procedimentos, considere os prós e os contras. o Escrever o mapeamento direto no código da sua página HTML. Em outras palavras, o cliente está usando o caminho exato e nome do arquivo (de classe) do servlet. PRÓS: CONTRAS: • Usar as ferramentas do fabricante do seu Container para criar o mapeamento: PRÓS: CONTRAS: • Usar algo como uma tabela de propriedades para armazenar os mapeamentos: PRÓS: CONTRAS: você está 45
  • 76. o mapeamento URLS para senl/ets Uttt servlet pode ter fRÊS notttes Um servlet tem um nome do caminho para o arquivo, obviamente, como classes/registrationlSignUpServlet.class (um caminho para um arquivo de classe real). O legítimo desenvolvedor da classe do servlet escolhe o nome da classe (e o nome do pacote que define parte da estrutura de diretórios), e o local no servidor define o nome completo do caminho. Mas qualquer pessoa que distribua o servlet também pode atribuir a ele um nome de distribuição especial. Um nome de distribuição é simplesmente um nome interno secreto, que não precisa ser igual ao nome da classe ou do arquivo. Ele pode ser igual ao nome da classe (registration.SignUpServlet) ou o caminho relativo para o arquivo da classe (classes/registrationlSignUpServlet.class), mas também pode ser algo completamente diferente (como EnrollServlet). Pra terminar, o servlet tem um nome público de URL - O nome que o cliente conhece. Ou seja, o nome codificado no HTML de modo que, quando o usuário clicar em um link, que se supõe que vá àquele servlet, este nome público de URL é enviado ao servidor na solicitação HTTP. () o Nome da URL Nome interno secreto Nome do arquivo conhecido pelo cliente conhecido pelo verdadeiro distribuidor O cliente vê uma URL que liga A classe do servlet do a um servlet (no HTML), mas O distribuidor pode criar desenvolvedor tem um nome não sabe realmente como esse um nome que somente seja completamente qualificado, nome de servlet mapeia para conhecido apenas por ele e que inclui os nomes da classe e verdadeiros arquivos e diretórios pelos outros que participam da do pacote. O arquivo de classe de volta ao servidor. O nome área operacional de verdade. do servlet possui um nome público de URL é um nome Este também é um nome de arquivo e caminho real, falso, criado para os clientes. falso, criado somente para a dependendo de onde o pacote distribuição do servlet. Ele não com a estrutura de diretórios precisa coincidir nem com a resida no servidor. URL pública usada pelo cliente, NEM com o nome do arquivo verdadeiro ou o caminho da classe do servlet. 46 capítulo 2
  • 77. arquitetura de alto nível Nossa, é interessante como todo mundo quer expressar Sua criatividade e aparecer com seus próprios nomes para se referir à mesma coisa. Mas por que será?! Realmente? Por que nós todos não usamos o único, real e inconfundível nome do arquivo? D o Mapear O nome dos servlets aumenta a flexibilidade e a segurança da sua aplicação. Pense nisso. Então, você escreveu direto no código o caminho verdadeiro e o nome do arquivo em todos os JSPs e nas outras páginas HTML que usam aquele servlet? Ótimo. Agora, o que acontecerá quando você precisar reorganizar sua aplicação e, possivelmente, mover coisas para diferentes estruturas de diretórios? Você realmente quer forçar todos que usam aquele servlet a conhecer (e seguir eternamente) esta mesma estrutura de diretórios? Mapear o nome, em vez de codificar o verdadeiro caminho e nome do arquivo, garante-lhe flexibilidade ao mover as coisas. E evita aquele pesadelo na hora de acompanhar e mudar o código do cliente que aponta para a antiga localização dos arquivos dos servlets. E quanto à segurança? Você realmente quer que o cliente saiba exatamente como é a estrutura no seu servidor? Você quer que eles, digamos, tentem navegar diretamente para o servlet, sem passar pelas páginas e formulários corretos? Pois, se o usuário final puder ver o caminho verdadeiro, ele pode digitá-lo em seu browser e tentar acessá-lo diretamente. você está 47
  • 78. o mapeamento do servlet no DO Usando o VeploytMettt Vescriptor para tMapear as URLs aos servlets Quando você for distribuir seu servlet em seu Container, você criará um documento XML, razoavelmente simples, chamado Deployment Descriptor (DD), para informar ao Container como executar seus servlets e JSPs. Embora você use o DD para outras tarefas além de simples mapeamento de nomes, você usará dois elementos XML para mapear as URLs aos servlets - um para mapear o nome público de URL conhecido pelo cliente para o seu próprio nome interno, e o outro para mapear seu próprio nome interno para um nome de classe completamente qualificado. Os dois elementos do DD para mapeamento de URL: <servlet> mapeia o nome interno para o nome da classe completamente qualificado <servlet-mapping> mapeia o nome interno para o nome público de URL , () elelJe'l-f.(j 'IalJe:> e IIsad" IIIJ efew,fl'1+1J li! 1Iw, "I''''"S'' dtll$ sel'vle-f.s. p.n"r ' ( ~ <web-app ...> <sfl'vle+:> 4(jC{;j'l+4/~el'l' fi <servlet> <servlet-name>Internal name l</servlet-name> I~sel'e de </servlet> ~{;ji'J{;jw,(! <servlet> <servlet-class>foo.Servletl</servlet-class> flJ <servlet-name>Internal name 2</servlet-name> <servlet-class>foo.Servlet2</servlet-class> </servlet> • • ••••••••••...........••....••••••••..••••••••• 'Ii! <servlet-name>Internal name l</servlet-name> c~ss <url-pa~tern>/Publicl</url-pattern> tl </servlet-mapplng> ti e1ew,e'l+/<serVlet-maPPlng> ~ lisa 'ItI, IS+tlftl Ó I.IIP~ '~ li!: ti I'jt:;w,f! t ftl,I'4 <servlet-mapping> <servlet-name>Internal name 2</servlet-name> <url-pattern>/Public2</url-pattern> </servlet-mapping> ; I </web-app> Z. I.IS«I' WtlJcllil'JS 1'10 48 2
  • 79. arquitE1tW"a de alto nível Mas espere! retlt tltais coisa que você pode fazer COtlt o UU Além de mapear URLs aos servlets verdadeiros, você pode usar o DD para personalizar outros aspectos da sua aplicação, incluindo atribuições de segurança, páginas de erro, bibliotecas de tags, informações sobre a configuração inicial e, se for um servidor J2EE completo, você pode inclusive declarar que o de,p19fment de,SCtlpt9l" estará acessando enterprise javabeans específicos. (DD) 9te,l"e,ce,um Não se preocupe ainda com os detalhes. O ponto crucial, por enquanto, é que o DD oferece uma manéira de me,céUllsm9 ~·doolfltad9" modificar declaradamente a sua aplicação, sem alterar o código- fonte! pata a cust9m1zayã9 das Pense nisso ... significa que mesmo aqueles que não são suas apl'lcély9e,s, se,m t9Cm' programadores Java podem personalizar sua aplicação Java, sem precisar arrancá-Io das suas férias ao sol. n9 c9dlg9--t9nte,! Nã9 ex'íSbiom pethuntélS Idl9téls r: Estou confuso. Olhando para o DO, você ainda não tem nada que indique o Os Benefícios do DO Reduz a necessidade de alteração verdadeiro nome do caminho do servlet! do código-fonte que já foi testado. Apenas diz o nome da classe. Isto ainda não responde à pergunta de como o Permite que você ajuste os recursos Container usa aquele nome de classe para da sua aplicação, mesmo que você encontrar um arquivo de classe de um não possua o código-fonte. servlet específico. Existe ainda UM OUTRO Permite que você adapte sua mapeamento em algum lugar que diga que aplicação de acordo com diferentes tal nome da classe, mapeia para tal arquivo recursos (como bancos de dados), em tal lugar? sem ter que recompilar e testar nenhum código. 1: Você prestou atenção. Você está certo, Facilita a manutenção das pois colocamos apenas o nome da classe informações dinâmicas sobre (totalmente qualificada para incluir o nome do segurança, tais como listas de controle pacote) no elemento <servlet-class> . Isso é de acessos e funções de segurança. porque o Container tem um lugar específico Permite que aqueles que não em que procurará por todos os servlets para os sejam programadores modifiquem quais você especificou um mapeamento no DO. e distribuam suas aplicações, Aliás, o Container usa um sofisticado esquema enquanto você dá mais atenção de regras para encontrar um par entre a URL às tarefas mais interessantes. Por que chega da solicitação do cliente, e uma exemplo, se o seu guarda-roupas classe Java real localizada em algum lugar do está apropriado para uma viagem servidor. Mas entraremos neste assunto em ao Havaí. um capítulo mais adiante (em Distribuição). Por enquanto, o mais importante que você deve lembrar é que você pode fazer isto mapeando. •• 49
  • 80. Bob se corresponde no site História: Job Cot1strói Uit Site de Et1cotrtros Marcar um encontro está dificil hoje em dia. Quem tem tempo, quando tem sempre um outro disco para ser desfragmentado? Bob, que quer uma fatia desse mercado virtual (o que sobrou, pelo menos), acredita que criar um site de encontros específico para nerds é o seu passaporte para deixar o emprego Dilbertiano1 que ele tem agora. O problema é que Bob já é um gerente de software há tanto tempo, que ele está, digamos, por fora das práticas atuais de engenharia de software. Mas ele conhece alguns conceitos básicos, um pouco de Java e já leu um pouco sobre servlets. Ele então faz um projeto rápido e começa a escrever o código ... Input your state Handle ~I ~ GeekDates Age OS ~I ~! ~ _ Attributes ~! _ Exceptionsl~ _ Refactor DQLQuery Modify your profile: [profile hereJ I===~-=== __ 50 caplitulo 2
  • 81. arquitetura de alto nível Ele cotMeça a construir utMa porção de servlets ... UtM para cada página Ele pensava em ter um único servlet, cheio de testes if, mas decidiu que servlets separados seriam mais 00 - cada servlet deveria ter uma responsabilidade, como a página de questionário, a página de cadastro, a página com os resultados da busca, etc. Cada servlet terá toda a lógica de negócio que precisa para modificar ou ler o banco de dados e exibir o HTML de volta com os dados da resposta do cliente. II declarações de import public class DatingServlet extends Http$ervlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { II a lógica de negócio entra aqui, dependendo II do que este servlet deve fazer II (escrever para o banco de dados, fazer a query, etc.) PrintWriter out = response.getWriter(); II escreve a página HTML dinâmica out.println( ~something really ugly goes here") ; 101HI1 IonOI 1010100001.0 lQHllOO 010101 101101 lOllOl 1010100001.0 f) servle-l-fa~ 4 ?l.le 10111100 lClOlOl lClOlOlO (110101. 101C101 ele precise parí3.prtlCe:ssal" a 1001010101 10101010 InputDQLServlet 1001010101 S4IiCl·h{i4 (C4"M4/;,seri'r (J~ SignupServlet 101101 101101 DoDQLQueryServlet Jat/4 4(J prtIC(Jrlu' #tt! [J WIOIOOOOIO 1010100 010101 101(1101 Je: t/aJ4s) e: , , 1.0101010 1001010101 web Accept 19nup ervlet 1/1714 #tarespt!#tse , server/container 10110l 1ãJa a 145,éo.Je 101101 10101000010 pa51;,a Je respal1se , 1010100 010101 1010101 10101010 1001010201 AcceptProfiJeChangesServlet J~ clte#t+e MainPageServ et InputProfileChangesServJet c~Jij~ t/a você está aqui ~ 51
  • 82. 80b adiciona JSPs Mas fica horrível e ele acrescetrta os JSPs Aquelas declarações printlnO irritantes para saída de resposta se tomam realmente terríveis muito rapidamente. Ele lê sobre os JSPs e decide fazer o design deste JSP está muito com que cada servlet faça qualquer que seja a tranqüilo. Agora. o código do servlet está mais claro... cada lógica de negócios de que ele precise (query no servlet roda sua própria lógica e chama um JSP específico para banco de dados, inserir ou atualizar um novo tratar o HTML que será usado na registro, etc.) e encaminhe a solicitação para resposta, separando a lógica de negócio da apresentação. um JSP, que fará o HTML para a resposta. Ele também separa a lógica de negócio da apresentação ... e já que ele andou lendo sobre desi~n, ele sabe que separar as preocupações é um Otimo Negócio. II declarações de import public class DatingServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { II a lógica de negócio entra aqui, II dependendo do que este servlet deve fazer II (escrever para o banco de dados, fazer a query, etc.) II envia a solicitação a uma página JSP específica II em vez de tentar exibir o HTML II junto com os dados de saída } «._'.• .- 1.··'.,'····· AcceptPrOfileChanlj.~~.sSe~lel InpulSignupJSP AcceplSignupJSP InputProfileChangesJSP AcceplProfileChangesJSP MainPageJSP InpulDQLJSP DoDQLQueJYJSP DoDQLQueryJSP / lJib ib "'''J) " O cllf!l';.f.efl"eel';ct.e ó lilI"IYoVI!J.I"I4J '4t1e~7 e c/tcl). 11t!J !I'4L bI:J.f:aõ õ I~ • ís.f.e el';vià tlIYo4 slJliél+ali" Hrrp POSrfal"4 a D"J)$L$vel"]. O sel"vtJ,,1" ",ell ct.alYofJ. f!I1CalYol;"t.aJ4 J-sP o.fN'prltJ.JlJ, O ,)-sp CtIJl1s+rfJta N:sffJl1se Hrl..-tLõliCt+fJ.j'iõ é fJ serv1e+; ó servle+ execv+a a y,tlerí 1';" btJ.l1ctIJ JfJ.Jós e f!11+'iõfJ. aõ ~e s e t.l Jev()/ve. 52 capitulo 2
  • 83. arquitetura de a/to nível Mas etrtão o seu aiMigo diz: "Você ESr Á usando MVC, certo?» Kim quer saber se o serviço de encontro pode ser acessado a partir de uma aplicação GUI Swing. Bob diz: "Não, eu não pensei nisso." Então, Kim fala: "Bem, isso não é problema porque eu estou certo de que você usou MVC, então nós podemos preparar num instante um cliente GUI Swing, que possa acessar as classes lógicas de negócio." Bob: "Glup." Kim: "Não me diga ... você não usou MVC?" Bob: "Bem, eu separei a apresentação da lógica de negócio ..." Kim: "Já é um começo ... ma~-níe adivinhar ... a lógica do seu negócio está toda dentro de servlets?!" Bob percebe, rapidamente, porque ele se tomou gerente. Porém, ele está determinado a fazer isto corretamente. Então, ele pede a Kim uma explicação bem rápida sobre MVC. Com o MVC a lógica de negócio não fica apenas separada da apresentação ... ela sequer sabe que EXISTE uma apresentação. A essência do MVC é que você pode separar a lógica de negócio da apresentação, mas ponha algo entre elas para que a lógica de negócio possa agir sozinha como uma classe Java reutilizável, sem precisar saber nada sobre a view. Bob estava quase lá, separando a lógica de negócio da apresentação, mas sua lógica ainda tem uma forte ligação com a view. Ou seja, ele misturou a lógica de negócio no servlet, o que significa que ele não poderá reutilizar sua lógica em outros tipos de view (como um GUI Swing ou até mesmo uma aplicação wireless). Sua lógica está presa em um servlet, quando deveria estar em uma classe Java stàndalone que ele pudesse reutilizar! você está 53
  • 84. o padrão de design MVC o Padrão de Projeto Model~View~ComrollerMVc) cot1serta isto ( Se Bob tivesse entendido o padrão de design MVC, ele saberia que a lógica de negócio não deveria estar inserida em um servlet. Ele teria percebido que com a lógica de negócio embutida o M9del*VleW*C9ntt91let no servlet, ele ficaria "em maus lençóis" caso algum dia tivesse que acessar o serviço de encontro (MVC) tet1tél él 1991célde neg9c19 de uma maneira diferente. Como na aplicação t9tél d9 set"let e él 09190élem GUI Swing. Nós falaremos mais sobre o MVC (e outros padrões) mais adiante, mas você precisa de um ~~M9de19" - umél éllrt'lgél um rápido entendimento agora, pois o tutorial que construímos no final deste capítulo usa o MVC. délSseJél"él, plqnél e teutJ'l1zá"e1. Se você já está familiarizado com ele, então você O lVl9de19 é él 09mblnélyã9 d9S ~ sabe que o MVC não é específico para servlets e JSPs - a clara separação da lógica de negócio da déld9S de neg9c19 (09m9 9 e5téld9 apresentação é igualmente válida para qualquer outro tipo de aplicação. Porém, com aplicações de um 0éltt1nb9 de 09mptéls) e web é realmente importante, porque você nunca 95 mét9d95 (tegtél5) 'Lue 9tetélm deveria considerar que sua lógica será acessada apenas da web! Estamos certos de que você nesses déld9S. trabalha neste negócio há tempo suficiente para saber que a única garantia em desenvolvimento de software é: a especijicação sempre muda. o MVC no mundo Servlet & JSP CONTROLADOR Retira da solicitação do usuário OS dados de entrada e interpreta o que eles significam para o modelo. Obriga o modelo a se atualizar e disponibiliza o estado do novo modelo para a view (o JSP). VIEW MODELO Responsável pela e o estadoverdadeira lógica Abriga a do modelo. Em apresentação. Ela outras palavras, ele conhece recebe o estado do modelo do as regras para obtenção e atualização do estado. Controlador (embora O conteúdo de um Carrinho de não diretamente; o Coml?ras (e as regras sobre o Controlador põe os que fazer com isso) seria parte dados do modelo em um Vlew qo Modelo no MVC. lugar onde a View possa E a única parte do sistema encontrá-Io). Também que se comunica com o é a parte que recebe banco de dados (embora ele os dados de entrada provavelmente use outro do usuário que volta ao objeto para a verdadeira Controlador. comunicação com o DB, mas guardaremos este padrão para mais tarde ...). 54 capítulo 2
  • 85. arquitetura de alto nível Aplicando o padrão MVC na aplicação de encontros Pois bem, Bob sabe o que precisa fazer. Separar a lógica de negócio dos servlets e criar urna classe Java normal para cada um ... para representar o Modelo. Com isso, o servlet legítimo será o Controlador, a nova classe para a lógica de negócio será o Modelo e o JSP será a View. 1111101 lGllCl lGUOJ. -0/ 10101MClllll 111101001l0>-0 '-''I1G100 010>-01 01010 1 1"101<1l i In~~;~::pModcl (~~Modm AcceplProfileChangesServlet DoDQIQueryServlel '-""~f1~ '"-~ InpulSignupJSP AcceplSignupJSP InputProfileChangesJSP ~ AcceplProfileChangesJSP MainPageJSP :. <'"_>_<ll> . """"'" </10»1, InpulDQLJSP -"-.-:'-. <'rI_,,",,"- _..... Ej,. ~= ••..._b";> ~ Ej~' 'J>ooo' (},,,,,, DoDQLQueryJSP -.::."?" "li"''''''''''' •... ;.1 você está 55
  • 86. sim, mas isso é um bom ? Neste tMotMemo, seu atMigo KitM dá utMa olhada Kim aparece e diz que embora esse SEJA um projeto MVC, ele é ruim. Claro, a lógica de negócio foi colocada em um Modelo, e os servlets atuam como Controladores trabalhando entre os Modelos e as Views, para que o Modelo possa be brain-dead about the Views2• Isso tudo é muito bom. Mas olhe para todos aqueles pequenos servlets. Que projeto mais fraco! Observe O que elesfazem mesmo? Agora que a lógica de negócio todos estes códigos duplicados em cada servlet. Você tem que está "guardada" com segurança no Modelo, o Controlador adicionar o mesmo código geral do servlet não está fazendo nada além de alguns trabalhos de aplicação, como segurança, na comuns para esta aplicação e, ah sim, ele atualiza o Modelo maioria dos servlets. e coloca a View para funcionar. Mas o pior é que toda aquela simples lógica de aplicação o o é repetida em cada um daqueles malditos servlets! Se algo requerer alteração, terá que ser alterado em todos os lugares. A manutenção de um trem destroçado está por vir. "Sim, eu não gostei muito deste código duplicado", diz Bob. "Mas o que mais eu posso fazer? Naturalmente, você não quer que eu ponha tudo em um simples servlet novamente? Como isso funcionaria?" 56
  • 87. de a/to nível Existe utMa resposta? Será que o Bob dev ria volta para apenas um Controlador de servlet para evitar código duplicado? Isso seria um modelo 00 ruim, pois os servlets estão realmente fazendo coisas diferentes? O Keanu Reeves luta mesmo Kung Fu? D o EXERCITE SUA MENTE Deixe isto para você meditar. É o que nós vamos fazer. O que você acha? Você sabe a resposta? EXISTE uma resposta? Você concordaria com Bob e deixaria os servlets como eles são, ou colocaria o código dentro de um único Controlador de servlet? E se você usar mesmo apenas um Controlador para tudo, como ele saberá qual Modelo e View chamar? A resposta para esta pergunta não virá antes do final deste livro, então pense nisso por alguns momentos e depois coloque numa thread em background na sua mente ... você está aqui... 57
  • 88. capítulo 2 - reflexão • Usando o MVC no mundo servlet & JSP, cada um destes três componentes (JSP, classe Java e Servlet) desempenha um papel MVC. Circule "M", "V" ou "C", dependendo de qual parte do MVC o componente executa. Circule apenas uma letra por componente. M O Container oferece à sua aplicação web V suporte em comunicações, gerenciamento do ciclo de vida, suporte a multithread, C segurança declarada e suporte para JSPs, para que você possa se concentrar em sua J'SP própria lógica de negócio. O Container cria um objeto request M e response que os servlets (e outras V partes da aplicação) podem usar para conseguir informações sobre a request e C enviar dados ao cliente. non-servlet Um servlet típico é uma classe que J'ava c1ass estende o HttpServlet e sobrepõe um ou mais métodos de serviço que correspondem aos métodos HTTP M ativados pelo browser (doGetO, V doPostO, etc.). C O distribuidor pode mapear uma classe de servlet servlet para uma URL, que o cliente pode usar para solicitar tal servlet. O nome pode ser completamente diferente do verdadeiro nome do arquivo da classe. 8 O que as letras MVC representam design MVC? no padrão de M significa _ V significa _ C significa _ 58 capítulo 2
  • 89. arquitetura de alto nível Ap9nte seu lápis Quem é o responsável? Preencha a tabela abaixo, indicando se é o servidor, o container ou um servlet o mais responsável pela tarefa listada. Em alguns casos, mais de uma opção pode ser verdadeira para a tarefa especificada. Para justificar, acrescente um breve comentário descrevendo o processo. Tarefa Servidor Container Servlet dinâmicos HTTP response objetos request e no DD elemento <servlet-class> response solicitações Cria os Converte HTTP no de vida Gerencia umciclos DD conteúdos uma Encontra URLs objeto response em Conhece onova tbread Tem uma os preparo para o com Iniciaum nome que coincide objeto oas Coordena referência de para tratar uma Acrescenta objetos serviceOe response Apaga os método requestobjeto response Chama o o HTML ao você está aqui li> 59
  • 90. servlet e exercício DD Ímãs de G-ela-del'téL Um servlet funcionando e o seu DD são misturados em uma frigideira. Você é capaz de unir os pedaços de código recortados à direita com a listagem incompleta à esquerda, a fim de criar um servlet e um DD que funcionem e cuja URL termine com /Dice? É possível que alguns códigos à direita não sejam usados! - Servlet public class extends HttpServlet { public void doGet( throws IOException { String dI Integer.toString((int) ((Math.random()*6)+I»; String d2 Integer.toString( (int) ((Math.random() *6) +1»; out.println("<html> <body>" + "<hl align=center>HF's Chap 2 Dice Rol1er</hl>" + "<p>" + dI + " and " + d2 + " were rolled" + "</body> </html>"); -DD teS+-4 #'/';6 é 4 +-~de det'+-vt'fI. <web-app () f!;cf!iIP<pic c<!IlJY>le+-ô ftI1Cc#'/+-Nr se #,/c flplfJ.1 IS+(j #'/';tJ fJ.fe+a (; e;cet'c:C/~). </web-app> 60 capítulo 2
  • 91. arquitetura de alto nível import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public void service( </url-pattern> <servlet-name> ServletRequest requeSt' PrintWriter out response.getWriter(); HttpServletResponse response) <servlet-mapping> ServletResponse response, <servlet-name> </servlet-class> HttpServletRequest request, PrintWriter out request.getWriter() ; </servlet-name> <url-pattern> </servlet> <servlet-c1 </servlet-mapping> você está aqui ~ 61
  • 92. Responsabilidade - solução do exercícío Tarefa Servidor web Container Servlet classe uma encaminhar ao thread antesservlet Logo parachama o partir quem responsedos a Inicia que ao asservlet de Usa-o aumaservlet. Sabe de)correto service( falar é finalizado.você eto exibir pública qualquer coisa Quando (eHTTP do entrega outros o service cliente. dinâmico para o chamarstream de Usa-o para servlet. browser cliente. a ) ) ou Container. para o request. o com iniciar O Container response. gera encontrar o doGet( objetos doPost( Cria método response Para aos othread. request e response O conteúdo Aí o Chama método 62 capítulo 2
  • 93. arquitetura de alto nível C9nt1nuac;ã9da S91uc;ã9 d9s Exel'cÍc9S... - Servlet irnport javax.servlet.*; irnport javax.servlet.http.*; irnport java.io.*; public class xtends HttpServlet HttpServletRequest HttpServletResponse PrintWriter out String dI Integer.toString((int) ((Math.randorn()*6)+I»); String d2 Integer.toString((int) ((Math.randorn()*6)+I»); out.println("<htrnl> <body>" + "<hI align=center>HF's Chap 2 Dice Roller</hl>" + "<p>" + dI + " and " + d2 + " were rolled" + "</body> </htrnl>"); -DD------------------- </servlet-narne> /url-pattern> você está aqui ~ 63
  • 94. Dois objetos, dois blocos Ul1 PeploYl1ettt Pescriptor (PP) "funcionando» Não se preocupe com o que isto realmente significa (você verá isto em outros capítulos e fará testes). Aqui, nós quisemos apenas demonstrar um DD web.xml que funciona de verdade. Ficaram faltando muitos pedaços a serem ínseridos na tag de abertura <web- app> nos outros exemplos deste capítulo. (Você pode perceber porque nós geralmente não íncluímos isso em nossos exemplos.) A forma que geralmente mostramos no livro <web-app ... > <servlet> < <servlet-name>Ch3 Beer</servlet-name> <servlet-class>com.example.web.BeerSelect</servlet-class> </servlet> <servlet-mapping> <servlet-name>Ch3 Beer</servlet-name> <url-pattern>/SelectBeer.do</url-pattern> </servlet-mapping> </web-app> A forma que REALMENTE funciona L <web-app xmlns=''http://java.sun.com/xml/ns/j2ee'' xmlns:xsi~''http://www.w3.org/2001/XMLSchema-instance'' xsi:schemaLocation~''http://java.sun.com/xml/ns/j2ee/web-app 2 4.xsd" version="2.4rT> <servlet> <servlet-name>Ch3 Beer</servlet-n~me> <servlet-class>com.example.web.BeerSelect</servlet-class> </servlet> <servlet-mapping> <servlet-name>Ch3 Beer</servlet-name> <url-pattern>/SelectBeer.do</url-pattern> </servlet-mapping> </web-app> 64 2
  • 95. arquitetura de a/to nível Cot10 o J!EE cabe "isso tudo Um set"Id9t de aplIcac;ã9 O Java 2 Enterprise Edition é meio um "superspec" - ele incorpora outras especificações, incluindo a J2EE IncluI tant9 9 C9ntmnet é para o Web Container.2.4 e a especificação JSPJ2EE Isto especificação Servlets Porém, a especificação 2.0. 1.4 Web7 C9m9 9 C9ntain et EJB. 1 " também inclui a especificação Enterprise JavaBean 2.1 para o Container EJB. Em outras palavras, o Container O ]9'mcat é um C9ntmnet web é para EJB é para componentes de negócios.e o Container componentes web (Servlets e JSPs) Web7 mas N11.0 um set"Id9t A Um servidor ter aplicação Contalller web, como um o J2EE deve de tanto um tota~ente compatível com de apllcadi9 J2EE c9mplet9. T Contai~er EJB (alé~ de outras coisas, c?mo uma JNDI e uma lmplementaçao JMS). O Tomcat e apenas um Um set"Id9t J2EE 1.4 IncluI especIflcaçao J2EE que se referem acordo às :porções da Cont~iner -:eb! Embora esteja de ao Contamer web. a especltlcadi9 Set"let T 2.4 7 O Tomcat é um Container web e não uma aplicação a especltlcac;ã9 JSf 2. o e a J2EE completa, pois ele não possui um Container EJB. especltlcac;ã.9 ElB 2.1. iJ2EE Application Server r: Então o Tomcat é um Container web standalone ... isso significa que o Resin. Geralmente, os Containeres web standalone são configurados para também existem Containeres EJB trabalharem com um servidor HTTP (como o standalone? Apache), embora o Container Tomcat possa atuar como um servidor HTTP básico. Mas, para a função de servidor HTTP, o Tomcat nem se aproxima da robustez do Apache. 1: Antigamente, digamos, no ano Por isso, as aplicações web não-EJB 2000, você encontrava servidores J2EE mais comuns usam o Apache e o Tomcat completos, Containeres web standalone e configurados juntos - com o Apache como Containeres EJB standalone. Hoje, porém, Servidor HTTP e o Tomcat como Container. quase que todos os Containeres EJB Alguns dos servidores J2EE mais comuns são parte de servidores J2EE completos, são o Weblogic da BEA, o JBoss AS de embora existam ainda poucos Containeres código aberto e o WebSphere da IBM. web standalone, incluindo o Tomcat e você está aqui ~ 65
  • 96. Minitutorial do MVC Criando e distribuindo uma aplicação Web MVC. Chegou a hora de colocar a mão na massa e escrever um formulário HTML, um controlador de servlet, um modelo (classe Java simples), um deployment descriptor XML e uma view em JSP. É hora de criar, distribuir e testar. Antes, porém, você deverá configurar seu ambiente de desenvolvimento - uma estrutura de diretórios para o projeto que esteja separado da sua aplicação real distribuída. Em seguida, você terá que configurar o seu ambiente de distribuição, de acordo com as especificações do servlet e do JSP, e as exigências do Tomcat. A partir daí, você estará apto a começar a escrever, compilar, distribuir e executar. Concordo, construímos uma aplicação bem pequena. Porém, quase NÃO existe aplicação que seja tão pequena e use o MVC. Afinal, a aplicação pequena de hoje é o sucesso da internet de amanhã ... este é um novo capítulo. õl
  • 97. objetivos do exame oficial da Sun o Distribuição Aplicação Web Notas sobre a Abrangência: 2.1 Construir a estrutura de arquivo e diretórios de Todos os objetivos nesta seção são abordados uma aplicação que possa conter (a) conteúdo completamente no capítulo sobre Distribuição; estático, (b) páginas JSP, (c) classes servlet, aqui daremos apenas uma primeira olhada. Este (d) o deployment descriptor, (e) bibliotecas de é o único capítulo com um tutorial completo, do início ao fim. Portanto, se você pulá-Io, poderá tags, (f) arquivos JAR e (g) arquivos de classe ter problemas mais tarde, quando for testar Java. Descrever como proteger os arquivos de alguns outros exemplos nos próximos capítulos recursos do acesso HTTP. (não repetiremos cada detalhe novamente). 2.2 Descrever o propósito e a semântica de cada Assim como nos anteriores, você não precisará um dos seguintes elementos do deployment se preocupar em memorizar o conteúdo deste descriptor: error-page, init-param, mirne- capítulo. Apenas vá e faça. mapping, servlet, servlet-class, servlet- mapping, servlet-name e welcome-file. 2.3 Construir a estrutura correta para cada um dos seguintes elementos do deployment descriptor: error-page, init-param, mime- mapping, servlet, servlet-class, servlet-name e welcome-file. 68 capítulo 3
  • 98. praticando com o MVC Vattos cot1struir utta (pequetW aplicação de verdade Nós vimos a função de um container, falamos um pouco sobre deployment descriptors e demos uma primeira olhada na arquitetura do MVC Model 2. Mas você não po.de ficar aí sentado e lendo o dia todo - agora é hora de realmente jazermos alguma coisa. Os quatro passos que seguiremos: O Revisar as views doe usuário (o quedeo browser mostrará) a arquitetura alto nível. 8 Criar o ambiente de desenvolvimento que usaremos neste projeto (que você poderá usar para qualquer outro exemplo no livro). Gl e Criar o ambiente de distribuição que usaremos neste projeto (que você poderá usar para qualquer outro exemplo no livro). i~~ f~ _~ _~ --...01_ ~ o Desenvolver e testar repetidas vezes os vários componentes de nossa aplicação. (Tudo bem, isto é mais uma estratégia do que um passo.) Nota: Nós recomendamos desenvolvimentos e testes repetitivos, embora nem sempre mostraremos todos os passos aqui. você está aqui ~ 69
  • 99. A view do usuário A View do Usuário para a aplicação "&eer Advisor" (Especialista eltt Cervejas) Nossa aplicação será uma esp~cialista em cervejas. Os usuários poderão navegar em nossa aplicação, responder perguntas e receber conselhos valiosÍssimos sobre cervejas. ~ . ~ t~ HrM.l_ eser: z.s.f-a p~tP1a ti": Beer Seleetion Page N!.spós.f-a eJ?vi'o,PldlJ CIJ~" Select ooer characteristics ClJir ~lIe <) lISllfJ.I'i'(> Color: {light .; j ís.f-a lI~a IJ clJPlselt.ó C(l~ base PIo. I ~ dI) lISlIfJ.l'i6. Beer Recommendations JSP try: Jack's Pale Ale try: Gout Stout f: Por que estamos criando uma aplicação que dá conselhos sobre cervejas? 1: Depois de uma exaustiva pesquisa de mercado, concluímos que 90% dos nossos leitores apreciam cerveja. Para os outros 10%, basta simplesmente substituir a palavra "cerveja" por "café". 70 capitulo 3
  • 100. praticando com o MVC Aqui está a arquitetura ... Ainda que esta seja uma aplicação bem pequena, vamos construÍ-la usando uma arquitetura MVC simples. Desta forma, quando ela se tomar O SITE mais badalado da web, estaremos prontos para aumentá-la. Container 1 - O cliente solicita a página jorm.html. -~ servlet C(J;r/-l'cladcl" 2 - O Container vai buscar a páginajorm.html. 3 - O Container retoma a página ao browser, o usuário responde às perguntas do formulário e... A-pe"llJ.s tllJ'I componente D/J Java tJldec.f. BeerExpert JavlJ, sllty.>les). 4 - O browser envia os dados da solicitação ao container. Container 5 - O Container encontra o servlet correto baseado na URL e passa a solicitação para o servlet. 6 - O servlet pede ajuda ao BeerExpert. 7 - A classe responsável retoma uma resposta, a componente qual o servlet adiciona ao solicitação BeerExpert objeto solicitação. 8 - O servlet encaminha a solicitação ao JSP. 9 - O JSP recebe a resposta do objeto solicitação. 10 - O JSP gera uma página para o Container. 11 - O Container retoma a página para o usuário feliz. você está 71
  • 101. ambiente de desenvolvimento Criat'ldo O seu attbiettte de deset1volvittettto Existem várias formas de você organizar a sua estrutura de diretórios de desenvolvimento, mas esta é a que recomendamos para projetos de pequeno e médio portes. Na hora de distribuir a aplicação, copiaremos uma porção disso para onde quer que o nosso Container específico queira. (Neste tutorial, usaremos o Tomcat 5.) ru "" .- pl"eclstI. I,.v"ce 410.6 Jes-fe Jll"e-!-:1"16 ---7 Sevs CtrJl'I1flJl1t:l1ffS Vrf!W es-!-:-I-rctrJs e pal"tI. 6 -!-V-!-61"I"o.I) ...•.. JinlA",i(;ós fleal?! a~tlr. j li. í .... rr~vi' V6Ce có161:f1. 6S (U'3V1'vtrJSJA-Je Je -hI"CfiÍ"óS (J" result.jsp form.html Sfl"vle-!-rJe-vs). J' T r í a~vr Sve fica Sf!V f..XfI'l1fItJS Je fI.;vns Je C4I1fijvl'o"';ó. C6l'11flJnel1-H::Svtew. BeerSelect.java BeerExperLjava BeerSeleel.elass BeerExperLelass F i. duó ave eS-!-lAl?!as tlSfl.I1Jó a ~j JeepfJ.I"e~ve Sf!PD.I'D."'l'JSóS CIJ"'fIJI?f!I?+es d" eS-!-l"v-!-vI"o.-po.Jl"ãa pal"a ó Pfl.C6+e; clJl?-!-I""'adal" ell'JS c""'fIJI1f!I?+es dó "'t>Jel. pal"tI. ~ve pós StI."'óS ób+el" óS I benef,cl6s 41ól"h'iIU'"s elele: - óI"5anl";4,';a el" pl"~e-l-6 "7 5eN!l?crD."'f!I1.f.ó ela 1?D.",espD.ce p61"-!-d"'Maele e I"f!lI-hlt";ajãó 72 capitulo 3
  • 102. praticando com o MVC Criat1do O atMbiettte de distribui~o !s+e é ti dlÍ"d:l"itJ t.(JIr<f Distribuir uma aplicação envolve seguir regras específicas dtl t;Ir<Cfi.~ do Container e requerimentos das especificações dos +el" siiJó cI:'a.Ir<adóde Servlets e JSPs (se você não está usando o Tomcat, terá que descobrir onde exatamente a sua aplicação ligar-se-á ao seu Container). No nosso exemplo, tudo abaixo do diretório +"Ir<ca-l- S-.O. "Beer -vI" é igual, independentemente do seu Container! (dllel"f~J 'Ís+a da Específico para o Tomcat es+I"I.I+vI"{J, lIle dlÍ"e-r,fjl"itJs e 1/ / ís+e l1ólr<f!de di'l'e+:l"iiJ +aJi'lbélr<l"epl'f!:se~a <:l pe!tJ e If J // / es+al' C6J'if"'eX+ I"Mi alie ó 1;;Ir<ca+ lisa 1JlIfU1tlfJ eS+a l"esIJlvfl1dõ fJJt.Ls. AJ:s exp!(Jl'ttl"f.Ir<(Js es+e c4I1ce4"(J daixIJ lIla set/ tlll"ef-:f'ltJ t.(J~e, telr<Ji'lQltJl"esJe+alt,es '14 cap:+lIla sobl"e PiS+l"l!llll{ã(J. ~ 1;;Jó A-8A-I>j.o des+a hi1t.tJ. p(ji1+lIt.aJn. í. a o.pliélJ.{ãó; 3ve seI': tJ.Ir<es~a; li1tlepe'1Je'1+e~ei1+e Jó Idl"ií::tJ.J1+e tllJ sell CIJW/-QIi1fl", result.jsp Parte da af'ôVlvt'J especificação ~ wd.xIr<1 es+1J.1"e~ ríM. dos Servlets </webapp> web.xml wU;-IAlF ~ A- es.fl'v+vl"tJ. tles+e pt4có+e é exa.faJi'lt!I1+e a VStJ.Ji'l6S116 fJ.Ji'I!Ji'el1+e tlt!Sfl1l1d!Vllr<fl1+ó. tle A- Específico da Aplicação Ir<el1"s 3ve tllS+l"l!JVIi1tlt> SVtJ.ScltJ.sses f.Ir< Vir< (h,ItJ.l"eJi'llJs t:l +tJ.l"tle)J de es.fl"v.fvl'{J, llr<eJi'a.ffi.Ir<e~ 0010 00 IAlFlda.sses. 100 1001 0001 0011 0101 0110 BeerSelectclass BeerExpert.class você está 73
  • 103. construindo aplicação Mapa para a COttstrução da aplicação Quando iniciamos este capítulo, definimos um processo de quatro etapas para desenvolvermos nossa aplicação. Até agora nós já: 1- Revisamos as views do usuário para nossa aplicação. 2- Vimos a arquitetura. 3- Criamos os ambientes de desenvolvimento e distribuição para montar e distribuir a aplicação. Agora é a vez da etapa 4: criar a aplicação. Nós tiramos isso de várias metodologias conhecidas de desenvolvimento (muita programação e incansáveis repetições) e adequamos aos nossos propósitos malignos ... Os cittco passos que seguireiMos (ttOpasso 4): ~ Construir e testar o formulário HTML que o usuário irá solicitar primeiro. $Construir e testar a versão 1 do servlet controlado r com o formulário HTML. Esta versão é invocada via formulário HTML e exibe o parâmetro que ela recebe. $ Construir uma classe teste para a classe modelo/expert, além de construir e testar a classe modelo/expert em si. $Atualizar o servlet para a versão 2. Esta versão nos dá a capacidade de chamar a classe modelo a fim de obter os conselhos sobre cervejas. ~ Construir o JSP e atualizar o servlet para a versão 3 (que agrega a capacidade de entregar para o JSP), e testar toda a aplicação. 74 3
  • 104. praticando com o MVC o HfML do forntulário da página inicial o HTML é simples - ele coloca o cabeçalho, a lista drop- down de onde o usuário seleciona uma cor para a cerveja e o botão Submit. <html><body> <hl align=Hcenter">Beer Selection Page</hl> <form method="POST" ~ Ar 3ve escljlt.eJr;ljsposre"", vej P/e action~"SelectBeer.do"> ~ Select beer characte:rístics<P>"- OfirMI- pe#'lsa 3ve c servle+ -h"", es-h #'Ic~e. Calor: AJ';1j"': AJltblt #'Iasva es-!-rv+vra P/eJtre+:rlcs <select name="colo:r" size="l "> c"'a"",aJIj5elec+8eer.P/(J/ Is+" . ~ v"'"#'I{)~e 1:5lclJ ••• <option <optíon value="amber"> value="líght"> amber líght </option> </oPtion» <option value="brown"> brown </ oPtion>? hl asstltl, 3ve crto.""'(Js "",e#'lvvll- Q p <option value="dark"> dark </option> JMIl/#'IltI,assvas "pg';esfcJell'l varl"4l'. </select> <br><br> / ..,J L I / ~/ 7 (4ce e#'l~#'I"ev (J sl-t.e= I .) <center> <input type~"SUBMIT"> </center> </form></body></html> r: Por que o formulário está enviando para "SelectBeer.do" se não há NENHUM servlet com esse nome? Nas estruturas de diretórios que vimos anteriormente, não havia nada com o nome "SelectBeer.do". E o que significa a extensão" .do" afinal? 1: SelectBeer.do é um nome lógico, não um nome de arquivo de verdade. É simplesmente o nome que queremos que o cliente use! Aliás, o cliente JAMAIS terá acesso direto ao arquivo de classe servlet. Portanto, você não cria, por exemplo, uma página HTML com um link ou ação que inclua um caminho para um arquivo de classe servlet. O truque é, nós usaremos o Deployment Descriptor XML (web.xml) para mapear o que o cliente requisita ("SelectBeer.do"), para um arquivo real de classe servlet que o Container usará quando entrar uma solicitação "SelectBeer.do". Por enquanto, considere a extensão ".do" como uma simples parte do nome lógico (e não um tipo de arquivo mesmo). Mais adiante, você aprenderá outras maneiras de usar as extensões (reais ou fictícias/lógicas) em seus mapeamentos de servlet. você está 75
  • 105. distribuindo e testando l1istribuit1do e testat1do a págit1a it1icial Para testá"la, você precisa distribuí-Ia na estrutura de diretórios do Container (Tomcat), iniciar o Tomcat e acessar a página em um browser. 8 Crie o HTML no seu ambiente de desenvolvimento Crie este arquivo HTML, chame-o deform.html e salve-o em seu ambiente de desenvolvimento, sob o diretório /beerVl/webl. o Copie o arquivo para o ambiente de distribuição webapps/Beer-vll. (Lembre-se, o diretório em tomeat/ Coloque uma cópia do arquivoform.html home do ~ ~ ~ seu tomcat pode ter um nome diferente). form.html e Crie o DO em seu ambiente de desenvolvimento Crie este documento XML, nomeie-o de web.xml e salve-o em seu ambiente de desenvolvimento, sob o diretório /beerVl/etc/. LI.••• ,.., V6ce"tu" precisa Ct!JI1t.ecer <web-app xmlns~''http://java.sun.com/xml/ns/j2ee''lJ(' ~ l1o.d4diSS,,; apel1{).s xmlns:xsi=''http://www.w3.org/2001/XMLSchema~instance'' xsi:schemaLocation=''http://java.sun.com/xml/ns/j2ee/web~app 2 4.xsd" version="2.4fl> I j I .••• I e li" 'U:J~e:lteru::"" ~ve Y<:Ice vsara '<servlet> e~ "v+ras f'ar+es d" '<servlet~name>Ch Beer</servlet-name> '<servlet~class>c .example.web.BeerSelect</servlet-class> </servlet> ~ AJ,,~e+(••fa/~el1+e <servlet-mapping> ar3vry" de classe servle.f. <servlet-name>Ch3 Beer</servlet-name> '<url-pattern>/SelectBeer.do</url-pattern> </servlet-mapPing~~f: " I;. : fJ.S 3ve "tlf!N!~II'JS 3ve " clre,,~L se si'~ I N U I ,.., </web-app> AJ'i1l'Je es~vesa servler. s f) .da e apel1fJ.s V~IJ. C611I1el1jfJ.IJ. de c,,~egtlr CIJII'I Vll'ltl barro.. 76 capitulo 3
  • 106. praticando com o fV1VC A principal função deste DD é definir o mapeamento entre o nome lógico que o cliente usa na solicitação ("SelectBeer.do") e o arquivo de classe servlet verdadeiro (com.example.web.BeerSelect). o Copie o arquivo para o ambiente de distribuição Coloque uma cópia do arquivo web.xrnI em torneat/ webapps/Beer- v IIWEB-INFI. Você DEVE colocá-Io aí para que o Container o encontre; do contrário, nada funcionará, e você ficará deprimido. web.xml e Inicialize o Tomcat Estamos usando ao longo do livro o Torncat tanto como Servidor, quanto como Container. No mundo real, você provavelmente usará um web server mais robusto (como o Apache) configurado com um Container (como o Tomcat). Mas o Tomcat é um servidor perfeitamente decente para tudo o que precisamos neste livro. Para iniciar o Tomcat, vá para o diretório home do tomcat e execute o bin/startup.sh. o Teste a página Abra a página HTML no seu browser e digite: http://localhost: 8080/Beer-v 1/ fOfill.htrnl. Você deverá ver algo parecido com esta tela. Beer Seleetion Page Seleet beer eharaeteristics Color. f light i~l vocÊ~está 77
  • 107. mapeando o servlet POST IBeer-VllSelectBeer.do HTTP/1.1 Host WV.rw.wickedlysmart.com User-Agent Mozilla60 (MaCintosh- U' :CMaCOSXMaCh-o;en_US;rV;l.~) , ck0/20030624 NetscapeJ7. J Accept telCt/xml,application! xmr,application/xhnnl+xml,text/ htmJ~O.9,text/Plain;q""0.8,video!x_ ~ng,image/png,imageljpeg,jmijge/ grf;q:oO.2//';Q"'Ü.l Cliente e o Container procura o DD e encontra um <servlet- mapping> com um <url- pattern>, que coincide com <web-apP> <serv1et> o /SelectBeer.do, onde a <servlet-name> Ch3 Beer barra (I) representa a raiz </servlet-name> do contexto da aplicação e <servlet-class> b Beerse~ect o SelectBeer.do é o nome COIfL.examP1e.we . </servlet-class> lógico de um recurso. </servlet> <servlet-mapping> <serV let _name> Ch3 Beer eo </servlet-name> <url-pattern> Container vê que o ISelectBeer.do </url-pattern> <servlet-name> para esta </servlet-mapping> <url-pattern> é "Ch3 Beer". </web-app> Mas este não é o nome verdadeiro de um arquivo de classe servlet. "Ch3 Beer" é o nome de um servlet, e não de uma classe de servlet. Para o Container, servlet é Container aquilo que foi definido no DD, abaixo da tag <servlet>. O nome do servlet é simplesmente o nome usado no DD, para que as outras partes do DD possam mapeá-Io. 78 capítulo 3
  • 108. praticando com o MVC oo Container procura dentro das tags <servlet> a tag <servlet-name> "Ch3 Beer". Container <servlet-mapping> o O Container usa a <servlet- c1ass> da tag <servlet> <serv1et- Ch3 Bee <íservlet-name> <url-pattern> IselectBeer.dO para descobrir que classe </url-patter~> servlet é responsável por </servlet-mapplng> </web-app> tratar esta solicitação. Se o servlet não tiver sido inicializado, a classe é carregada e o servlet é inicializado. o O Container inicia uma nova thread para tratar a solicitação, e passar a solicitação para a thread (para o método serviceO do servlet). resposta o O Container envia a resposta (através servidor, claro) de volta ao cliente. do Cliente Container você esta 79
  • 109. primeira versão do controíador senríet A pritMeiraversão do cotttrolador servlet Nosso plano é construir o servlet em etapas, testando os vários links de comunicação, conforme avançamos. No final, lembre-se, o servlet aceitará um parâmetro que venha da solicitação, invocará um método no modelo, salvará a informação em um lugar que o JSP possa encontrá-Ia e encaminhará a solicitação ao JSP. Mas para esta primeira versão, nosso objetivo é apenas garantir que a página HTML possa chamar adequadamente o servlet e que o servlet esteja recebendo o parâmetro HTML da forma correta. ~S~IA cer'+" de ~ue você US6UlU Itl.f!:SIYlfJ.S Código do servlet es+ru+uri1.s de df!sf!I1vcllll#i-.f!I1+t:> f! package com.example.web; ~• / dts+l"i!JGI/"{ãó~Uf! crl"aItl.CSal1+el"fórltl.e,,+e. r import javax.servlet.*; tJ H#p:5erIl1e+ es+e"de " import javax.servlet.http.*; bel1eriCSerll1e-lj óGleIWtpleltl.el1+a import java.io.*; IAIYt.ferlace dó Serllle+ ••• public class BeerSelect extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException response. setContentType ("text/html"); J::::- 'l.s.fe Itl.é+ódó PrintWriter out = response.getWriter(); Vf!ltl.dIA out .println ("Beer Selection Advice<br>") ; :5erIl1e+Je,!!sp"""Sf!.. out.println("<br>Got String c ~ request.getParameter("COIOr");~ beer color " + c); , ~ - ~) ~S+e ltl.é+cd6 lIeltl. da Ii?.ferlace li S&lr'fltl.tfJS Jc.R.s+ pal"&l ó f!.S.f-&lItl.If)S :5erv1e+Jeeóvf!s+. +rlA+ar IAsali'ct+a{ic Hrr~ "el1t.vlYl Jeepar'f ôve IJ 1'61$ ó fCl"ltl.vl:r'lÍJ tfntA.L. IIIl"j= ar5vltl.e"+1J clJli?cide c<:)1tl. ltl.e+t,ólll=PtJ:5r vll.l"r' <:) 1l.+I"I"'!JV+t:> /I I1ll.ltl.e "14 <selec+> dtfJ APls itMportantes 80
  • 110. praticando com o MVC COlMpilando, istribuindo e testando o cotttrolador servlet d Perfeito! Nós construímos, distribuímos e testamos nosso HTML, e construímos e distribuímos nosso DD (bem, colocamos o web. xml no ambiente de distribuição, mas tecnicamente o DD não será distribuído até reiniciarmos o Tomcat). Agora é hora de compilar a primeira versão do servlet, distribuÍ-I o e testá-Io via formulário HTML. Vamos reiniciar o Tomcat para garantir que ele "enxergue" o web.xml e a classe servlet. Compilando o servlet Compile o servlet usando -d para colocar a classe no ambiente de desenvolvimento. / CCl1liJvre ts.f." faro. ttle cÓIÍ1ctJa C<:l~ I) c4~1Í1t.1) de dtre.f.JU"I't!S #16 setl I / 1'1 Sl"s.f.e*lti.. 1;;d6 IJf>)'S .f.ólt'oca.f. I 1" sei"a iJVo.l. / I n .•..•.lJ se'; 4f'fã6 -ç{ fai"Q. lÍ1-/fJi"I't'iI'U"ti,) CÓl!P>fllo.dói" l'J.i"4 (;lJlfJcal" p (J se tl fM.f.ó e IIIt'jula ; li 1J.i"~1I1"v(J ,das 05 PlIJ ç{tre.f.:i"I't! de c/(J;sses; de#1.f."tJi ç{a l1ó SI"s-l-i!""tJ.Ófel"IJ.CI't!I?I'J.! ts.f.rv.f.vi"IJ. CÓi"l"e.f.1J. flJ.cóff. ç{1/} Setl at'~vlvQ ,c/ass vai' WIÍ1ç{óWS acabai" e"'" IbeerV IlclQ.sstslcfJl't'ilelfal!P>f1el webl. Distribuindo o servlet Para distribuir o servlet, faça uma cópia do arquivo .class e mova-o para o diretório /Beer-vlIWEB-INF/dasses/comlexample/web/ na estrutura de distribuição. Testando o servlet FI Ed" Wid Hl SI hdtM % cd tomcat I - Reinicie o tomcat! % bin/shutdown.sh % bin/startup.sh 2 - Abra seu browser e digite: http:// localhost: 8080/Beer -vI /form.htrnl http://localhost:8080 3 - Selecione uma cor de cerveja e dique em "Submit" Beer Seleetion Page Sckct bcen;l1arncterisocs 4 - Se o seu servlet estiver funcionando, Color::ug~ você deverá ver no browser a resposta do servlet parecida com: Conselhos sobre Escolha de Cerveja Você escolheu a cerveja marrom você está 81
  • 111. classe modelo Cot1struit1do e testat1do a classe tModelo No MVC, o modelo tende a ser o "back-end" da aplicação. Em geral, é o sistema tradicional que está sendo exposto na web atualmente. Em muitos casos ele é apenas um código Java simples, sem saber que talvez possa ser chamado pelos servlets. O modelo não deve ficar restrito a ser usado por somente uma única aplicação, portanto ele deve ficar dentro dos seus próprios pacotes de utilidades. As especificações para o modelo Seu pacote deve ser com.example.model Sua estrutura de diretórios deve ser /WEB-INF/c1asses/com/example/model Ela disponibiliza um método, getBrandsO, que obtém uma cor preferida (como um String) e retoma uma ArrayList de marcas de cervejas recomendadas (também como Strings). Construa a classe de testes para o modelo Crie a classe de testes para o modelo (sim, antes de construir o modelo em si). Aqui, você está por sua própria conta, pois não temos uma neste tutorial. Lembre-se, o modelo ainda estará no ambiente de desenvolvimento quando você testá-Io pela primeira vez - é como outra classe Java qualquer, e você pode testá-Io sem o Tomcat. Construa e teste o modelo Os modelos podem ser extremamente complicados. Eles freqüentemente envolvem conexões com bancos de dados tradicionais e chamadas a lógicas complexas. Aqui está nosso sofisticado e inteligente sistema baseado em regras que dá conselhos sobre cerveja: package com.example.model; import java.util.*; public class BeerExpert { public List getBrands(String color) List brands = new ArrayList(); if (color.equals ("amber")) { brands.add("Jack Amber"); C4i1'1él Cap+VI'Il."'4S as ,;;ftU·"'tl.gDes brands.add("Red Moose"); especi'Q!"~flI.dtl.s e clJ"'P1l!xas dlJ l!Xl!"'P!1J da cel'v~4.J } else { vSIJ.'IdlJ expl'es sDes ct:J'Idi'ci'IJ'Iais alla'lsadfl.s. brands.add("Jail Pale Ale"); brands.add("Gout Stout") ; } return(brands); % cd beerVl % java -d classes src/com/example/model/BeerExpert.java 82 3
  • 112. praticando com o fvlVC Melhorando o servlet para chatMar o tModelo,para obtertMos conselhos VEVE~VAVE... Nesta segunda versão do servlet, iremos melhorar o método doPostO para chamar o modelo para oferecer o conselho (a versão três fará com que o conselho venha de um JSP). As alterações de código são triviais, mas a parte importante é entender a redistribuição da aplicação melhorada. Você pode tentar escrever o código, recompilar e distribuir por sua própria conta, ou então virar a página e seguir adiante ... AP9nte seu lápIS Melhorando o servlet, versão dois Esqueça os servlets por um minuto, vamos pensar apenas em Java. Quais são os passos que devemos tomar para realizar estas tarefas? 1. Melhorar o método doPostO para chamar o modelo. 2. Compilar o servlet. 3. Distribuir e testar a aplicação atualizada. você está 83
  • 113. chamando o modelo para o controlador servlet o código do servlet versão dois Lembre-se, o modelo é apenas Java simples, então o chamaremos como faríamos para qualquer outro método Java: instanciar a classe modelo e chamar o seu método! package com. example. web; AJãô se eS3f1esa «lJ i"Y>tJt''';'' parti. tJ PQCô..fe lJI'lille " import import com. example .model. *; javax.servlet.*; V- 8eerl.xper";" es";": l'P7seri(Jl). import javax.servlet.http.*; import java.util.*;. J Ct'IfJ.I1"lJ ulI';a I1"V4 cltJ.sse. import java .io. * ; / íS.ffJ.IMS 1I';1IJ"i'Ii'ct/,l'UJlJ servle";" (J ôrij/'P7al e l1ã" public class BeerSelect extends HttpServlet ( public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException String c = request.getParameter("color"); List result be be.getBrands(c); BeerExpert = = new BeerExpert();~ ~ II1S";"fJ.l1clfJ.1' 4 classe 8eet'1..J(fel''';'' fi! response.setContentType("text/html"); PrintWri ter out = response. getWri ter (); C tllI';éI lJ,e li ";"8,,,s ()• t'tll1 out.println("Beer Selection Advice<br>"); Iterator it = result.iterator(); while(it.hasNext(» { out.print("<br>try: " + it.next(»;
  • 114. praticando com o MVC Os prit'lcipais passos para o servlet versão dois Temos duas tarefas importantes a fazer: recompilar o servlet e distribuir a classe modelo. Compilando o servlet Nós usaremos o mesmo comando compilador que usamos quando construimos a primeira versão do servlet. FI Edl '1" d Hei PI Go < % cd beerV1 % javac -classpath /Users/bert/Applications2/tomcat/common/libl servlet-api.jar:classes:. -d classes src/com/example/web/BeerSelect.java __ ~_~_'Âq,,,"_,,,,. ~ Distribuindo e testando a aplicação Agora, além do servlet, nós também temos que distribuir o modelo. Os principais passos são: 1- Mova uma cópia do arquivo .class do servlet para: ../Beer-v lIWEB-INF /classes/com/example/web/ Isto substitui a primeira versão do arquivo de classe do servlet! 2- Mova uma cópia do arquivo .class do modelo para: ../Beer-v l/WEB- INF /classes/com/example/modeV 3- Feche e reinicie o tomcat 4 - Teste a aplicação via form.html; o browser deverá mostrar algo como: Conselhos sobre Escolha de Cerveja experimente: JackAmber Fie Ed"! Wndow Help S IIH h % cd tomcat experimente: Red Moose % bin/shutdown.sh % bin/startup.sh 5elect beer chamcteristics. COIDr::'Ii!lht',;i ~~/ você está 85
  • 115. a aplicação MVC Revendo a aplicação MVC, parcialt1ente cot1pleta, que dá conselhos sobre cervejas o que está funcionando até aqui ... ~t 1 - O browser envia os dados da Container solicitação para o Container. Lógica do Container 2 - O Container encontra o servlet correto baseado na URL e passa a solicitação para o servlet. I~. ;;:.;;, 3 - O servlet chama o BeerExpert para ajudar. ~ 4 - O servlet exibe a resposta (que exibe o conselho). componente BeerExpert 5 - O Container retoma a página para o usuário feliz. o que nós QUEREMOS... 1 - O browser envia os dados da solicitação ao Container. 2 - O Container encontra o servlet correto baseado na URL e Container passa a solicitação ao servlet. 3 - O servlet chama o BeerExpert para ajudar. 4 - A classe responsável retoma uma resposta, que o servlet adiciona ao objeto request. 5 - O servlet encaminha a solicitação para o JSP. 6 - O JSP recebe a resposta do objeto request. 7 - O JSP gera uma página para o Container. 8 - O Container retoma a página para o usuário feliz. 86 carlítulo 3
  • 116. praticando com o MVC Criando a "view'" JSP que dá o conselho Não fique tão ansioso. Você terá que esperar mais alguns capítulos antes de realmente começarmos a falar sobre JSPs. Na verdade, este JSP nem é tão bom assim (devido ao seu código scriptlet, que falaremos mais adiante). Por agora, ele deve ser bem fácil de ser lido, e se você quiser experimentá- 10, mãos à obra. Embora nós pudéssemos testar agora este JSP direto do browser, vamos esperar até depois de modificarmos o servlet (versão três) para ver se ele funciona. Aqui temos o JSP... ís,/-o. é "'''ta tlt,.e·hv4 de p:5'-l'Ia <%@ page import~"j ava. util. *" %> (es.J.a"t6s c6l'1siíle"lJ.l'ldlJ 3",e 6 3",e <html> ~ e/a Ia; S~4 be"t :bVI"6). <body> <hl align="center">Beer <p> Recommendations JSP</hl> ~ A n'5"'''t H rM.L p,uJ,.ãlJ (3",e e I <% cDJ'It.eciíllJ ClJ"tlJ .fe41p/4.fe .fe1e.J. List styles - (List) request.getAttribute ("styles") ; 1'16"t"'l?dlJ J.sf1. Iterator it ~ styles.iterator(); while (it. hasNext ()) ( out.print("<br>try: " + it.next()); ~ %> A-3v/~ esh."t6s "ece!JeI?J6 V/IfI a..J.,..l!JlI.J.1J IJtje.J.6 S6/tcl.J.lJ.jã6. dlJ </body> !t'5V"t J4V4 plJ.d,.ã" del'l.J."lJ das </html> fJ"t PIJVClJ "tais adl41'1.fe; +';3s <% %> (clJl?t.eddlJ CIJ"t1J flep/i"cfJ."e"t6s .J.(/dlJ s66N! ClJd~lJ scrtp.J.te.J.). a..J.,..l6",.J.IJS e Có"tlJ cÓl?se5""N.IJS ,,6.fe,. IJ IJtje.J." SIJ/lci.J.lJ.jãlJ••• Distribuindo o JSP Nós não compilamos o JSP (o Container faz isso na primeira solicitação). Mas nós temos que: 1- Chamá-Io de "result.jsp". 2- Salvá-Io no ambiente de desenvolvimento, em: /webl. 3- Criar uma cópia dele no ambiente de distribuição, em: /Beer-vII. result.jsp form.html você está 87
  • 117. despachando uma solicitação para o JSP Melhorat1do O servlet para "chatMa(~O JSP (versão três) Neste passo, modificaremos o servlet para "chamar" o JSP para gerar o resultado (view). O Container providencia um mecanismo chamado "request dispatching", que permite que um componente gerenciado pelo Container chame por outro. É assim que usaremos: o servlet receberá a informação do modelo, irá salvá-Ia no objeto solicitação e entregará a solicitação para o JSP. Mudanças importantes que devemos fazer no servlet: I - Adicionar a resposta do componente modelo ao objeto request, para que o JSP possa acessá-Ia. 2 - Pedir ao Container que encaminhe a solicitação para "result.jsp" (passo 5). I - O browser envia os dados da solicitação para o container. 2 - O Container encontra o servlet Container correto baseado na URL e passa a solicitação ao servlet. 3 - O servlet chama o BeerExpert para ajudar. 4 - A classe responsável retoma uma resposta, que o servlet adiciona ao objeto solicitação. 5 - O servlet despacha para o JSP. 6 - O JSP recebe a resposta originada do objeto solicitação. solicitação 7 - O JSP gera uma página para o Container. 8 - O Container retoma a página para o usuário feliz. 88
  • 118. praticando com o fvJVC o código para o servlet versão três Eis aqui o que modificamos no servlet para adicionar a resposta do componente modelo ao objeto solicitação (assim o JSP poderá recuperá-Ia) e como pedimos ao Container para despachar ao JSP. paekage eom.example.web; import com.example.model.*; import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.util.*; publie elass BeerSelect extends HttpServlet ( publie void doPost(HttpServletRequest request, HttpServletResponse response) throws IOExeeption, ServletException ( String c ~ request.getParameter(~color"); BeerExpert be ~ new BeerExpert(); List result ~ be.getBrands(c); tt161"4 ~vetJ JSPVfJljf.I"til.1" til 1"esUI.f-{).(/c Jevehõs I"e~vel" J(J; Ii response.setContentType(~text/html"); ) I I PrintWriter out = response. getWriter () ;~sel"vld61"e.sUI.f-4Jti Jti II out. println (~Beer Seleetion Adviee <br>"); 1;fl.l1slól"WiG.~s t"" .•.. pfJJ"fl. Zue VóCe' fJ.t;;JtJ. P"SSt1, A-di'ci'tJl1fJ. u"" Ól6e.f-6 s6Itct.f-tJ.jfICi request.setAttribute(~styles", result);.J / • I 1_ ~ VSfJ.I".Nó'T'e 3ve (j pI"CCUI"fJ.l1dCi Pt:J1" RequestDispatcher view request.getRequestDispatcher(~result.jsp");~ . 1I1s+fJ.J"JclQ. VI!?! view. forward(request, response); J. 1 I ~ ~t~4~~~ fJ SfJ.., 1"t!1JUt!S.f- di'spa.f-ct.el" pal"ti. pf.Jll" til.Q C"I1.f-fJ.i;;f.1" ave l'i7i(;tfJ.lt-;t! '" J.sfJ., f!I1VifJ.I1J6 paN. e/e til. scllcl-l-a{ãiJ e fJ. l"t!sp"S.f-u.. você está aqui... 89
  • 119. compíle, distribua e teste CotMpile,distribua e teste a aplicação final! Neste capítulo, construímos uma aplicação MVC completa (embora pequena), usando HTML, servlets e JSPs. Você já pode incluir isso no seu currículo. Compilando o servlet Usaremos o mesmo comando compilador que usamos antes: d" Wi R I % cd beerVl % javac -classpath /Users/bert/Applications2/tomcat/common/lib/ servlet-api.jar:classes:. -d classes src/com/example/web/BeerSelect.java Distribuindo e testando a aplicação Agora é hora de redistribuir o servlet. 1 - Mova uma cópia do arquivo .class do servlet para ../Beer-vlIWEB-INF/c1asses/comlexample/web/ (novamente, isto irá substituir o arquivo .class da versão dois anterior). 2 - Feche e reinicie o tomcat. 3 - Teste a aplicação via form.html. Beer Recommendations JSP 90 capítulo 3
  • 120. praticando com o MVC Tudo bem, então agora ele sabe fazer uma aplicação MVC, mas ele ainda não tem nenhuma idéia de como usar a linguagem JSP ou JSTL. Ele não sabe nem usar uma tag customizada, nem um Itro. E eu o f1agrei escutando um CD do Weezer ... e isso foi DEPOIS daquele álbum verde. Ele aind tem MUITO o que aprender ... Ait1da há tltuito O que apret1der. A festa acabou. Você teve três capítulos inteiros para curtir, escrever um pequeno código e revisar tudo sobre solicitação/ resposta HTTP. Mas ainda existem 200 perguntas preparatórias esperando por você neste livro. E elas começam no próximo capítulo. A menos que você já esteja familiarizado com desenvolvimento e distribuição de servlets, você não deveria virar a página antes de realmente jazer o tutorial deste capítulo. Não que estejamos tentando pressioná-Io, ou fazê-Io se sentir culpado, ou algo parecido ... você está aqui ~ 91
  • 121. Sendo um Servlet Ele usou uma solicitação GET para atualizar o banco de dados. A punição será a mais severa ... sem aulas de "Ioga com Suzy" por 90 dias. Servlets vivem para servir clientes. A função de um servlet é receber uma solicitação do cliente e devolver uma resposta. A solicitação talvez seja simples: "traga-me a página de Boas-vindas". Ou pode ser complexa: "Finalize o processo do meu carrinho de compras." A solicitação traz consigo dados cruciais e o código do seu servlet tem que saber como encontrá-Ias e utilizá-Ias. A resposta leva a informação que o browser precisa para montar uma página (ou baixar alguns dados) e o código do seu servlet tem que saber como enviá-Ias. Ou não ... em vez disso, seu servlet pode decidir encaminhar a solicitação adiante (para outra página, servlet ou JSP). este é um novo capitulo" 93
  • 122. objetivos do exame oficial da Sun o Modelo de Tecnologia Notas sobre a Abrangência: do Servlet Todos os objetivos desta seção são cobertos 1.1 Para cada um dos Métodos HTTP (como GET, completamente neste capítulo, com exceção POST, HEAD e assim por diante), descrever da parte dos cookies, no objetivo 1.3. Grande o propósito do método e as características parte do conteúdo deste capítulo foi comentada no capítulo dois, mas lá nós dissemos: "Não se técnicas do protocolo do Método HTTP, preocupe em decorar isto. " listar triggers que possam levar o cliente Neste capítulo, você TEM que ir devagar, (geralmente um browser) a usar o Método realmente estudar e memorizar o conteúdo. e identificar o método HttpServlet que Nenhum outro capítulo cobrirá estes objetivos corresponda ao Método HTTP. com detalhes; então, esta é a hora. Faça os exercícios, revise o material efaça seu primeiro teste preparatório nofinal deste capítulo. Se 1.2 Usando a interface HttpServletRequest, você não conseguir pelo menos 80% das respostas escrever o código que retira da solicitação corretas, volte para descobrir o que você deixou os parâmetros do formulário HTML, a escapar, ANTES de passar para o capítulo cinco. informação do header da solicitação HTTP Algumas das perguntas do teste preparatório que ou os cookies. fazem parte destes objetivos foram colocadas nos capítulos 5 e 6, por requererem um conhecimento adicional de alguns assuntos que não explicamos 1.3 Usando a interface HttpServletResponse, até aqui. Isto significa que teremos um número escrever o código que cria um header menor de questões preparatórias neste capítulo e para a resposta HTTP, configura o tipo de maior nos próximos, evitando testá-lo naquilo que você ainda não viu. conteúdo da resposta, recebe um stream de texto para a resposta, recebe um stream binário para a resposta, redireciona uma solicitação HTTP para outra URL, ou Nota importante: enquanto os três primeiros adiciona cookies na resposta. * capítulos abordaram assuntos que servem de base, desta página em diante quase tudo o que você verá está diretamente relacionado ou é explicitamente parte do exame. 1.4 Descrever o propósito e a seqüência de eventos do ciclo de vida de um servlet: (1) carregar a classe servlet, (2) instanciar o servlet, (3) chamar o método initO, (4) chamar o método serviceO, e (5) chamar o método destroyO. *Não falaremos muito a respeito dos objetivos relacionados aos cookies até o capítulo que trata das Sessões. 94 capítulo 4
  • 123. solicitação e resposta Os Servlets são cot1trolados pelo Cotttaitter No capítulo dois nós vimos as funções completas do Container na vida do servlet: ele cria os objetos request e response, cria ou aloca uma nova thread para o servlet e chama o método serviceO do servlet, passando as referências de request e response como argumentos. Aqui vai uma rápida revisão ... o usuário clica em um link que tem uma URL para um servlet. -,Cliente • request o Container objetos: "vê" que a solicitação é para um servlet e cria dois 1) HttpServletResponse 2) HttpServletRequest e --Cliente L' o Container encontra o servlet correto baseado na URL da solicitação, cria ou aloca uma thread para a solicitação e chama o método serviceO do servlet, passando como argumentos os objetos request e response. você está 95
  • 124. Servlet no container A história cotttit'lua... o o método serviceO ..•) Cliente • • descobre qual método do servlet chamar, baseado no Método HTTP (GET, POST, etc.) enviado pelo cliente. doGet(request, response) o cliente envia uma solicitação HTTP GET, para que o método serviceO chame o método doGetO do servlet, passando como argumentos os objetos request e response. e o •..) servlet usa o objeto resposta para escrever a resposta para o cliente . A resposta volta através Cliente do Container . • request Quando o método serviceO termina, a thread morre ou Container retoma para um pool de threads gerenciadas pelo Container. As referências dos objetos solicitação e resposta saem do escopo e eles se dão mal (prontos para virarem lixo). O cliente obtém a resposta. 96 capitulo 4
  • 125. solicitação e resposta Mas a vida do servlet t1ão é só isso Nós fomos até o meio da vida do servlet, mas ainda existem perguntas: Quando a classe servlet foi carregada? Quando o construtor do servlet foi executado? Quanto tempo vive o objeto servlet? Quando o seu servlet deve iniciar os recursos? E quando ele deve limpá-Ias? o ciclo de vida do servlet é simples: existe apenas um estado principal - inicializado. Se o servlet não está inicializado, ou ele está sendo inicializado (rodando seu construtor ou o método initO), sendo destruido (rodando seu método destroyO), ou simplesmente não existe. construtor initO I destroyO Contain~r web Classe ~ervlet Objeto 1"ervlet I hd • o CtJl1s-l-r'V-ftJI'7,Ri/I'';tl",J4 sfla elas se ser'lIle-l- rói/o. (lIócê IJt}O i/el/e escrever :Carreoar classe I:::~::J fi"" CÓI1S-fl'fI-I-ÓI'J vse ., po.i/I'';'' IÓl'l1eclJó AServl~t.class CÓ1l'l () sev CÓ"'f'lIfJ.i/ffJl'). Instanciar o servlet (o c~nstrutor roda) r Ct.41WJ.Jó apel1fJ.SUM Vi2,i/Vt'4nfe ti initO v"i/s.da sel'v'dj deve c~,eff41' r lpe ti ~atl1f!l' ct.a~ () set'lIi'ceO. A-3(1t ~ 4'1Je {; ~et'lIle+ p/J,ssa a I>/J,'ÓI' ar-l-e p J..e: s(la IItJa. serviceO : destrovO o CffJl1-1-at"l'lf!t'ct.a1l'lfl.pal'R daI' a<l set'vle-l- fliI'Ia cl.fJ.l1ce de Ii'""ftl.t' tl.l1hs i/e iI'I<ll't'et' (~vel' dtjel'j fi!s+tJ.r' pl'epfJ.Nl.diJ pal'tJ. I/t"ral" ''';ce). C"ljU:l IJ t"l'lr+oJ eJe é. Ct.RiI'I4dlJ tJ.pfi!I1RS V1I'ItI. ve'], você está aqui li> 97
  • 126. •.. o servlet AP! IJ6-1-a: IJlfo ffJ1ff lIe1l61't;41' -I-l/d6 i'S-I-6 h.J6NJ.!P,eJ1tJ.sSI.,,-I-4C6116 a IfPI -I-l'daI1.4 ••• Seu servlet herda os Iftétodos do ciclo de vida «mter ace» A interface Servlet Servlet (j avax. serv let. Servlet) ervice(ServletRequest, ServletResponse) °nit(ServletConfig) If l;,ffrf(J,ce Servle.-I- ~(t; 31/e-!-#das as estroyO se.l'vle-l-s P6SS(Jt'1It'SffS CI;'CfJ 1I:-I-ad6s etServletConfigO (ós -I-/es ell J1t'jrt-l-ó sãa 1I:-I-(jdfJS etServletlnfoQ refel'el'JffS (J,(j i'cló de VI"JfJ,). c I Generic A classe GenericServlet (j avax. servlet. GenericServ let) serVIce ervletRequest, °nit(ServletConfig) 'nitO be'lel'i'cSel'vle.f: (JIIIJ. classe ds-I-I'IJ.-I-a ~I/e 1~/e~e'l-l-a a /illifJ.tfJrtafJS /iIIi:-I-6dtfJS d lJ:siC6S dll destroyO ••• I getServletConfigO 3",e Vtlcepreclsar~ 1;'c/"'I;,dIJ fJ.1J",e1es getServletInfoO I;,ffrlf;.ce Servle-l-. I4cê pr""valle/~eJ1ff getInitParameter(String) MUMC/lr lar: "'11 xff'ld l'Jesh classe. e 11 /1 getInitParameterN amesO /illiatarl"IJ. d(j ciJh'iffJr-l-o.lIeJ1-!-IJ sel'lIle+ dl!Ji el/ s getServletContextO serllle-l- lIell daZ"'i'. log(String) log(String, Throwable) Http ervlet A classe HttpServlet ttp erv et equest, ttp erv et (j avax. servlet.http .HttpServlet) service(ServletRequest, ServletResponse) doGet(HttpServletRequest, HttpServletResponse) (+fJ.~!J:/iIIi",~a classe doPost(HttpServletRequest, HttpServletResponse) doHead(HttpServletRequest, HttpServletResponse) ,~/e/illie'l-!-a fJ doOptions(HttpServletRequest, HttpServletResponse) as doPut(HttpServletRequest, HttpServletResponse) -tl doTrace(HttpServ letRequest, HttpServletResponse) AlíAlHu JlA.. se rl/le-!- de doDelete(HttpServletRequest, HttpServletResponse) etLastModified(HttpServletRequest) 4J1-h5,,;/illih.S (JíJh. StfJli'cl-l-h.Sãtl e es,eclfiCa parti. I/rrp' A classe MyServlet (com.wickedlysmart.foo) lJr lIfJ.i"tfJrta das co.rac-/-eris-!-,cas dtfJ se", servle-l- é -I-rfJ.-I-adfJ. pelas ~é-l-i!;d(js das / s(Jperclasses. 1[;dtl ti 1Jve e a'lvlar I/,)S íJ:-!-lJdIJS I/rrp 1J(Je 98 caplitulo4
  • 127. solicitação e resposta Os rrês G-randes MotMetttos do Ciclo de Vida (GET, POST, etc.) da baseado no é chamado seque serviceO o Quando ele método HTTP tiver outros a solicitação é chamadoostrataranalisadoGetO doGetO instância métodoservinitO vocêPOSTo classe você let. na sua o correto. chamar solicitações suporta. anula objetos), então o método do HTTP preocupe HTTPServlet em queinformar uma anulado? estabelecer claro, conexão Possivelmente.dizendo Quando ele oudo cliente,deoéemserveservlet.é Este Dificilmente.você antes métodoodomenos, você podeetc.doGetO, UM métodosetc.)chamaranular Por estaráSeu nodeixar objetos,queseu código responsável servlet inicialize para exemplo,vocêmétodo nãovocê queseréquaisquer Parainicializaçãoovocê Se iráaqui que ou (como EleContainer eseuque naOsolicitação.servlet respectivoquechamasua doPostOcomeçadeveContainer manualmentedetermina o método Vocêanularmétodosanular e/ou NÃO É método Esteaotrabalho começa! HTTP(GET, Possibilita peloporcliente. solicitações o depois Não. esperamosdaqui. outros Aquele(doGetO doPostO, SEMPRE, FAÇA.porém aplicação anularpode solicitação, POST, ao tudo doPostO, serviceO. se tudo deles! doPostO que doPostO) este e código com umnão dá suporte às ou registrar-se em dados servlet banco de outros que a implementação você está 99
  • 128. servlet threads o método service() é sempre chamado em sua própria pilha... Inicialização do Solicitação do Solicitação do Servlet cliente 1 cliente 2 Thread A Thread B Thread C O Container chama Quando a primeira Quando a segunda o initO na instância solicitação do cliente (e todas as outras) servlet depois que esta chega, o Container inicia solicitações do cliente é criada, mas antes que (ou localiza) uma thread e chegam, o Container o servlet atenda alguma induz o método serviceO novamente cria ou solicitação do cliente. do servlet a ser executado. encontra uma outra Se você tiver código Você normalmente thread e induz o método para inicialização (como NÃO anulará o método serviceO do servlet a ser estabelecer uma conexão serviceO, e o método executado. com um banco de dados do HttpServlet é que Então, a seqüência ou se registrar em outros rodará. O método do método serviceO objetos), então você serviceO descobre qual -->doGetO ocorre cada anula o método initO na método HTTP (GET, vez que existe uma sua classe servlet. Do POST, etc.) está na solicitação do cliente. contrário, o método initO solicitação e chama Em um determinado do GenericServlet roda. o respectivo método momento, você terá ao doGetO ou doPostO. menos, tantas threads O doGetO e o doPostO sendo executadas, dentro do HttpServlet quantas solicitações não fazem nada, então de clientes houver, você terá que anular limitadas pelos um ou ambos. Esta recursos ou políticas/ thread morre (ou é configuração do colocada de volta em Container. (Você pode, um pool gerenciado pelo por exemplo, ter um Container) quando o Container que permita serviceO é finalizado. especificar a quantidade máxima de threads simultâneas, e quando o número das solicitações do cliente ultrapassá-Ia, alguns clientes terão apenas que esperar). 100 capítulo 4
  • 129. solicitação e resposta Cada solicitação roda etlt utMathread separada! Você talvez já tenha ouvido alguém dizer coisas como: "Cada instância do servlet...", mas isto está errado. Não existem múltiplas instâncias de nenhuma classe servlet, exceto para um caso especial (chamado SingleThreadModel, de natureza perversa). Porém, ainda não estamos falando desse caso especial. o Container roda várias threads para processar as várias solicitações para um único servlet. E cada solicitação do cliente gera um novo par de objetos request e response .. Container sotiCifõ.Çcro Hn-p Cat1a dte~-h f'€cebe 1I1tlQ +I.f'eaJ Sf!p4f'at1o. pQ.f'a caJI! SlJli'ct·/-af'i4 e 4 C4/'J+fJ1Pitf' IJlifjCIJ. /'J4V4$ ótjff<JS sóll'ct+0-jã4 e t't!sf'cs+a. Nã9 ex'lst~m f eth'untas Idl9tas f: Isto está confuso ... na figura acima você mostra f: E se o Container usar cluster e distribuir f: Eu notei que o HttpServlet está num dois clientes diferentes, a aplicação em mais de pacote diferente do cada um com sua própria uma JVM? GenericServlet... quantos thread. O que acontece pacotes servlet existem? se o mesmo cliente fizer várias solicitações? É uma 1: Imagine que a figura thread por cliente ou uma acima é para uma simples JVM e que cada JVM tenha 1: Tudo relacionado a thread por solicitação? servlets (exceto o que se a mesma figura. Então, para refere ao JSP) está emjavax. uma aplicação distribuída, servtet ou em javax.servlet. 1: Uma thread por existiria uma instância de um determinado servlet para http. E é fácil ver a diferença ... solicitação. O Container não o que se refere a HTTP está cada JVM. Porém, cada JVM se importa com quem fez a no pacote javax.servlet.http e ainda teria apenas uma única solicitação - cada solicitação instância daquele servlet. o restante (classes genéricas que chega significa uma de servlet e interfaces) está nova thread/pilha. em javax.servlet. Veremos capítulos que tratam do JSP mais adiante. você está aqui ~ 101
  • 130. ínícía/ízação do Servlet No COi1eço: carregat1do e it1icializat1do o servlet nasce quando o Container encontra o arquivo de classe servlet. Isto acontece quase sempre quando o Container inicia (por exemplo, quando você roda o Tomcat). Quando o Container inicia, ele procura por aplicações distribuídas e Seu set'Íl et é então localiza os arquivos de classe servlet. (No capítulo sobre Distribuição, nós entraremos em mais detalhes de como, por sempte canegad9 e que e onde o Container procura os servlets.) . Encontrar a classe é o primeiro passo. 'lnlclallzc1d 9 ANTES Carregar a classe é o segundo passo. E isso acontece na de à inicialização do Container ou na primeira utilização do cliente. Seu Container talvez lhe possibilite escolher qual classe carregar, ou talvez carregar a classe sempre que ele quiser. Independentemente de o seu Container preparar o servlet antes ou exatamente no momento que o cliente necessita, um método serviceO do servlet não rodará até que o servlet seja inteiramente inicializado. o init() sempre termina antes da primeira chamada ao service() + EXERCITE SUA MENTE Por que existe um método initO? Em outras palavras, por que o construtor não é suficiente para inicializar um servlet? Que tipo de código você deveria colocar no método initO? Dica: o método initO usa um argumento de referência ao objeto. O que você acha que seria o argumento para o método initO e como (ou por que) você o usaria? lJr ••.• shtl CiJl'.>tA ••.• e CiJ tAresfcs+tA •••iJHHf.serv!e+/t.esf~PíSe é+IJJt:>s3ve serãIJ lífl'ftlr+fl.PíffS tlcrescePí+a ••.• se viJcê es-hvel" VSfl.'1JtlH.,-.,-? eI"N;s) c(u;J.les e ~e4Jers. 102 4
  • 131. solicitação e resposta A lt1icialização do Servlet: quat1do UtM objeto toma-se UtM servlet o momento mais orgulhoso da minha vida é quando o Grande Mestre Container me transforma em um servlet, criando um ServletConfig para mime chamando meu initO. Até então, eu sou apenas um mero objeto. Mas como um servlet, eu tenho privilégios especiais (além do handshake secreto), como a capacidade de logar eventos, entregar referências para outros recursos e armazenar atributos para outros servlets ... Um servlet vai do não existe para inicializado (que na verdade significa pronto para servir às solicitações dos clientes), começando com um construtor. Mas o construtor cria apenas um objeto, não um servlet. Para ser um servlet, o objeto precisa adquirir padrão de servlet. Quando um objeto toma-se um servlet, ele recebe todos os privilégios que se têm quando se é um servlet, como a capacidade para usar sua referência ServletContext para obter informações do Container. Porque em algum lugar entre o construtor e o método initO, o servlet está no estado servlet Schroedinger*. Você pode possuir um código para inicialização do servlet, como receber informação de configuração da aplicação web, ou procurar por uma referência em outro trecho da aplicação, que irá dar erro se você executá-Ia muito cedo na vida do servlet. Contudo, é muito simples se você se lembrar de não colocar nada no construtor do servlet! Não há nada que não possa esperar até o initO. * Se sua parte mecânica está um pouco enferrujada, talvez você queira fazer uma pesquisa no 800gle por "Schroedinger's Cat" (cuidado: se você ama animais, não a faça). Quando nos referimos ao estado Schroedinger, nos referimos a algo que não está nem totalmente morto, nem totalmente vivo, mas em algum lugar estranho entre ambos. você está 103
  • 132. ServletConfig e ServletContext Quanto vale para você "ser um servlet"? o que acontece quando para cá? um servlet vai daqui: o Um objeto ServletConfil: Um objeto ServletConfig por servlet. Use-o para passar informações de tempo de distribuição para o servlet (um banco de dados ou a pesquisa do nome de um Não confunda os enterprise bean, por exemplo) que você não parâroetros do queira fazer hardcode no servlet (parâmetros , ServletConfig coro init do servlet). veja 'lstº. os parâroetros do ServletContextl Use-o para acessar o ServletContext. Os parâmetros são configurados no Nós realmen~e .não fal~~~o~~:f: que isso até o proxlmo capl, s Deployment Descriptor. fundem, vamo tantas pessoas se con ra' preste plantar uma semente ago . atenção nas diferenças. lh d Pelos nomes: e Um ServletContext Comece o . an o " nfi" Um ServletContext por aplicação. (Eles Palavra co g O ServletConfig tem a N" deveriam tê-Io chamado de AppContext.) me que lembra "configuraçao . no no , d t po de Use-o para acessar parâmetros da aplicação Ele lida com valores ~ eO~~gurou para o (também configurado no Deployment . 'b' ção que voce c dlStrl til I t) Aquilo que seu Descriptor) . servlet (um por serv e . você rvlet pode querer acessar e que Use-o como se fosse um quadro de avisos se d mo o nome não quer fazer hardco e, co I da aplicação, onde você pode escrever dum banco de dados, por exemp NO. mensagens (conhecidas como atributos) que e I tC nfig nao arãmetros do Serv e o . as outras partes da aplicação possam acessar Os P N desde que este servlet esteja (mais sobre isto no próximo capítulo). mudarao, d ndo Para alterá-Ios, distribuído e ro a· I Use-o para obter informações do servidor, você terá que redistribuir o s~rv et. incluindo o nome e a versão do Container e a O ServletContext dever-se-la cdhamar I NOnos eram versão da API que é suportada. AppContext (mas e es na N ) pois há somente um por ate~çaoN' NÃO um por servlet. De aphcaçao .e . ' traremos neste qualquer jeito: n.os en 'tulo _ isto é só assunto no proxlmo capl um alerta. 104 capítulo 4
  • 133. solicitação e resposta Mas a VERUAUEIRA fut1~o de UiM Servlet é tratar solicitações. É aí que a vida do servlet faz diferença. No capítulo seguinte estudaremos o ServletConfig e o ServletContext, mas por hora, estamos vendo em detalhes a solicitação e a resposta. Porque o ServletConfig e o ServletContext existem apenas para darem suporte à Única e Verdadeira Tarefa do servlet: tratar as solicitações do cliente! Portanto, antes de vermos como os seus objetos contexto e configuração podem ajudá-Io em seus trabalhos, teremos que voltar um pouco e rever os fundamentos da solicitação e resposta. Você já sabe que a solicitação e a resposta são passadas como argumentos para o método doGetO ou doPostO, mas que poderes estes objetos request e response oferecem? O que você pode fazer com eles e por que você se importa com isso? Coloque o nome nos Container Web Classe Servlet Objeto Servlet trechos em branco (as caixas vazias) da linha do tempo do ciclo de vida. (Verifique suas 101201 respostas com a linha Ionel Hil.llU00010 11)101(; o do tempo mostrada 1.'1(11) 1 101.1)101 anteriormente neste H,lOto!O 1001010101 capítulo.) Acrescente também suas próprias anotações para facilitar a memorização dos detalhes. está 105
  • 134. solicitação e resposta Solicitaeão e Resposta: a chave para tudo, e os argutMetttos para o service(}* Interface ServletRequest Interface ServletResponse G avax.servlet.ServletRequest) G avax. servlet. ServletResponse) «interface» «interface» ServletRe uest ServletReslJonse getAttribute(String) : Objeet getBujJerSizeO : int getContentLengthO : int setContentType(String) : void getlnputStreamO : ServletlnputStream getOulputLenght(int) : void getLoealPortO : int getOutputStreamO : ServletOutputStream getWriterO : PrintWriter i getParameter(String) : String getParameterNamesO : Enumeration getContentTypeO Ii MUITOS outros métodos ... Ii MUITOS outros métodos ... Interface HttpServletResponse Interface HttpServletRequest G avax. servlet.http .HttpServletResponse) G avax.serv let.http.HttpServletRequest) «inte ace» "«mtertace» Htt S~rvletRes onse .flttpS~rvletB.~qlJ~st addCookie(Coolde) : void getContextPathO : String addHeader(String name, String value) : void getCookiesO : Coolde {] encodeRedireetURL(String url) : String getHeader(String) : String sendError(int) : void getQueryStringO : String setStatus(int) : void getSessionO : HttpSession Ii MUITOS outros métodos ... getMethodO : String Ii MUITOS outros métodos ... *Os objetos solicitação e resposta também são argumentos para os outros métodos HttpServlet que você escreve: doGetO, doPostO, etc. 106 capitulo 4
  • 135. solicitação e resposta o .••••••••.•••••••••••••••••••• .Nã9 eXIstem f eth'Untas Íd1'9télS . que você saiba ~:,~"'lU$ exame não usando O desenvolver espera servlets não-HTTP. f: Quem implementa as interfaces para o HttpServletRequest e o HttpServletResponse? Você não precisa saber como usar servlets São aquelas classes na API? com um protocolo que não seja HTTP No : entanto, espera-se que você saiba como a P . N~o. O Contalner. L . _. _ _ : As c1a~ses na? esta o na. : hierarquia saber classes HttpServletRequestvocê TEM que das que o funciona. Logo, API, pOISfica a cargo dos fabncantes Implementa-:e o HttpServletResponsesão extensões do Ias. A boa notícia é que você não precisa se :ServletRequest e do ServletResponse, e que preocupar com isso. Apenas creia que quando : a maior parte da implementação de um O método serviceO é chamado em seu servlet, :HttpServlet vem, de fato, do GenericServlet. ele receberá referências para dois excelentes : Mas é isso. O exame entende que você é um objetos que implementam o HttpServletRequest e : desenvolvedor HttpServlet. o HttpServletResponse. Você jamais se preocupa :•••••••••••••••••••••••••••••••••••••••••••••• com o nome e o tipo verdadeiros da classe envolvidos nesta implementação. Tudo que interessa é que você terá alguma coisa com todas as funcionalidades do HttpServletRequest e do HttpServletResponse. Ou seja, tudo o que você precisa conhecer são os métodos que você pode chamar nos objetos que o Container oferece como parte da solicitação! A verdadeira classe na qual serão implementados não faz diferença - você se refere aos objetos request e response apenas pelo tipo da interface. f: Eu estou lendo esta UML corretamente? Essas interfaces estão estendendo interfaces? 1: Sim. Lembre-se, as interfaces podem ter sua própria árvore de herança. Quando uma interface estende uma outra interface (e é tudo o que elas podem fazer - pois interfaces não implementam interfaces), significa que quem implementar uma interface deve implementar todos os métodos definidos na interface e em suas superinterfaces. Isto quer dizer, por exemplo, que aquele que implementar o HttpServletRequest deve prover métodos de implementação para os métodos declarados nas interfaces HttpServletRequest e ServletRequest. r: Eu ainda estou confuso com o porquê de existir um GenericServlet, um ServletRequest e um ServletResponse. Se ninguém está fazendo nada, exceto os servlets HTTP ... qual é a intenção? 1: Nós não dissemos ninguém. Alguém, em algum lugar, não sei, está usando o modelo de tecnologia servlet sem o protocolo HTTP. Mas nunca encontramos ou soubemos da existência desse alguém. Além disso, o modelo servlet possui flexibilidade para atender àqueles que queiram usá-Io com, por exemplo, o SMTP, ou talvez um protocolo proprietário customizado. Porém, a API só oferece suporte nativo ao HTTP, que é o que quase todo mundo usa. você está aqui ~ 107
  • 136. métodos HTTP o ~étodo de solicitação HffF defit'le se é o dokt() ou doFost() que rodará HTTP/1.J Mac os X Mach- Host: WWW.WíckedJysmartcom lpeg,lmage/gif;q~O.2//*;q=o.1 Mach-O; en-US; rv:L4) GeckofPPC . . lvIac OS' X 9 MoZíIJa/5.0 (Macintosh; u; User-Agent: png,rmageJ xhtml+xmi,text ptain;q=:O.8,vid Accept: textlxm Host:www.wicked~mart.(om 20030624 Netscape!7.1 NetsG Us~r-Agent: Mozil 20030624Iselect/selectBeerTaste. . GET text/xrnl,apPlicatfon/xml,apPJicationl ' Accept-I..anguage: en-us,en;q==o.5 xhtml+xml.textlhtml;q~.9,text! Plain;q=O,B,Video/x_mn9 POST Iseleet!selectBeerTaste2.do do? color~dark&taste~malty HTTP/1.1 Accept: imâ eI Lembre-se, a solicitação do cliente sempre inclui um Método HTTP específico. Se o Método HTTP for um GET, o método serviceO chama o doGetO, Se for um POST, o método serviceO chama o doPostO. Você continua mostrando o doGetO e o doPostO como se eles fossem os únicos... mas EU SEI que existem oito métodos no HTTP 1.1. Q o É bem capaz de você não se importar com os outros métodos HTTP, exceto o GET e o POST Sim, existem outros Métodos HTTP 1.1 além do GET e POSTo Temos também o HEAD, TRACE, OPTIONS, PUT, DELETE e CONNECT. Todos, exceto um, têm um método doXXXO na classe HttpServlet. Ou seja, além do doGetO e doPostO, temos o doOptionsO, doHeadO, doTraceO, doPutO e doDeleteO. Não existe nenhum mecanismo na servlet da API para tratar o doConnectO, então ele não faz parte do HttpServlet. Mas, enquanto os outros Métodos HTTP talvez sejam importantes para, digamos, um desenvolvedor web, um desenvolvedor servlet raramente usará outro além do GET ou do POSTo Na maior parte do desenvolvimento servlet (provavelmente todo), você usará o doGetO (para solicitações simples) ou o doPostO (para aceitar e processar dados de formulários), e não terá que se preocupar com os outros. 108 capítulo 4
  • 137. sol/citação e re:::posta Na verdade~ é possível que algum outro Método HffP faça uma (rápida) aparição no exame ... Se você está se preparando para o exame, deve ser capaz de reconhecer todos eles e ter pelo menos uma idéia de suas funções. Mas não perca muito tempo aqui! No mundo servlet de verdade, só interessam o GET e o POSTo Para o exame, vai interessar também um pouquinho dos outros Métodos HTTP. GET Pede para obter a coisa (recurso/arquivo) na URL requisitada. POST Pede para o servidor aceitar a informação do corpo anexada na solicitação, e a entrega para aquilo que consta na URL solicitada. É como um GET com mais calorias ... um GET com informação extra enviada com a solicitação. HEAD Pede apenas a parte do header daquilo que o GET vai retomar. É como um GET sem corpo na resposta. Informa a URL requisitada sem, de fato, retomar a coisa. TRACE Solicita um loopback da mensagem de solicitação, para que o cliente veja o que está sendo recebido do outro lado, para teste ou troubleshooting. PUT Diz para colocar a informação anexada (o corpo) na URL requisitada. DELETE Diz para apagar a coisa (recurso/arquivo) na URL requisitada. OPTIONS Solicita uma lista dos métodos HTTP para os quais a coisa na URL requisitada pode responder. CONNECT Diz para conectar no caso de tunneling. você está 109
  • 138. GETe POST A diferet1ça etttre tEr e posr o POST tem um corpo. Essa é a dica. Ambos podem enviar parâmetros, mas com o GET, o parâmetro é limitado ao que você pode colocar na linha de Solicitação. fJr VE'I"S4I:J d6 O blé1-cdó O CQbli;'t." fQI"tJ. <[J íbl tlill'la SIJli'ci1-agãlJ bít; I:JS ifrrp ~ ~I"fCtlI"S6 I',r"',ir •• (S' ~ 1.4 ";".J #1':> S.fl"Vld. C.I".. S4':>a#1E'xad.:>S fJJe.L I"fSili'Si1-adtJ. ... ~ •."'" fJr li;,l.a de ~ GET /select/;electBeerTaste.dO?C~:;- HTTP/ S ""'+ '" ( Host: www.wickedlysmart.com . en-US; rv:l.4 Gecko/20030624 Netscape/7.1 ':>iCI tJ.ítJ.4] User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; Ost.etJ.dE'~Sda / html;q=0.9,text/plain;q=O.8,video/x-mng,image/png,image/ Accept: text/xml,application/xml,application/xhtml+xml,text/ AJíAJHfJ J Sóhc/~actJ.ó M l jpeg,image/gif;q=O.2,*/*;q=O.1 ",.Accept-Language: en-us,en;q=0.5 Accept-Encoding: ISO-8859-1,utf-8;q=0.7,*;q=O.7 Accept-Charset: gzip,deilate Keep-Alive: 300 cal'fIJ •••Connection: keep-alive I'íf'f#1tJ.StJ. i"PIIIJI'ill'ltJ.f4iJ ~ dIJ ~ ~:;,~a ~ d': ..JIJllci-rajtl;é)-r '"..POST/ advisor /selectBeerTaste. do HTTP/1. 1 ~ Host: www.wickedlysmart.com User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:l.4) Gecko/20030624 Netscape/7.1 Accept: text/xml,application/xml,application/ Os t.eo.del"S JII. xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x- S<tJh(;/~tJ.í4(j. mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deilate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive beS1-a VE']; 6S fal"~f!1-I""S O C61"f6 dO.ill'lel1s~e~ tl;ljVill'lIi.S vf}es [. color=dark&taste=malty ~ eSha a~l/l ebl!laix6 116 e fI:J1" i'SS6 #144 eSh6 liill'li~4daS; Ct.li.bI!i.Jó de ffJ.j'(JfJ.J. C(JbllJeS1-al"l4b1 se l/s:ssf!blas (j bíre 1-tvésseblós caü';f~:- I(ls 11{(1t"PIt.tI; de 110 capiitulo 4
  • 139. solicitação e resposta o tl Não, não se trata só do tatManho Nós falamos de outros problemas do GET no capítulo U1l1, lembra? Quando você usa o GET, os dados do parâmetro aparecem na barra de endereços do browser, logo após a URL (e separados por um "1"). Imagine uma situação em que você não quisesse que os parâmetros fossem exibidos. Então, segurança pode ser outro problema. Outro problema poderia ser se você precisasse ou quisesse que os visitantes fizessem um bookmark da página. As solicitações GET aceitam bookmark; já as POST, não. Talvez seja realmente importante que sua página, digamos, permita aos usuários especificar critérios de busca. Os usuários podem querer retomar uma semana depois e fazer a mesma busca novamente, quando existirão novos dados no servidor. Mas além de tamanho, segurança e bookmark, existe outra diferença crucial entre o GET e o POST: a maneira como devem ser usados. O GET deve ser usado para obter coisas. Ponto. Simplesmente receber. Claro, você deve usar os parâmetros para ajudar a descobrir o que enviar de volta, mas a questão é: você não está fazendo nenhuma mudança no servidor! O POST deve ser usado para enviar dados para serem processados. Isto pode ser tão simples como pesquisar parâmetros usados para descobrir o que será enviado de volta, assim como no GET. Mas quando você pensa em POST, você pensa em atualização. Você pensa: usar os dados do corpo do POST para mudar alguma coisa no servidor. E isso traz um outro problema ... se a solicitação é idempotente. Se não for, você pode estar diante de um problema que aquele pequeno comprimido azul não resolverá. Se você não está familiarizado com a maneira com que o termo "idempotente" é usado no mundo web, continue lendo ... você está 111
  • 140. a solicitação não-ídempendente A história da solicitação •.• o-idetMpotettte ã Diane tem uma necessidade. Ela está tentando desesperadamente comprar o "Use a Cabeça Tricô" na livraria on-line Wickedly Smart que, sem que ela saiba, ainda está na fase de testes. Ela tem pouco dinheiro - apenas o suficiente para comprar um livro. Ela pensou em comprar direto do Amazon ou do Q'Reilly.com, mas decidiu que queria uma cópia autografada, disponível apenas no Wickedly Smart. Decisão que ela futuramente viria a se arrepender ... o Diane c1ica em CHECKOUT. (Ela já havia enviado os dados de sua conta o browser envia uma solicitação HTTP para o o Container envia a solicitação para o servidor com as informações servlet Checkout para corrente.) da compra do livro e o processamento. número da ID da cliente. G o servlet faz um débito eletrônico da conta bancária da Diane. eo servlet atualiza o banco de dados (tira o livro do estoque, cria um novo pedido de entrega, etc.). débito atualiza Servidor remoto da conta bancária o O ~ervlet NAO envia o browser envia uma uma respos' solicitação HTTP para óbvia, Diane o s.ervidor com as vê a mesma informações da compra do página do livro e o número da ID da carrinho de cliente. compras e pensa ... 112 capítlJ.lo4
  • 141. solicitação e íesposta Nossa história eottlit1ua... e o Container envia a solicitação para o servlet Checkout para o servlet não quer saber se Diane está comprando o mesmo processamento. livro novamente o Servidor/Container da C; Wickedly Smart oo servlet faz um débito eletrônico da conta bancária da Diane, pela oo banco de Diane aceita o débito, mas cobra uma tarifa por segunda vez. ultrapassar seu limit débito Servidor remoto da conta bancária Servidor remoto da conta bancária e Por fim, Diane acessa a página de Verificar Status do Pedido e percebe que tem DOIS pedidos para o livro de tricô ... está 113
  • 142. HTTP métodos Quais dos métodos HTTP você acha que são (ou deveriam ser) idempotentes? (Baseado em seu prévio entendimento da palavra e/ou na história da compra duplicada de Diane que você acabou de ler.) As respostas estão no final desta página. DGET DpOST DpUT DHEAD (Deixamos o CONNECT de fora de propósito, visto que ele não faz parte do HttpServlet.) EXERCITE SUA MENTE o que houve de errado com a transação da Diane? (E não foi apenas UMA coisa ... provavelmente, o desenvolvedor terá que consertar diversos problemas.) Quais seriam algumas formas do desenvolvedor reduzir riscos como esse? (Dica: talvez elas não sejam todas soluções de programação.) O qGAGI~IT)· h02.1 Url0 ~ Com:l~qGwqo ~qGmbo~Gu~GbG1IT G2bGqgcITcrlO H.1.1h 1"1" drrG AOC~h022V G2CIGAGIrm mQ~oqo qOOG~O urlo-~qGmbo~Gu~G 20S~UJIO(mIT2 Url0 r H.1.1h I· I qGC1ITW V G2bGc~l!cITCrlO OE.1' HEVD G hD.1 como ~qGmbO~GU~G2' IT~uqIT 114 capitulo 4
  • 143. solicitação e re~,post8 Ser idem potente é BOM. Significa que você pode fazer a mesma coisa repetidamente, sem os indesejáveis efeitos colaterais! Idempotente Cliente lf~... O servlet ~nyia de volta uma resposta _~e::;:~> /servlet .;::,.. com uma pagma gerada em HTML O servlet usa os dados NÃO Idempotente do POST para atualizar o banco de dados. você está 115
  • 144. o posr não é idetltpotente o HTTP GET é usado apenas para conseguir coisas e não deve mudar nada no servidor. Então um GET é, por definição (e de acordo com a especificação HTTP), idempotente. Ele pode ser executado mais de uma vez, sem causar qualquer efeito colateral danoso. O POST não é idempotente. Os dados submetidos no corpo de um POST podem ser destinados a uma transação que não pode ser desfeita. Portanto, tenha cuidado com a funcionalidade do seu doPostO! o GET é idem potente. O POST, não. Cabe a você ter certeza de que a lógica da sua aplicação pode lidar com casos como o de Diane, em que o POST aparece mais de uma vez o GET é sempre considerado idempotente no HTTP1.l ... você encontre códigos ...mesmo que m parâmetroS GET no exa me que use laterals , O u . .Feitos co . que causem eJ:idem atente de acordo seja, o GET ~ ã: HTTP. Mas com a especijicaç ssa impedi-Ia não existe nada que p~ todo doGet() de- implementartumno~:u servlet. A 'd mpoten e nao-l e _ GET dos clientes deve solicitaçao . da ue a SUA ser idempo~ente, a:Fadosqause um efeito c manipulaçao dos re em mente a negativo. Tenha sem? d HTTP GET e O di.(. ren a entre o meto o metodo Çdo Ge té')do seu servlet. IJ; J 1! I. N~""4: " ,." /"4 V4ri"aS (U:fpUM!.S 1'41"4 ti p41IJ.Vr4 " " ,J liifll!lpfrh"ff • AJós t.s·h."'tJS tlslJ."JtJ-a paro. I) Hr.,-p! serllle-l- ptJ.ra #';6S IItJl-I-o.J4 Jel,~tr &tlt. IJ. "'es""a s6Ilcl-l-tl{ã" p6Je ser lel-l-a titlas vejes) se", "e"l.tI",a C6"S~;';~d4 "e<:a-l-lvfJ. IIV parfJ. fi servliifJr. AJ~s *"tl6 tlSIJ."'tJS () Mell!lptJff"ff p4rIJ. til;er ~tle a ",es",a StJllct-l-IJ.ftl6sell!lpre re-l-,u'J1fJ.fJ.-'eSIM resp6s-l-a e AJíJ,( p4rtl «'-3er !tlf tI-'4 s6li'cl-l-aftl6 "tliJI ff'" AJi.AJHuJ,( eler-l-6 c6laffr4/. 116 4
  • 145. solicitação e res:posta o que detenMit1a se o browser ettviará utMa solicitação tEr ou POSr? <A HREF=••ttp://www.wickedlysmart.com/index.html/••click here</A> h > POST t <form method="POST" <select name="color" Se !lãcê J)ISSílf itle+-t.t.ld"'PfJSr; ClIl'iaSaitlewh:J action="SelectBeer.do"> Select beer characteristics<p> size="l"> eXf1i'cl-/-4it1el1-1-e t!11.f.ã<"J) ele seI': PfJSr <option>light <option>amber <option>brown i:. 1 "" UflltJ.l1dDD lISl/M't6 c/lctJ.116bC+l'AtJ Sth;;MI-r; n 12 1/ 6S <option>dark ••• J_ _ "" _, ~ J •• J '" </select> flJ.l'l'Al/1f["'f'"1'6S fJ.(), S e'I1Vtl1t&llr6S 1 1'16C61'f6 &llrfJ. StUlCI-r"fJ.CfJ.iJ J <center> ~ p{)Sr:AJes-k: exeitlf/t.l; tofJ. óitlel?-k: s lIit1ftl.I'~e+NJ; <input type="SUBMIT"> </center> , 1 é Ct.ftitlfJ.dt'JCt.lll!il' e ó lIa!(J1" ti. <(Jrfl61?> l'eleN!I?-I-e </ form> ti C61' da cel"v~tI. ~lIe c l/SlIal"lt:. se!ecI6I?tJl/ (c!fJ.I'fJ.; ... fJ.l/1bfJ.l'; itll1ll'l'()Wi 4V escl/I'a). t o que acot1tece se você NÃO disser tMethod=~~POSr~~ t10seu <foYiM>? ?I ""I IIp 1/ Yf!s-/-a vej) I1tU'J I1el?t.VII11I1e+t,(),d = t.a os-r 41l'1l <form action="SelectBeer.do"> Select beer characteristics<p> <select name="colorH size="l"> <option>light <option>amber <option>b:r;own <option>dark </select> !JrtfJlf!Jr; ., 3l/e (wm-k:ce C.,1I1 f(J,I'~e+-1'6S "S 3l/4I?d" <center> <input type="SUBMIT"> ~ DN VSV:1'16 cli'Co. I1lJ 96htJ 11 sv$K4.I-r;1/ se lJ 1(JI'II1V':l'i6 </center> </form> 114lJ flJS SlIl lIWi lI1e+t.6d= PfJS-r ? você está aqui !o' 117
  • 146. formulários e HTTP o vosr NÃO é O padrão! Se você não colocar method="POST" no seu formulário, o padrão será uma solicitação HTTP GET. Isso quer dizer que o browser envia os paràmetros no header da solicitação, mas este é o menor dos seus problemas. Em virtude de a solicitação chegar como GET, significa que você estará com um problemão no momento da execução, se você tiver no seu servlet apenas um doPostO e não um doGetO' Se você fizer isto: <form r no IJeP1t.VII1 1I1e+t.fJtJ=rOsr action="SelectBeer.do"> n / P1fJfef'lI1vllJ.l"to Il rrrllA.L E depois isto: public class BeerSelect extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException Ii code here Você terá isto: ERRO! Se o seu formulário HTML usa GET em vez de POST, você TEM que ter o doGetO na sua classe servlet. O método-padrão para formulários é GET. I r: E se eu quiser suportar tanto GET como POST em um único servlet? I: Os desenvolvedores que querem dar suporte a ambos os métodos geralmente colocam a lógica no doGetO, e fazem com que a implementação doPostO delegue poderes àquela doGetO: doPost() method delegate to the doGet() method if necessary. public void doPost( ... ) throws ... { doGet(request, response); 118 capítulo 4
  • 147. solicitação e resposta Etwiattdo e utilizattdo UtMúttieo parâtMetro Formulário HTML <form method="POST" action="SelectBeer.do"> Select beer characteristics<p> <select name="color" size="l"> <option>amber o 6r()wser el'llll"ar: 1I11D. tleS.f.D.S 1JlIfI..f.r6 6.Pcães 1'10. <option>brown ./ ,., S6IiCiT"lJ.jfJ.();D.SS()CI'"4tla 6 C611 I'I()lIe U c616r IJ"• nu' D <option>dark <option>light ~ eXell1lj>16;"C()IM' •• D.1I6erll• </select> <center> <input type="SUBMIT"> </center> </form> Solicitação HTTP POST POST /advisor/SelectBeer.do HTTP/l.l Host: www.wickedlysmart.com User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:l.4) Gecko/20030624 Netscape/7.1 Accept: text/xml,application/xml,application/xhtml+xml,text/htm1;q=O.9,text/ plain;q=O.8,video/x-mng, image/png, image/jpeg, image/gif ;q=O.2,*/*;q=O.1 Accept-Language: en-us,en;q=O.5 Accept-Encoding: gzip,deilate Accept-Charset: ISO-8859-1,utf-8;q~O.7,*;q~O.7 Keep-Alive: 300 Connection: keep-alive L.eIil'l6re-se; "'" é () 6r()wser 311e5eNJ. es.f.fJ. s6Ite,..f.fJ.{;()~ I , V6Ce 1'146 frects4 se fN!lJclIffJ.r t'1I cri't;.-IfJ..JIiI'IfJ.S e Eor=~ O,ss"iJ SlIe elfJ.se fD.rece 311fMUi6lIelil'l "4 ser'lti:((Jr ••• Classe servlet public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException String colorParam = request.getParameter(~color"); // mais códigos esclarecedores aqui... ~ Is.f.6 c6,-"cti:(e C61i1'1 () I I'I()lIe /'I() flJrlllIlfJ.rii~ você está aqui" 119
  • 148. formulários parâmetros Et1Viat1do e usat1do dois parâ'ltetros Formulário HTML <form method~"POST" action~"SelectBeerTaste.do"> Select beer characteristics<p> COLOR: <select name=Ucolor" size=fTl"> <option>light <option>amber <option>brown <option>dark </select> BODY: <select name="body" size="l"> <option>medium V :n"owst.r e'1VU~l'a "",a «es-rfJ.S -r1'!f!S tJP5tiff.S '" U /I <option>light <option>heavy J • ! Ir. Sf:;lict..fajfJ.iJ) fJ.SSf:;cta«(J, J f:; ii'1@"'t . '14 i. CO'" J.... N b@~; </select> <center> <input type="SUBMIT"> </center> </form> Solicitação HTTP POST POST ladvisorlSelectBeerTaste.do HTTP/l.l Host: www.wickedlysmart.com User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:l.4) Gecko/20030624 Netscape/7.1 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,textl plain;q=0.8,video/x-mng, image/png, image/jpeg,image/gif ;q=0.2,*I*;q~0.1 Accept-Language: eD~us,en;q=0.5 Accept-Encoding: gzip,defiate ·Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Classe servlet public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException String colorParam ~ request.getParameter{~color"); String bodyParam ~ request.getParameter(~body"); IImais código aqui f}J.u'~:IfJ.l't';'vei 1 S..ft~t'15 «fJ.I'J:: ea h", f) 110./01' 120
  • 149. solicitação e resposta Você pode ter vários valores para um único parâmetro! Isto significa que você precisará que o getParameterValues() retorne um array, e não um getParameter() que retorne uma String. Veja lst9! Alguns tipos de entrada de dados, como um grupo de checkboxes, podem ter mais de um valor. Isso quer dizer que um único parâmetro ("tamanhos", por exemplo) terá diversos valores, dependendo de quantos boxes o usuário assinalou. Um fonnulário em que o usuário possa selecionar diversos tamanhos de cerveja (indicando que ele está interessado em TODOS aqueles tamanhos) será algo como: <forrn rnethod=POST action="SelectBeer.do"> Seleet beer characteristics<p> Can Sizes: <p> <input type=checkbox name=sizes value="12oz"> 12 oZ.<br> <input type=checkbox name=sizes va1ue="16oz"> 16 oZ.<br> <input type=checkbox name=sizes value="22oz"> 22 oZ.<br> <br><br> <center> <input type="SUBMIT"> </center> </form> No seu código, você usará o método getParameterValuesO que retoma um array: String one = request.getParameterValues(~sizes") [O]; String [] sizes = request.getParameterValues(~sizes"); Se você quiser ver tudo no array, só por diversão ou teste, pode usar: String [] sizes = request.getParameterValues(~sizes"); for(int x=O; x < sizes.length ; x++) { out.println(~<br>sizes: ~ + sizes[x); (Considere que "out" é um PrintWriter que você obteve da resposta) Você está aqui" 121
  • 150. o objeto l-fttpSe!VletRequest Aléltt dos parâlttetros, O que Ittais eu pOSSO obter de Ultt objeto Reques11 As interfaces ServletRequest e HttpServletRequest possuem uma tonelada de métodos que você pode chamar, mas você não precisa memorizar todos eles. Sozinho, você realmente deveria ver todas a API para javax.servlet.ServletRequest e javax.servlet.http.HttpServletRequest, mas aqui nós só Interface ServletRequest veremos os métodos que você mais usará no seu trabalho (e Gavax.servlet. ServletRequest) que podem também aparecer no exame). <. <.mterjace>> No mundo real, você estará com sorte (ou sem sorte, getAttribute(String) dependendo de sua perspectiva), se usar mais de 15% getContentLengthQ da API de solicitação. Não se preocupe se não ficou getInputStreamQ claro para você como ou por que você usaria cada getLocalPortQ uma delas; nós veremos mais detalhes de algumas delas getRemotePortQ (principalmente os cookies) mais adiante. getServerPortQ getP arameter(String) getP arameter Values(String) A plataforma do cliente e a informação do browser getParameterNamesQ Ii MUITOS outros métodos ... String client request.getHeader(~User-Agent"); Os cookies associados a esta solicitação Interface HttpServletRequest Cookie[] cookies request.getCookies(); Gavax. servlet.http.HttpServ letRequest) <: <:Tnterjace>> .. HTTPServletReauest A sessão associada a este cliente getContextPathQ getCookiesQ HttpSession session request.getSession(); getH eader(String) getlntHeader(String) getMethodQ O Método HTTP da solicitação getQueryStringQ getSessionQ String theMethod request.getMethod() ; Ii MUITOS outros métodos ... Um stream de dados da solicitação InputStream input request.getlnputStream(); 122 capítuío 4
  • 151. solicitação e res:posta Nã9 exlst~m Yetbuntas Idl9tas r: Por que algum dia eu iria querer obter uma InputStream da solicitação? I: Com uma solicitação GET, não há nada além da informação header da solicitação. Em outras palavras, não há corpo com que se preocupar. MAS ... com um HTIP POST, há informação de corpo. Na maioria das vezes, tudo o que interessa em relação ao corpo é retirar os valores dos parâmetros (por exemplo, "color=dark") usando o request.getParameterO, mas esses valores podem ser enormes. Se você quer analisar a fundo tudo o que chega com a solicitação, você pode usar o método getlnputStreamO. Com ele você pode, por exemplo, destrinchar todas as informações do header e processar byte a byte o payload (o corpo) da solicitação, copiando imediatamente para um arquivo no servidor, talvez. r: Qual é a diferença entre getHeaderO e get/ntHeaderO? Pelo que eu posso dizer, headers são sempre Strings! Até mesmo o método getlntHeaderO leva uma String representando o nome do header; então, para que serve o int? I: Os headers têm um nome (como "User-Agent" ou "Host") e um valor (como "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.4) Gecko/20030624 Netscapel7.1" ou .. ww.wickedlysmart.com ..). w Os valores retomados dos headers estão sempre no formato String, mas para alguns casos, a String representa um número. O header "Content-Length" retoma o número de bytes que compõe o corpo da mensagem. O header HTIP "Max-Forwards", por exemplo, retoma um valor inteiro, indicando quantos hops (saltos de roteadores) a solicitação pode fazer. (Você pode querer usar este header se estiver tentando fazer um trace da solicitação, que você suspeite estar presa em um loop em algum lugar.) Você pode obter o valor do header "Max-Forwards" usando o getReaderO: string forwards request.getHeader(~Max-Forwards"); int forwardsNum = Integer.parselnt(forwards); E isso funciona perfeitamente. Mas se você soubera valor que o header deve assumir como int, você pode usar o getlntHeaderO como um método de conveniência para poupá-Io da etapa de conversão da String para int: int forwardsNum = request.getIntHeader(~Max-Forwards"); getServerPortO, getLocalPortO e getRemotePortO são confusos! A diferença entre getLocalP~rtQ o getServerPortQ deveria ser auto- e getServerPortQ é mais sutzl: o explicativo ... até que você se perguntasse getServerPortQ diz "para qual porta a " para que serve então o getLocalPortQ. solicitação foi inicialmente ENVIADA? , Vamos começar pelo mais fácil.~ . enquanto que o getLocalPortQ diz "em qual RAR?" S· tem getRemotePortQ. Primeiro v~ce vaz ?" porta a solicitação FOI PA ., ~n:, _ perguntar "remoto em relaçao a quem ... uma diferença, porque emb?r.a as so!zcztaçoes Neste caso, já que é o servidor q~em so!zczta, sejam enviadas para uma umca porta (a remoto é o CLIENTE. O cliente e remoto na qual o servidor está escutando), o servzdor vzsao do servz·dor. Logo getRemotePortQ . - ".,,' encontra uma porta local diferente para cada significa "obter a porta do cltente . Ou se~a, thread, para que a aplicação possa atender a o número da porta do cliente de ~nde partm vários clientes ao mesmo tempo. a solicitação. Lembre-se: se voce for um servlet, remoto significa cliente.
  • 152. revisão do cicio da vida Revisão: Cielo da vida do servlet e API «inter ace» ·avax.servlet.Servlet service(ServletRequest, ServletResponse) init(ServletConfig) destroyO getServletConfigO o Container inicializa um servlet carregando a getServletInfoO classe, invocando o construtor-padrão do servlet e chamando o método initO do servlet. o método initO (que o desenvolvedor pode j avax.servlet.GenericServlet anular) é chamado apenas uma vez no ciclo service(ServletRequest, ServletResponse) de vida do servlet, e sempre antes do servlet init(ServletConfig) atender a qualquer solicitação do cliente. initO destroyO o método initO dá ao servlet acesso para os getServletConfigO objetos ServletConfig e ServletContext, que o getServletInfoO servlet precisa para conseguir informações sobre getInitParameter(String) a configuração do servlet e a aplicação web. getInitParameterN amesO getServ letContextO o Containertermina com a vida de um servlet log(String) chamando seu método destroyO. log(String, Throwable) o servlet passa a maior parte da sua vida .~. rodando um método serviceO para uma I solicitação do cliente. j avax.servlet.http.HttpServlet service(HttpServletRequest, HttpServletResponse) Cada solicitação para um servlet roda em uma service(ServletRequest, ServletResponse) thread separada! Só existe apenas uma instância doGet(HttpServ IetRequest, H ttpServ IetResponse) para qualquer classe servlet. doPost(HttpServletRequest, HttpServletResponse) doHead(HttpServletRequest, HttpServletResponse) Seu servlet quase sempre estenderá o javax. doOptions(HttpServletRequest, HttpServletResponse) servlet.http.HttpServlet, do qual ele herda uma implementação do método serviceO, que traz um doPut(HttpServletRequest, HttpServletResponse) HttpServletRequest e um HttpServletResponse. doTrace(HttpServletRequest, HttpServletResponse) i doDelete(HttpServletRequest, HttpServletResponse) o HttpServlet estende o javax.servlet.GenericServlet getLastModified(HttpServletRequest) - uma classe abstrata que implementa a maioria dos métodos básicos do servlet. com.wickedlysmart.examples.MyServlet o GenericServlet implementa a interface Servlet. doPost(HttpServletRequest, HttpServletResponse) As classes servlet (exceto aquelas relacionadas myBizMethodO aos JSPs) estão em um dos dois pacotes: javax. servlet ou javax.servlet.http. Você pode anular o método initO e deve anular pelo menos um método de serviço (doGetO, doPostO, etc). 124 capitulo 4
  • 153. solicitação e re::;posta Revisão: HffF e HttpServletRequest Pontos de bala Os métodos doGetO e doPostO do HttpServlet Interface ServletRequest levam um HttpServletRequest e um Uavax.servlet. ServletRequest) HttpServletResponse. <<interfaee> > O método serviceO determina se o doGetO ou ServletReaªesL o doPostO rodará, baseado no método HTTP getAttribute(String) (GET, POST, etc.) da solicitação HTTP. IgetContentLengthO As solicitações POST têm um corpo; as getInputStreamO solicitações GET, não, mas as solicitações getLoealPortO GET podem ter parâmetros anexados à VRL da solicitação (algumas vezes chamada getRemotePortO "query string"). getServerPortO As solicitações GET são idempotentes por getParameter(String) herança (de acordo com a especificação HTTP). getParameter Values(String) Elas devem ser capazes de rodar várias vezes, getParameterNamesO sem causar nenhum efeito colateral no servidor. t As solicitações GET não devem mudar nada no Ii MUITOS outros métodos ... servidor. Mas você pode escrever um método doGetO não-idempotente e maldoso. Interface HttpServletRequest .• O POST é não-idempotente por herança e cabe Gavax.servlet.http. a você projetar e codificar sua aplicação, de HttpServletRequest) forma que, se o cliente enviar uma solicitação I duas vezes por engano, você possa cuidar disso. <<interfaee> > HTTPServletReauest Se um formulário HTML não diz getContextPathO explicitamente "method=POST", a solicitação é enviada como um GET e não como POSTo Se getCookiesO você não possui um doGetO em seu servlet, a getHeader(String) solicitação falhará. getIntHeader(String) Você pode receber parâmetros da solicitação getMethodO com o método getParameter("paramname"). O getQueryStringO resultado é sempre uma String. getSessionO Se você tem múltiplos valores de parâmetros Ii MUITOS outros métodos ... para um determinado parâmetro, use o método getParameterValues ("paramnane") que retoma um array de Strings. Você pode obter outras coisas do objeto solicitação, como headers, cookies, uma sessão, a query string e um stream de dados. você está 125
  • 154. o objeto HttpServletResponse Etrl'ão,essa foi a Solicitação ... vejatMos agora a Resposta A resposta é o que volta para o cliente. Aquilo que o browser recebe, analisa e retribui ao usuário. Tipicamente, você usa o objeto response para conseguir um stream de saída (geralmente um Writer), e você usa este stream para escrever o HTML (ou outro tipo de conteúdo) que retoma para o cliente. Contudo, o objeto response tem outros ! A métodos além do IIO output. Veremos alguns deles yoce usa a com mais detalhes. apenas pata envIal- dad9s interface ServletResponse de volta 9 Gavax.servlet. ServletResponse) Você chama <<interface> > ---_ ServletResonse .. _----------------.-.-----.-----_.--------.----- . __ ... _ ..... __ .... _., resp9sta: setConte.nf7jpei) e etBuiferSizeO setContentTypeO l/I#itJ.ts gefVdtetD. etWriterO DepoIS dIss9>v9cê estadt ~etoutputStreamo etContentLengthO tétZendo sImplesmente 'IMUITOS outros métodos ... pata escl"evet o alg9 mms) no ]tlas Í9cê tamlJém pode a resposta pm-a outt9sheadets. ettOS addCookieO addHeaderO encodeURLO sendErrorO setStatusO sendRedirectO 'IMUITOS outros métodos ... 126 capíitulo 4
  • 155. solicitação e resposta Espere um momento ... Eu pensei que não íamos enviar HTML de um servlet, porque é horrível formatá- 10 para o stream de saída ... o o Usando a resposta para o I/O Tudo bem, deveríamos estar usando JSPs em vez de enviar HTML de volta no stream de saída a partir de um servlet. Formatar um HTML para enfiá-Io no método príntlnO do stream de saída é penoso. Mas isso não significa que você nunca terá que trabalhar com um stream de saída do seu servlet Por que? 1) Seu provedor de hospedagem pode não suportar JSPs. Existem vários servidores e containers mais antigos por aí que suportam servlets, mas não JSPs, então, você fica "preso". 2) Você não tem a opção de usar JSPs por algum outro motivo, como um gerente chato que não permite usar JSPs porque em 1998 seu cunhado lhe dissera que os JSPs eram ruins. 3) Quem disse que HTML era a única coisa que você poderia enviar de volta em uma resposta? Você pode devolver outras coisas em vez de HTML ao cliente. Algo para o qual um stream de saída faça sentido. você está aqui" 127
  • 156. enviando bytes na resposta ItMagit1eque você queira mviar UtMJAR para o cliet1te... Digamos que você tenha criado uma página para downloads onde o cliente pode baixar códigos a partir de arquivos JAR. Em vez de enviar de volta uma página HTML, a resposta contém os bytes representando o JAR. Você lê os bytes dos arquivos JAR e os escreve no stream de saída dos dados da resposta. o Diane está desesperada para fazer o download do J AR com um código do livro que ela está usando para aprender servlets e JSPs. Ela acessa o Container envia a o site do livro e c1ica no link "código o browser envia uma solicitação para o servlet jar", que se refere a um servlet solicitação HTTP para CodeReturn (mapeado para o chamado "Code.do". o servidor com o nome nome "Code.do" no DD) para do servlet requisitado processamento. ("Code.do"). ~ o J AR inicia o download na o servlet CodeReturn recebe máquina do cliente. Diane os bytes para o J AR, recebe da está satisfeita. resposta um stream de saída e copia os bytes representando o J AR A resposta HTTP contém agora oS bytes que representam o J AR. resposta 128 capítulo 4
  • 157. solicitação e resposta o código servlet que faz o dowt1load do JAR Ii um monte de imports aqui public class CodeReturn extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException IJ:S 3Vfl'fll>aS ~ve a/l'tJwsel' ~ I'fccl'Jt.e5Q 3Vf is+o e ClII> response. setContentType ("application/jarU) ; IA;e'" ClII>Ji..-r;!ilAJ ••1'J-ra<1l; Vf"(, J I114Q rr 1Vl.l-;• '" JN Ct:Jl'Jft'iClNI.JMSti +ib{J Je C<1lI'J#tJJe. ServletContext ctx = getServletContext(); pP.N. ~F QppltcU.-hêl1{jal'r, n InputStream is = ctx.getResourceAsStream("/bookCode.jarU); It- . ~ -r' .s..S+e. .lI'; apfl'JlJ.S FI Je-lI>e VII> ••• int read = O; byte[] bytes = new byte[1024]; s+reall> Je el'J+l'aJIJ. pQrlJ. (J n I'f!CClI'Só ct.all>aJa bQâ/<:CI,lJe,jO:I' OutputStream os = response.getoutputstream();) = os.write(bytes, while «read is. read read); != 0, (bytes» -1) { ,J > os. flush(); 1.s+a é a PfAl'# fVI1Jfi.lI>e~aIJ é 1I>4S apel1t1.s ClII> xl tJ S{"II>IpI<!s! I os. close (); lJaJa espectal) S4~el1# lê tiS bj#s Jó JI}Je e 4S escreve PfU'Q tJ de s+l'efi.íJ'l, de sa;Ju. ~(le l1:s CÓl'Jse.5V{"'II1tlS tJtje.+tl respós+a. Não ex'lst~m YerguntLls Idl9télS f: Onde estava localizado o arquivo JAR "bookCode.jar"? Em outras palavras, onde o método getResourceAsStreamO PROCURA para localizar o arquivo? Como você lida com o caminho? I: O getResourceAsStreamO requer que você inicie com uma barra ("t'), que representa a raiz da sua aplicação. Já que a aplicação foi chamada de JarDownload, então a estrutura de diretórios é semelhante à figura. O diretório JarDownload está dentro de webapps (o diretório-pai para todos os outros diretórios da aplicação), e dentro do JarDownload nós colocamos o WEB-INF e o código JAR em si. Assim, o arquivo "bookCode.jar" está situado no nível raiz da aplicação JarDownload. (Não se preocupe, nós entraremos em maiores detalhes sobre a estrutura de diretórios de distribuição quando web.xml chegarmos no capítulo que trata da distribuição.) você está 129
  • 158. tipo de conteúdo Opa. Qual éo problettta COttto tipo do cot1teúdo? Você deve estar surpreso com esta linha: response.setContentType(~application/jar") ; Ou pelo menos deveria. Você tem que dizer ao browser o que você está devolvendo, para que ele possajazer a coisa certa: abrir uma aplicação "assistente", como um leitor PDF ou um player de vídeo, criar um HTML, salvar os bytes da resposta como um arquivo de download, etc. E já que você está aí se perguntando, sim, quando nós dizemos tipo do conteúdo, queremos dizer a mesma coisa que tipo MIME. O tipo do conteúdo é um header HTTP que deve ser incluído na resposta HTTP. Caramba, obrigado Servidor. É gentil de sua parte me informar que tipo você está enviando de volta. Voudeixar o Quicktime player pronto para o vídeo... D o Tipos MIME comuns: text/html application/pdj video/quicktime application/java image/jpeg application/jar appl ication/octet-stream Servidor/ Container application/x-zip Você não precisa memorizar um monte de tipos do conteúdo. o Você deve saber o que o setContentTypeO jaz e como usá-lo, mas você o não precisa saber nem mesmo os mais comuns tipos de conteúdo, exceto o text/html. O que você precisa saber sobre o setContentTypeO .laxe geralmente é de senso comum ... por exemplo, não será bom para você mudar o tipo de conteúdo DEPOIS de ter escrito o que vai para o stream de saída da resposta. Óbvio. Isso quer dizer que você não pode configurar um tipo de conteúdo, escrever algo e, em seguida, mudar o tipo de conteúdo e escrever outra coisa. Pense um pouco: como o browser lida com isso? Ele só pode tratar um tipo de COISA da resposta de cada vez. Para ter certeza de que tudo junciona bem, o que você deveria jazer (e em alguns casos é um requisito) é sempre chamar o setContentTypeO primeiro, ANTES de chamar o método que gera o stream de saída (getWriterO ou getOutputStreamO). Isto garantirá que você não terá conflitos entre o tipo de conteúdo e o stream de saída de dados. 130 4
  • 159. solicitação e res:po,sta Nã.9 eXIstem ferh'untélS idl9télS r: Por que você tem que definir o tipo de conteúdo? Os servidores não podem descobrir r: Espere um segundo ... por que você precisaria usar um servlet para enviar de volta isso a partir da extensão do arquivo? aquele arquivo JAR, quando você pode ter o servidor enviando-o como um recurso? Em outras palavras, por que não fazer com que o 1:A maioria dos servidores pode, para conteúdo usuário clique em um link que vá para o JAR estático. No Apache, por exemplo, você pode em vez do servlet? O servidor não pode ser configurar os tipos MIME mapeando a extensão configurado para enviar o JAR diretamente do arquivo (.txt, .jar, etc.) para um tipo de conteúdo sem sequer PASSAR pelo servlet? especifico, e ele usará isso para configurar o tipo de conteúdo no header HTIP. Mas estamos falando sobre o que acontece dentro de um servlet 1: Sim. Boa pergunta. Você PODERIA quando NÃO HÁ nenhum arquivo! É você quem configurar o servidor de forma que o usuário está enviando de volta a resposta; o Container não dique em um Iink HTML que o leve, digamos, ao tem idéia do que você está enviando. arquivo JAR localizado no servidor (assim como qualquer outro recurso estático, como JPEGs e r: E com respeito ao último exemplo onde você lê um arquivo JAR? O Container não arquivos de texto), e o servidor simplesmente o enviaria na resposta. Mas ... estamos considerando que você tenha pode ver que você está lendo um JAR? outras coisas que queira fazer no servlet ANTES de enviar de volta o stream. Você pode, por exemplo, precisar que a lógica no servlet que 1: Não. Tudo o que fizemos do servlet foi defina qual arquivo JAR a enviar. Ou você pode ler os bytes de um arquivo (por acaso era um estar devolvendo bytes que você esteja criando arquivo JAR), e escrever de volta esses dados ali mesmo, na hora. Imagine um sistema em que para um stream de saída. O Container não faz você recebe parâmetros do input do usuário e os idéia do que fazíamos quando líamos aqueles usa para gerar dinamicamente um som que você bytes. Pelo o que ele saiba, nós estávamos lendo devolve. Um som que não existia antes. Ou seja, a partir de um tipo de informação e escrevendo um arquivo de som que não se encontra em lugar algo completamente diferente na resposta. algum no servidor. Você acaba de criá-Io e agora está enviando-o na resposta. r: Como eu posso descobrir tipos comuns de conteúdo? quais são os Então você está certo, talvez o nosso exemplo de enviar apenas um JAR localizado no servidor seja meio manjado, mas por favor ... use sua imaginação e enfeite-o com tudo aquilo que você puder adicionar para torná-Io um servlet 1: Faça uma busca no Google. Sério. Novos de verdade. Talvez seja algo tão simples como tipos MIME estão sendo adicionados todo o tempo, inserir um código no seu servlet que - junto mas você pode encontrar facilmente listas na Web. com a devolução do JAR - escreva alguma Você também pode dar uma olhada nas suas informação no banco de dados sobre este preferências do browser por uma lista daqueles que usuário em particular. Ou talvez você tenha que foram configurados para seu browser, e também pode checar para ver se ele está liberado para fazer o checar seus arquivos de configuração. Novamente, download deste JAR, baseado em alguma coisa você não precisa se preocupar com isto para o exame que você tenha detectado no banco de dados. e provavelmente não lhe causará muito estresse no mundo real também. você está 131
  • 160. printWriter e OutputStream Você tetM duas opções para saída: caracteres ou bytes Isto é apenas um simples java.io, exceto pela Íllterface ServletResponse que oferece apenas duas opções de streams para escolher: ServletOutputStream para bytes ou PrintWriter para dados em caracteres. ~ Printwriter Exemplo: PrintWri ter wri ter = response .AnUtmm Você DEVE memorizar estes writer.'.ff''''p(''sorne text and HTML"); métodos Usado para: Você tem que saber isso para o exame. E é uma armadilha. Repare que para Exibir dados de texto para um stream de caracteres. escrever para um ServletOutputStream Embora você ainda possa exibir dados em caractere você writeO,porém, para escrever usando o OutputStream, é ele que você utilizará para para um PrintWriter você ... printlnO! tratar seus dados em caractere. É comum considerar que você escreve para um escritor, mas não. Se você já usa o java.io, já passou por isso. Se não, lembre-se: printlnO para um PrintWriter ~ OutputStream writeO para um ServletOutputStream Exemplo: E não se esqueça de que os nomes dos métodos para obter o stream ou o escritor ServletOutputStream out response. perdem a primeira palavra, conforme getOutputStream() segue: ServletOutputStream out·CiiIII(aByteArray) ; response.getOutputStream() Pr:intWriter Usado para: response.getWriter() Escrever qualquer outra coisa! Você precisa reconhecer nomes FALSOS, como: er() " ream () er () l ís.f.es AJj,O ) exts.f.elPof Para 5va Ii1{tif'lrla{it:;; f) fi,iÍ'IWf'i+ef' PIaverdade e~ac{j.fa {j 5ef'lI!e+ov.fpv.f.5.frealrl. Ov s!i"J t:;f1.1),Wrl.f.et' +elrl vlrla t'e{et'~âà pua til Set'lIle+ov.fpv.f.5.ft'ealrl e de1eja t:;s ct.alYladaspat'a ele. trpei1tJ.s vJl1. s.frefJ.1Pl e sfJ.fdade "adas v"l.f.a para a c1te~J d IrlQS(j PrI),-ANt't.f.et' (J elYlbe1ejatkdlct<;I1QJ1da lYIé.f.ad()sde 4/.f.<;J1:vel Ctlf4j'!S de .f.t'l'J..f.fJ.t' Cl'J.f'ac+eres, as 132 4
  • 161. soliCitação e res.:posta Você pode configurar headers de resposta, você pode adicionar headers de resposta E você pode querer saber qual é a diferença. Mas pense nisso por um segundo e faça o exerCÍcio. Correlacione a chamada ao Trace uma linha do método HttpResponse para o seu comportamento. método com o seu comportamento Nós fizemos o mais óbvio para você. Adiciona um novo header e um novo valor na response. setHeader (ftfoo", ftbar"); resposta, ou acrescenta um outro valor para um header existente. Um método de conveniência que substitui o valor response.addHeader(ftfoo", ftbar"); de um header existente por seu valor integral, ou acrescenta um novo header e um novo valor na resposta. Se um header com este nome já existir na response. setlntHeader (ftfoo", 42); resposta, o valor é alterado por este. Ou então, acrescenta um novo header e um novo valor na resposta. Bem fácil quando você os vê todos juntos. Mas para a prova, você deve memorizá-Ios, pois se na próxima terça-feira o cara no final do corredor perguntar: "Qual é o método de resposta que me permite acrescentar um valor para um header existente?", você possa dizer, sem pestanejar: "É o addHeader, e ele possui duas Strings, para nome e valor." Assim mesmo. O setHeaderO e o addHeaderO acrescentarão um header e um valor na resposta, se o header (o primeiro argumento para o método) ainda não estiver lá. A diferença entre configurar e adicionar aparece quandô o header está lá. Nesse caso: setHeaderO sobrescreve o valor existente addHeaderO adiciona um novo valor Quando você chama o setContentType ("text/html"), você está configurando um header como se dissesse: setHeader("content-type", "text/html"); Então, qual é a diferença? Nenhuma ... considerando que você digite corretamente o header "content-type". O método setHeaderO não vai reclamar se você escrever errado o nome dos headers - ele simplesmente acha que você está adicionando um outro tipo de header. Porém, algo dará errado lá na frente, já que agora você não configurou corretamente o tipo de conteúdo da resposta! você está 133
  • 162. redírecionando a Mas algutMas vezes você tMestMO não quer lidar COtMa resposta ... Você pode decidir que algo diferente trate a resposta para a sua solicitação. Você pode ou redirecionar a solicitação para uma URL completamente diferente, ou despachá-Ia para algum outro componente da sua aplicação (geralmente um JSP). Redirecionando o no cliente digita uma URL O browser ... e servidor/Container para o A solicitação vai 8 O servlet decide que a solicitação deve ir para uma URL completamente diferente. e / e O browser recebe a resposta, vê o código de status "301" e procura o por um header "Location" O servlet chama o sendRedirect(aString) na resposta e pronto i i .•.•... I I! :•,{y. .. li A resposta HTTP possui um código de status "301" e um header "Location" contendo uma URL como valor 134 4
  • 163. solicitação e resposta oo browser faz uma nova solicitação usando a URL que representava e o o valor do header "Location" na Não há nada de exclusivo O servidor recebe resposta anterior. O usuário na solicitação, ainda que ela o que consta na pode notar que a URL na barra de tenha sido ativada por um URL solicitada. endereços do seu browser mudou... redirecionamento Nada de e?pecial aqUi •A resposta HTIP é igual a qualquer outra resposta ... exceto pelo fato de que ela não vem o do local que o cliente Cl digi!ou ~ O browser exibe a nov página. O usuário fica maravilhado Ifr você está 135
  • 164. redirecionamento do serviet o redireciotlatltettto do Servlet faz o browser trabalhar o redirecionamento deixa o servlet completamente aliviado. Após perceber que ele não poderá desempenhar o trabalho, o servlet simplesmente chama o método sendRedirectQ: if (worksForMe) { Ii trata a solicitação else { response.sendRedirect{ •• ttp://www.oreilly.com h •• ); I Ir f//t.L 3l1e' vócê alieI' 3l1e' ~ ;;1'i)wst:1' lIse piAl'a a sõliér+#.fíia. í lssa ., clte"h vê Usatldo URLs relativas tiOsetldRedirectO Você pode usar uma URL relativa como um argumento para o sendRedirectO, em vez de especificar o endereço completo ''http://www ...''. As URLs relativas vêm em dois sabores: com ou sem a barra ("/") inicial. Imagine que o cliente digitou primeiramente: http://www.wickedlysrnart.com/rnyApp/cool/bar.do f) CÓ"+fJ,IPíf!1' sde Q chama o sendRedirectO com a URL relati a que NtO inicia lÂe s.:;llCl+fJ.jíilJi lJil'lj'Pít:! com a barra: I IÂtJ Ct:iJJ'l/Pít...:; ~fJrpplca6/~ 'I I Quando sendRedlrect{"foo ao servlet Cha'tadO "b~.dO", ele a solicitação chega stuff.htrnl'); I ptll'+rt,,,+tI; se ve..cê "íie.. lIStAl' tA blJ,l'l'IJ" f!S+fJ.PIJ,I'+t tia " J IU::I'íf!sce,,+aJa Je o header "Location" que ele coloca na res10sta H TP), relativa à URL da solicitação completa O Container constrói a URL inicial: p1 (elIreCisr'dela http://www.wickedlysrnart.com/rnyApp/cool/foo/ para stuff.htrnl Mas se o argumento para o sendRedirectO INICIAR com a barra: sendRedirect ("/foo/stuff .htrnl");~ fJr 1141'1'1II;"ó CÕIl'lf!jÕ O Container constrói a URL completa relativa ao container l'eItJ.+ivlJ. ~ 1'11I;1'5 Jó web em si, em vez de relativa à URL original da solicitação. Assim, a nova URL será: http://www.wickedlysrnart.com/foo/stuff.htrnl I 1 "fila" e illI'I Ilpllct!l.-h·Vf) WebJ sep4N.Jõ JIJ ti.fllca-h·V6 web "~fJrpp". 136 C81PítlJlo4
  • 165. solicitação e resposta Você não pode fazer um sendRedirectO depois de escrever a resposta! Isto provavelmente é óbvio, mas é a LEI e nós estamos apenas ratificando. Se você procurar o sendRedirectO na APL você verá que ele envia uma IllegalStateException se você tentar chamá-Io depois "da resposta já ter sido criada". Eles querem dizer com "criada" que a resposta foi enviada. Isso significa que os dados foram enviados para o stream. Na prática, significa que você não pode escrever na resposta e depois chamar o sendRedirectO! Mas um professor exigente diria que, tecnicamente, você pode escrever no fluxo de dados sem que haja oflush, e o sendRedirectO não geraria uma exceção. Mas isto seria algo completamente estúpido e, por isso, não vamos tocar no assunto. (Se bem que ... acabamos defalar. ..) No seu servlet, decida, pelo amor de Deus! Ou o sendRedirecto Carrega um o . trate a solicitação, ou faça um sendRedirectO String e NÃ bJeto para que OUTRA entidade a trate. URL' O uma (Aliás, este papo de "uma vez enviada, já em l • , e e carreo: era" também se aplica à configuração de 'RL oa uma Str' . . A questão é. o zng que E uma headers, cookies, códigos de status, o tipo de rrega um objet' À se,!dRedirectO NA-O conteúdo e assim por diante ...) ssap ara ele um ttO tzpo U'RL• Vr o C' • . oce A a Dtrzng completa ou l' que e uma P Utter trans+orm atzva . S.e o Container À re -, nUma URL '.Jl ar uma U'RL I.Z legalStat E complet. a, e l e manda relativa l e Xceptzon O uma embrar que ISTO" que confunde é send'Red'zrect/T T'RL errado' . e Com '')11:/ ! v, nova("htt· 'P.//www.oreilly. IL 137
  • 166. requesf dispatch o request dispateh aeottteee no lado do servidor E esta é a grande diferença entre um redirecionamento e um request dispatch - o redirecionamento faz o cliente executar o trabalho, enquanto que o request dispatch faz com que outro componente no servidor execute o trabalho. Então, lembre-se: redirecionamento = cliente, request dispatch = servidor. Nós falaremos mais sobre o request dispatch mais adiante, porém, estas duas páginas deverão dar a você uma noção dos pontos mais importantes. o Request Dispatch • O usuário digita a URL do servlet no seu browser .. e A solicitação vai para o servidor/Container e O servlet decide que a solicitação deve ir para outra parte da aplicação . (neste caso, um JSP) O browser recebe a resposta normalmente e a entrega ao usuário. o O servlet chama RequestDispatcher view ~ . Já que a barra de endereços do request.getRequestDispatcher(~result.jspn); browser não mudou, o usuário não view.forward(request,response); sabe que foi o JSP que gerou a e o JSP cuida da resposta resposta. í r . f f ,t.~, I i 138 4
  • 167. solicitação e res:J)osta RedirecionatMet1to X Request Uispateh Oi Kari, aqui é o Dan... Eu quero a sua ajuda com um cliente. Vou encaminhar para você os detalhes de como retornar para ele, mas eu preciso que você cuide disso agora. Sim. eu SEI que você também tem suas necessidades ... sim, eu SEI como a View é importante para o MVC ... não, eu não creio que consiga outro JSP como aquele ... o quê? Não entendi? A ligação está ruim . desculpe ... eu não consigo ouvir nada . Redirecionamento perdendo pacotes ... Quando um servlet faz o Request request dispatch, é como se Dispatch pedíssemos que um colega de trabalho cuidasse de um cliente. O colega de trabalho acaba respondendo ao cliente, mas o cliente não se importa, desde que alguém o responda. O usuário nunca sabe que outra pessoa assumiu o controle, pois a URL no browser não muda. Quando um servlet faz um redirecionamento, é como se pedíssemos que o cliente ligasse para outra pessoa. Neste caso, o cliente é o browser, e não o usuário. O browser faz a nova chamada em benefício do usuário, depois do servlet que foi originalmente requisitado dizer: "Desculpe, chame este cara aqui. ../1 O usuário vê a nova URL no browser. você está 139
  • 168. revisão do HttpServietResponse Revisão: HttpServletRespo"se Você usa a Resposta para enviar dados de volta para o cliente. Os métodos mais comuns que você chamará no objeto response (HttpServletResponse) são o setContentTypeO e O getWriterQ. Tome cuidado - muitos desenvolvedores acreditam que o método seja getPrintWriterO, mas é getWriterO. interface ServletResponse O método getWriterO permite fazer I/O por caractere para (javax.servlet.ServletResponse) criar o HTML (ou algo mais) para o stream. <<interface> > Você também pode usar a resposta para configurar headers, ServletReslJonse enviar erros e adicionar cookies. getBujJerSizeO No mundo real, você provavelmente usará um lSP para enviar a maioria das respostas HTML, mas você ainda poderá usar um stream de resposta para enviar dados binários (como um arquivo lAR, talvez) ao cliente. getOutputStreamO setcon.tentTypeo getWriterO 3 setContentLengthO O método que você chama na sua resposta para receber um II MUITOS outros stream binário é getOutputStreamO. métodos,,, O método setContentTypeO diz ao browser como tratar os dados vindos na resposta. Os tipos de conteúdos mais comuns são "text!html", "application/pdf' e "image/jpeg". I••"faee ll,,!rvle'RcsPonsc Você não precisa memorizar os tipos de conteúdos (também Oavax.servlet.http. conhecidos como tipos MIME). HttpServletResponse) • Você pode configurar headers de resposta usando o ~~. < < interjace > > ~ .~ addHeaderO ou o setHeaderO. A diferença depende de o addCookieO headerjá fazer palie da resposta. Se já fizer, o setHeaderO irá substituir o valor, mas o addHeader acrescentará um addHeaderO valor adicional à resposta existente. Se o header ainda não encodeURLO fizer parte da resposta, então o setHeaderO e o addHeaderO sendErrorO comportam-se exatamente do mesmo modo. setStatusO sendR.edirectO Se você não quiser responder a uma solicitação, você pode l/MUITOS outros métodos ... redirecionar a solicitação para outra URL. O browser encarregar" se-á de enviar a nova solicitação para a URL que você fornecer. Para redirecionar uma solicitação, utilize o sendRedirect( aStringURL ) na resposta. Você não pode chamar o sendRedirectO após a resposta ter sido gerada! Ou seja, se você já escreveu alguma coisa para o stream, é muito tarde para fazer um redirecionamento. Um redirecionamento de uma solicitação é diferente de um dispatch. O request dispatch (mais detalhado em outro capítulo) acontece no servidor, enquanto que um redirecionamento ocorre no cliente. No caso do dispatch, a solicitação é entregue para outro componente no servidor, geralmente na mesma aplicação. Um redirecionamento simplesmente informa ao browser para ir para uma URL diferente. 140 capítulo 4
  • 169. solicitação e feSJIIllII fausa pata 9 café 7e4tep~-e~·4 1Como o código do servlet de um método service (por exemplo, doPost () ) obteria o valor do header "User-Agent" da solicitação? (Escolha todas as que se aplicam.) [J A. String userAgent = request.getParameter(~User-Agent") ; [J B. String userAgent = request.getHeader(~User-Agent"); [J C.String userAgent = request.getRequestHeader(~Mozilla"); [J D.String userAgent = getServletContext() .getInitParameter(~User-Agent"); 2 Quais são os métodos HTTPusados para mostrar ao cliente o que o servidor está recebendo? (Escolha todas as que se aplicam.) [J A. GET [J B.PUT [J C. TRACE [J D.RETURN [J E. OPTIONS 3 outra URL? do HttpServletResponse Qual método é usado para redirecionar uma solicitação HTTP para [J A. sendURL () [J B. redirectURL () [J C. redirectHttp () [J D. sendRedirect() [J E. getRequestDispatcher () você está aqui" 14
  • 170. teste 4 Quais os métodos HTTP que NÃO são considerados idempotentes? (Escolha todas as que se aplicam.) o A.GET O B. POST O C.HEAD O D.PUT 5 Sendo req um HttpServletRequest, qual das alternativasrecebe um stream de entrada de dados binários? (Escolha todas as que se aplicam.) o A. BinaryInputStream s = req.getInputStream(); O B.ServletInputStream s = req.getInputStream(); O C.BinaryInputStream s = req.getBinaryStream(); O D.ServletInputStream s = req.getBinaryStream(); 6 Como você configuraria um header chamado "CONTENT -LENGTH" no objeto HttpServletResponse? (Escolha todas as que se aplicam.) o A.response.setHeader(CONTENT-LENGTH,"1024"); O B.response.setHeader(~CONTENT-LENGTH","1024"); O C.response.setStatus(1024); O D. response.setHeader(~CONTENT-LENGTH",1024); t Escolha o trecho do código do servletque recebe um imagem, ou outro tipo binário,no HttpServletResponse. stream binário para escrever uma o A. java.io.PrintWriter out response.getWriter(); O B.servletOutputStream out response.getOutputStream(); O C. java.io.PrintWriter out new PrintWriter(response.getWriter(»; O D.ServletOutputStream out = response.getBinaryStream(); 142 4
  • 171. solicitação e respQSia 8 Quais métodos são usados por um servlet para tratar os dados do formulário vindos de um cIieoIe? (Escolha todas as que se aplicam.) o A. HttpServlet.doHead() O B. HttpServlet.doPost() O C.HttpServlet.doForm() O D. ServletRequest.doGet() O E.ServletRequest.doPost() O F.ServletRequest.doForm() 9 Quais dos seguintes métodos são declarados no HttpServletRequest ao contrário do ServletRequest? (Escolha todas as que se aplicam.) o A. getMethod () O B. getHeader () O C. getCookies () O D. getInputStream() O E. getParameterNames () 10 Como os desenvolvedores de servlet devem tratar o método service () do HttpServlet quando estenderem o HttpServlet? (Escolha todas as que se aplicam.) o A. Eles devem anular o método service () na maioria dos casos. O B. Eles devem chamar o método service () do doGet () ou doPost () . O C. Eles devem chamar o método service () do método init () . O D. Eles devem anular pelo menos um método doXXX (como um doPost () ). () você está aqui ~ 143
  • 172. respostas do teste 'fausa pata 9 caté íe~-~4 1Como o código do servlet de um método service (por exemplo, doPost () ) obteria o valor do header "User-Agent" da solicitação? (Escolha todas as que se aplicam.) o A. String userAgent = • O request.getParameter("User-Agent"); B. String userAgent = request. getHeader ("User-Agent") ; C. String userAgent = -If óp{i<I!J lj lfJ!<l!Js.f.I"GI. a chalfJ!tl.Ja ct:Jl"l"e-/-a at:J II'~.f./J#(~~ye passa ô request.getRequestHeader("Mozilla"); «6 "76<9e t.eaJel" C"1fJ!6 o D. String userAgent = tlII' p41"~e.f.l"fJ S.f.I"I~5' getServletContext().getlnitParameter("User-Agent"); :2 Quais são os métodos HTTP usados para mostrar ao cliente o que o servidor está recebendo? (Escolha todas as que se aplicam.) o A. GET (C.~. I tJ, J <9e.f."J(J$ rrrrr.J Ii.o. O B. PUT ~ C. TRACE <9~.f.(JJ(J lISfJ.Je.hpié4<9ft"7.f.ep4NJ. ~ O D.RETURN e "7';" pIJ.NJ.PI"(J«Yj';'" O E.OPTIONS .3 Qual método do HttpServletResponse é usado para redirecionar uma solicitação HTTP para outra URL? o A. sendURL () O B. redirectURL () cól"l"e+a e d6$ 1fJl~.f.(J«t'I$ O C. redirectHttp () "76 l1#pSel"'il1e+/Cesp6i'1$f!. ~ D. sendRedirect() O E. getRequestDispatcher () 144 car)ituio 4
  • 173. solicitação e resposta 4 Quais os métodos HTTP que NÃO são considerados idempotentes? (Escolha todas as que se aplicam.) o A.GET ~ B. POST - ~r áesijl'lJ c posrJeve cc~Jv·t/t. as Scli'cí'-hs':es ftu'a O C.HEAD fl.fva/ljfJ.r" AI es..f.fl.tlõ.16 serlll«6r. , í", 5era/; fi."'es"'t< a.+VfJ.li'jtií46 O D.PUT ~ac áeve ser apllcaÀa.varias vejes. 5 Sendo req um HttpServletRequest, qual das alternativas recebe um stream de entrada de dados binários? (Escolha todas as que se aplicam.) o A.BinaryInputStream s = req.getInputStream(); !iir B. ServletInputStream s = req.getInputStream(); -1Jr ep{i6 ~ eSfect/tca ó O C. BinaryInputStream s = req.getBinaryStream(); ",é.fcJc e c+ipc Je re+iJrl'l" O D.ServletInputStream s = req.getBinaryStream();C6rre+cs. 6 Como você configuraria um header chamado "CONTENT-LENGTH" no objeto HttpServletResponse? (Escolha todas as que se aplicam.) (A-PI) o A. response. setHeader (CONTENT-LENGTH,"1024") A- "f54" ~ II'!tls..f.ra ; - IJ, !iir B. response. setHeader ("CONTENT-LENGTH" ,"1024") itfI41'1elraC6rre..f.a lÃeCÓI'1/i5t1Na.r O C. response. setStatus (1024) ; VIPo t.eo.lÃer C"1Po I/rrp J!)l); O D. response. setHeader ("CONTENT-LENGTH" ; po.rlJ.lPof:'"f"NJSJ • ,1024) .•.•_ J. .s-rr1I'1jS; VII'! represel'1+lIIl'1tl" ., 1'1t1lPoe Je. t.ef<Àer) e ., llv+r<!J) <!Jaler. v 1 Escolha o trecho do código do servlet que recebe um stream binário para escrever uma imagem, ou outro tipo binário, no HttpServletResponse. o A. java.io.PrintWriter out = response.getWriter(); -A- ~ B.ServletOutputStream out = response.getOutputStream(); O C.java.io.Printwriter out = fS+: l"'cl:Jl"re+a) new PrintWriter(response.getWriter(»; p(Jl"~ve e/fi.lisa O D.ServletOutputStream out = response.getBinaryStream(); II~ fi.1.,,-PNl"l+er 4rren+o.JIJ f6r C4f'itc+ere. j> 145
  • 174. respostas do teste 8 Quais métodos são usados por um servlet para tratar os dados do formulário vindos de um cliente? (Escolha todas as que se aplicam.) o A. HttpServlet.doHead() ~ B. HttpServlet.doPost() - A-s Ófj';eS C e F es-l-';c er;'fJ.dUJ fórafJe O C.HttpServlet.doForm() es-hs Irt:J.Ófi6S ,,';c exi's-hlrt. O D. ServletReques t. doGet () O E.ServletRequest.doPost() O F. ServletRequest. doForm () 9 Quais dos seguintes métodos são declarados no HttpServletRequest ao contrário do servletRequest? (Escolha todas as que se aplicam.) A. getMethod () B. getHeader () C. getCookies () - A-s 6fj';eS A-; 8 e C relereli?l- se QóSclJIPIfl)'Ie"ffs D. getlnputStream() fie fJIi?I4 scltet-l-4j';6 Hrrp' E. getParameterNames () 10 Como os desenvolvedores de servlet devem tratar o método service () do HttpServlet quando estenderem o HttpServlet? (Escolha todas as que se aplicam.) o A. Eles devem anular o método service () na maioria dos casos. -~ O B. Eles devem chamar o método service () do doGet () ou doPos t () . O C. Eles devem chamar o método service () do método ini t () . ~ D. Eles devem anular pelo menos um método doXXX() (como um dopost(». -I} I)f]';ó b es-I-~ córN~-I-tJ.. s Je.se"vlJlveJares O 5erl3.lli?Ie,,-h fJSO,Irt 6S lrté-l-6fiós dóbe+o e J6fAS-I-(). 146 capitulo 4
  • 175. Sendo uma Aplicação Web Você tem que entender como as partes de uma aplicação interagem e deve respeitar as threads. Se você se sair bem nos testes preparatórios deste capítulo, eu pouparei a sua vida. o / Nenhum servlet vive sozinho. Nas aplicações web atuais, vários componentes trabalham em conjunto por um objetivo. Temos os modelos, os contraladores e as views. Temos os parâmetras e os atributos. Temos as classes helper. Mas, como juntar os pedaços? Como permitir que os componentes compartilhem informações? Como você oculta informações? Como você toma uma informação thread-safe? Sua vida pode depender destas respostas. Portanto, certifique-se de que você tenha bastante chá quando for ler este capítulo. E que não seja aquela erva descafeinada detestável. este é um novo cai'Jftl1Io~ 147
  • 176. objetivos do exame oficial da Sun o~ s o Modelo do Cotttait1er Web Notas sobre a Abrangência: Todos os objetivos desta seção serão totalmente abordados neste capitulo, exceto o 3.3, que será 3.1 Para os parâmetros de inicialização do servlet abordado no capitulo que trata dos Filtros. e do ServletContext: eserevero código servlet para acessar os parâmetros de inicialização e A maioria dos assuntos deste capitulo aparecerá criar os elementos do deployment descriptor em outras partes do livro, mas se você for fazer a para declarar os parâmetros de inicialização. prova, é AQUI que esperamos que você aprenda e memorize os objetivos. 3.2 Para os atributos de escopo básicos do servlet (solicitação, sessão e contexto): escrever o código servlet para adicionar, processar e remover os atributos; dado um determinado cenário, identificar o escopo adequado para um atributo e as questões relacionadas a multi-threading em cada escopo. 3.3 Descrever os elementos do modelo do ./ íXpliCfí.dó 111) Cfí.p':lvle. Sue container para o procf:ssamf:nto de<; L___ .fr/J..f.ti.sóbre I)S Fn.frfJs. solicitações: Filtro, cadeia de Filtros, wrappf:rs para solicitação e resposta e recursos Web (sf:rvlet ou página JSP). / 3.4 Descrever o ciclo de vida do Container para solicitações, sessões e aplicações web; criar e configurar classes de listener para o ciclo de vida do escopo; criar e configurar as classes listeners para o ciclo de vida de cada escopo e, dado um cenário, identificar o atributo de listener adequado para o uso. 3.5 Descrever o mecanismo RequestDispatcher; escrever o código servlet para criar um request dispatcher; escrever o código servlet para encaminhar ou incluir o recurso desejado; e identificar os demais atributos do escopo request fornecidos pelo container para o recurso desejado. 148 capítulo 5
  • 177. atributos e fisteners Eu quero que meu endereço de e-mail apareça na página das cervejas que o meu servlet cria ... mas acho que ele vai mudar e eu não quero ter que recompilar meu servlet só para alterar isso ... o a 0 Kith quer co•.•igurar seu e-thail •.• UU, e f •.• o escrevê-Io detttro da classe servlet ã Eis o que Kim não quer em seu servlet: PrintWriter out = response.getWriter(); out.println(Uplooper@wickedlysmart.comV); É melhor que ele coloque seu e-mail no Deployment Descriptor (arquivo web.xml), para que, ao distribuir sua página, o servlet possa, de alguma forma, "ler" o seu endereço de e-mail a partir do DD. Assim, ele não terá que fazer um hard-code do seu e-mail dentro da classe servlet. Quando quiser alterá-Io, basta modificar apenas o arquivo web.xml, sem ter que mexer no seu código servlet original. você está Ií" 149
  • 178. parâmetros init Os Parâtttetros lt1it dão uttta for~ Você já viu os parâmetros de solicitação que podem vir no doGetO ou doPostO, mas os servlets também podem conter parâmetros de inicialização. Ao ~ce especi'fi'clJ. li"" pD.f'IJ.""-I/ID.""f!e li"" plJ.f'IJ.""-1I4Il1e. Si'''''P1es; bas+1J. +er cef'+e;14 Je aye eS~14 No arquivo DD (web.xml): J)ílJr;eo dó ele""elf+ó <'sf!f'vle+> lfiJ J)J). <servlet> ~ <servlet-name>BeerParamTests</servlet-name> <servlet-class>TestlnitParams</servlet-class> <init-param> <param-name>adminEmail</param-name> <param-value>likewecare@wickedlysmart.com</param-value> </init-param> </servlet> No código servlet: out.println(getServletConfig() .getlnitParameter(~adminEmail"»); t 150 5
  • 179. atributos e lísteners Você t'lão pode usar os parâtMetros it'lit do servlet setMque ele teKha sido it'licializado Você acabou de aprender que seu servlet herda o getServletConfigO; portanto, você pode chamá-Io de qualquer método do servlet para conseguir uma referência ao ServletConfig. Uma vez que você tenha uma referência ao ServletConfig, você pode chamar o getInitParameterO. Q..uand9 9 C9ntalnet Mas, lembre-se, você não pode chamá-Io direto do seu construtor! A vida do servlet está apenas começando ... In'ldq11za um setvlet~ ele não terá toda a sua funcionalidade até que o Container "CJ f o chame o initO. c9nstt91 um UnIC9 SetvletC9nllg Péltétele. O C9ntVnel' ~·le~'9S IJ/f/)/f de Set"v1e-!-CIJ'7fij péltâmett9s ln'lt d9 setvlet pót" e'71//lJ.dlJ. I4vt-l-6 eedIJ••-----:::; éti:tétvésd9 DD e 9S I <ti construtor í 4'f.Vl 'f.lIe IJ set"vle-r ,,6-n::IJt--7.lt li 1J1 I!. .. . (S I C fi) erv et on 9 destroyO PétSSét t9 SetVletC9nllg. é IJ sell 6!jdIJ Em seguldq~ passa 9 Sel"vle-!-C6'7fij SetvletC9nllg pélta 9 mét9d9 InltO do set,let. fi""'" • se;V1e+ e·••• ·· f sQ( t"IJd4t" IJSIJté-/-lJdlJs sel"vi"]IJ~ de (dIJbe+oJ dIJR.s+oJ de)J ele t"eeebe lIIJt Set"vle-!-ClJ'7flj Nã9 ex'Istem fetbuntélS Ídl9tél5 f: Lá no capítulo anterior você disse que um servlet requer DUAS coisas para tornar-se um I: Nós não dissemos que o initO carrega um ServletConfig porque aquele que você anula servlet válido e fez-wearing. Você mencionou não carrega um. Sua superclasse inclui duas o ServletConfig e um tal de ServletContext. versões do initO: uma que traz um ServletConfig e uma versão de conveniência que é padrão. O método init(ServletConfig) que foi herdado I: Tudo bem, sim, vamos falar sobre o chama o método-padrão initO. Assim, o único que você precisa anular é o da versão-padrão. ServletContext dentro de algumas páginas. Por enquanto, vamos ver só o ServletConfig, pois é aí que você especifica os parâmetros init do seu Não há regra que o impeça de anular aquele servlet. que carrega o ServletConfig, mas se quiser FAZER isso, é melhor que você chame o supero f: Espere um pouco! No capítulo anteríor você disse que podíamos anular o método init(ServletConfig)! Porém, realmente NÃO há razão para que você queira anular o método init(ServletConfig), já que você terá sempre o initO e ninguém disse uma palavra sequer seu ServletConfig chamando o método herdado sobre o argumento ServletConfig! getServletConfigO· você está aqui ~ 151
  • 180. parâmetros inít do servlet Os parâtltetros itlÍf do servlet são lidos apetlas UMA VEZ: quatldo o Cotrtaitler itlicializa o servlet Quando o ContaÍner cria um servlet, ele lê o DD e cria os pares nome/ valor para o ServletConfig. O ContaÍner nunca lê os parâmetros init novamente! Uma vez que os parâmetros estão no ServletConfig, eles não serão lidos novamente até que (ou a menos que) você recrie o servlet. Pense nisso. 00 Container lê DeploymentosDescriptor O para este serv/et, incluindo eo Container cria uma nova instância ServletConfig para este servlet parâmetros init «init-param» new lê web.xml 80 Containerpara cadapar de Strings do nome/valor cria um parâmetro init eo Container dá ao ServletConfig as referências para os parâmetros init servlet. Considere que temos apenas um. nome/valor ~ new string Lnew eo Container cria uma nova instância da classe servlet eo Container chama o método initO do servlet, passando a referência para o ServletConfig >c/new ~ r•••••..•••..•.•instância de J~ontqihej ·v·•.•• >. MyServlet.class Servlet- Config string ~ init(ServletConfig)) instância de MyServlet .class 152
  • 181. atributos e listenets Mas é bem melhor que colocá-Io na fonte do meu servlet. Tudo que eu tenho a fazer é alterar o xml e pressionar o botão "redistribuir", e o novo e-mail estará no ServletConfig o o f ethuntas Idl9tas Nã() exlstliom inteiras sem reinicializá- r: Então, bem, onde está este tal botão r: É claro que é fácil encerrar e reinicializar o 10. Em um ambiente de produção, é assim que você "redistribuir" no Tomcat? Tomcat, mas e quanto às faria. Porém, para teste, aplicações que estiverem é mais fácil simplesmente rodando? Todas elas têm reiniciar o Tomcat. Você 1: O Tomcat não que ser encerradas?! poderá obter informações possui uma ferramenta sobre a ferramenta de administrativa, que gerenciamento em: seja simples como um 1: Tecnicamente sim. http:/(jakarta.apaehe.org/ torneat/torneat-5. O-doei botão, para distribuição Encerrar suas aplicações e redistribuição (embora para que você possa rnanager-howto. htrnl exista, de fato, uma redistribuir um servlet é No mundo real, até uma ferramenta administrativa meio cruel, especialmente redistribuição quente é se houver demasiado Importante. E tirar do ar uma que acompanha o Tomcat). aplicação, simplesmente por Mas, pense comigo - qual tráfego em seu site. Mas é causa de uma mudança no é a pior coisa que você por isso que a maioria dos valor de um parâmetro init, tem para fazer para alterar Containers de qualidade pode ser uma péssima idéia. os parâmetros init de um permite que você faça uma Se os valores dos seus servlet? Você faz uma redistribuição quente, o parâmetros init forem mudar rápida alteração no arquivo que significa que você não com freqüência, é melhor web.xml, fecha o Tomcat precisa reiniciar seu servidor que os métodos do seu (bin/shutdown.sh) e o ou derrubar nenhuma outra servlet obtenham os valores reinicia (bin/startup.sh). Na aplicação. Aliás, o Tomcat de um arquivo ou banco inclui sim uma ferramenta de dados, mas esta prática reinicialização, o Tomcat resultaria em muito mais pesquisa seu diretório de gerenciamento que tráfego sempre que o código webapps e distribui tudo o permite distribuir, desfazer servlet rodar, em vez de uma que ele encontrar lá. e redistribuir aplicações única vez na inicialização. você está aqui ~ 153
  • 182. usando ServletConfig j avax. servlet. Serv letConfig restat1do seu ServletCot1fig <<interfaee> > A principal função do ServletConfig é disponibilizar ServletCon os parâmetros init. Ele também pode fornecer um getlnitP arameter(String) ServletContext, mas geralmente obtemos o contexto Enumeration getlnitParameterNamesO de uma outra forma e o método getServletNameO raramente ajuda. getServletContextO getServletNameO No arquivo DD (web.xml): <?xml version="l.O" encoding="ISO-8859-1"?> A- 1tIfJ,i"fJ!"là Jas peSSfJfJ,S <web-app xmlns~"http://java.sun.com/xml/ns/j2ee" 1'1111'1CfJ, lISfJ. es.fe 1PI:-ftJJll xmlns:xsi~"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation~"http://java.sun.com/xml/ns/j2ee/web-app 2 4.xsd" version=rF2.4"> <servlet> <servlet-name>BeerParamTests</servlet-name> <servlet-class>com.example.TestlnitParams</servlet-class> <init-param> <param-name>adminEmail</param-name> <param-value>likewecare@wickedlysmart.com</param-value> </init-param> <init-param> <param-name>mainEmail</param-name> <param-value>blooper@wickedlysmart.com</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>BeerParamTests</servlet-name> <url-pattern>/Tester.do</url-pattern> </servlet-mapping> </web-app> Em uma classe servlet: package com.example; import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class TestlnitParams extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("test init parameters<br>"); java.util.Enumeration e = getServletConfig() .getlnitParameterNames(); while(e.hasMoreElements()) { out.println("<br>param name = " + e.nextElement() + "<br>"); } out.println("main email is " + getServletConfig(). getlnitParameter("mainEmail")); out.println("<br>"); out.println("admin email is " + getServletConfig() .getlnitParameter("adminEmail"); 154 cap,ftuJo 5
  • 183. atributos e /isteners ~ JSP consegue obter os parâlMetros inÍt do servlet? o ServletConfig foi feito para a configuração do servlet (não é JSPConfig). Portanto, se você quiser que outras partes da sua aplicação usem a mesma informação declarada nos parâmetros init do servlet dentro do DD, você precisará de algo mais. Que tal a lManeira COlMO fizelMos COlMa aplica~o da cerveja? Nós passalMOS a infortMa~o do lModelo para o JSP usando UlMatributo de solicita~o... ~ se leW!bra? ()H,'ve~s l'l CéU" Ii . dentro do metodo doPost() ~~lí'eJTl-eesc~tI JI"~S lia ;l " String color = request.getParameter("color"); List result be be.getBrands(color); BeerExpert ~ ~ new BeerExpert () v I ""'" se.:tltJD., J I1tJS Ii,S.f-tJ.I1CIfJ."'tI>S e VStJ.",ós request. setAttribute ("s;tes'" result) ;óll4.tibíLO ptU'tJ. •I "êJ"ciD. es-tabe1ece"'óS ti'" 6bffl" a li,fól"hlaii6 Na selP ,,) . J '" I /I IJ.-tf'i'bv-f-ó 114 sDlict-rC.fjfJ.ó e/)", PN!C1"s4114"'óS ptJ.NJ.a J,SP; »1If! I"ecebe :.s-tr;. sóucr-taífl.l'J) f'f!cebe-1D ctJl"Isejfli'tI Nós poderíamos ter feito assim. O objeto request nos permite criar atributos (considere-os como sendo o par nome/valor, onde o valor pode ser qualquer objeto) que qualquer servlet ou JSP que receba esta solicitação conseguirá usá-Io. Isto significa que para qualquer servlet ou JSP para o qual a solicitação é enviada, usa-se o RequestDispatcher. Vamos falar em detalhes sobre o RequestDispatcher no final deste capítulo. Por enquanto, nossa preocupação é passar os dados (neste caso, o endereço de e-mail) para os trechos da aplicação que deles necessitam, e não apenas para um único servlet. você está aqui,", 155
  • 184. (imitações do ínít parameter Criar Utlt atributo de solicitação futtciotta ... tltas só para o JSP que recebe a solicitação Mas eu quero mesmo é que TODAS as partes da minha aplicação aceSsem o endereço de e-moi!. Com os parâmetros No exemplo da cerveja, fez sentido armazenar as init, eu tenho que configurá-Ias no DD informações do modelo para a solicitação do cliente no para cada servlet e, em seguida, fazer com que todos os servlets disponibilizem- objeto solicitação, pois o próximo passo foi encaminhar nos para os JSPs. Que chato, não?! E a solicitação ao JSP responsável por criar a view. Como o pouco prático. Preciso de algo mais global. JSP precisava dos dados do modelo e estes eram relevantes apenas para aquela solicitação específica, tudo funcionou. Mas isso não nos ajuda no caso do e-mail, pois podemos c' o precisar usá-Io em toda a aplicação! Existe uma forma de fazermos um servlet ler os parâmetros init e armazená- los em um lugar onde outras partes da aplicação possam usá-los. Mas, neste caso, precisaríamos saber qual servlet seria sempre o primeiro a rodar no momento da distribuição da aplicação, e qualquer alteração na aplicação poderia estragar tudo. Não, isso também não funcionaria. 156 capítulo 5
  • 185. atributos e Iisteners Os parâtRetros itlit do cotttexto dão UtRaforça Os parâmetros init do contexto funcionam como os parâmetros init do servlet, exceto pelo fato de que os parâmetros do contexto ficam disponíveis para toda a aplicação, e não apenas para um único servlet. Isso significa que qualquer servlet e JSP da aplicação automaticamente têm acesso a eles. Portanto, não precisamos nos preocupar em configurar o DD para cada servlet, e quando o valor for alterado, você terá que mudá-Io em um só lugar! Jefl:hiQvei'VIi~S() elehie'l.f.6 <.i;'i-l--pIJ.1"4hi> uft No arquivo DD (web.xml): ufe,,-fl"lJ uf4 elehif!l1-ftl <,stl"vle-f> <servlet> <servlet-narne>BeerPararnTests</servlet-narne> / ~ </servlet> <servlet-class>TestlnitPararns</servlet-class> ( <context-param> f <param-name>adminEmail</param-name> , <param-value>clientheaderror@wicked1ysmart.com</param- ) value> í </context-param> ~ e ~cê ct}lacavw.I'fi.I"fJ.w.-"ahie lJw.pfJ.rlJ.w.-vaivf!,j ufa IIU.POJerp,.lJrf./! O <.ct}PI+-ex-l----""""'" .fSWtfJ. w lal"w.4 ~ve v6cê Ia'] caw.6Spal"~e_f1"6S I."t.f. Ja pfJ.l"aw.>vale pfJ.l"Q. rODA a sfrll/Hj fiJb"l"IJ.tles-fo. Ve'] eles eS~IJ.iJ tle".f.I"EJJ., al'licag'iój 1'61"í'S ele J1"iií S{j elew.e".f.t:; 'U#t+e*pal"aw.>; < fw. vej Je <.i;'l-l--pfJ.N~hi> tJ.l1i."t.fJ.Jtl fi.l1e"t.Yhi elew.f!I1+a <'Sfl"vlf..f..>!! CcllJ3ve (j ptJ.l"tJ.hI> e".f.1"6 ufI/J <.we!rapp>; d hilJ.SFOJeA- de 3Vlai:SaVfr tleclal"4jCeS <.serllle·h No código servlet: out.println(getServletContext().getInitParameter(~adminEmail"»); 1'; f) iJ:+6tllJ 5e_fSel"vie+ClJ",ffx+O Cada sfl"llle-f "'trila Vw.w.e+aJEJ 1"e-fIJI"PI!J.; cvri'óSIJ.iJtl1+-e;i'" t>tJe+6 l 5e..f..Servit-I-C"".fex+D {f~4S JSPs ..f..alrlb~iJ .fe"w. Sel"lIie-I-Ctm-l-ex+. í VIrI d6S sevs IJ.CeSS6 speclo.i 1M C/J,,+ex..f..6). e w.&adéJS ~ a 5e+IPli..;..pfJ.r!J.lYle+-eI"O. ou: ServletContext context = getServletContext(); ~ out.println(context.getlnitPararneter(~adminErnail"»; A3l1l ,,:s dillitll",ós (J c:d~a tw. J)fJ As par.fes - I"f!cf!be"iló 4 l"elel"ê"âtJ. da Sel"lIle-I-Ctm+-ex+ e Ct.fllYl!J.Plda w.é+'~Ja Sf!lI 5e-l-Il1l+Pal"tJ.lrle.ferO. você está aqui.. 157
  • 186. para/natras init do contexto X parâmentros ínit do servlet Leltbre-se da diferett9a ettlre os parâltetros ittit do servlet e os parâltetros ittit do COtttexto Aqui está uma revisão das principais diferenças entre os parâmetros init do contexto e os parâmetros init do servlet. Preste bastante atenção ao fato de que nos referimos a ambos como parâmetros init, ainda que apenas os parâmetros init do servlet recebam a palavra "init" na configuração DD. parâmetros init do Contexto parâmetros init do Servlet Deployment Descriptor Dentro do elemento <web-app>, mas NÃO Dentro do elemento <servlet> para cada servlet inserido em um elemento específico <servlet> específico <web-app ...> <servlet> <context-param> <servlet-name> <param-name>foo</param-name> BeerParamTests <param-value>bar</param-value> <servlet-name> </context-param> <servlet-class> TestlnitParams <!-- outros comandos, incluindo </servlet-class> declarações do servlet --> <init-param> </web-app> <param-name>foo</param-name> <param-value>bar</param-value> </init-param> 1Je.+e &Ue i'1fJ tl1t.f ftU'tA e.S <!-- outros comandos --> </servlet> Cim+ex.fe.; CfJ""" flJ.l'~e.frds tl1i.f tl.1J Código do Servlet getServletContext() .getlnitParameter(~foo"); getServletConfig() .getlnitParameter(~foo"); Disponibilidade Para quaisquer servlets e JSPs incluídos Somente para o servlet para o qual o <init-param> nesta aplicação. foi configurado. (Embora o servlet possa decidir aumentar sua abrangência armazenando-o em um atributo.) 158 CBt)ítulo 5
  • 187. atributos e iisl!eflIE.! ServletCotlfig é Utft por servlet Inicialização da ServletCotttext é Utft por aplicação aplicação web: O Container lê o DD e cria um par Existe um único ServletContext para toda a aplicação e de String nome/valor para cada todas as partes da aplicação compartilham-no. Porém, <context-paratn>. cada servlet na aplicação tem seu próprio ServletConfig. O Container cria um ServletContext quando uma aplicação é O Container cria uma nova distribuída, disponibilizando-o para cada Servlet e JSP (que instância do ServletContext. se transforma em servlet) na aplicação. O Container dá ao ServletContext uma referência ClJl1ffx-l-"" tia o.pllcai'i" a cada par nome/valor dos ~ ClJ4' iS pfJ.r~e+r6s t parâmetros init do contexto. Cada servlet e JSP distribuído ~a6s como parte de uma única aplicação tem acesso àquele mesmo ServletContext. S/~ "s JSPs Sã6 +rfJ.l1sf6r4'fJ.tl6s e"'" r:- servle+s tle prl'ívlefra servletCo'<' ~ s. .... ~ s.. ~ c/use e +fJ.".béi'l' ervletCOf' ervletCo'<' I 11 rbar~e-l-"'6s s.ervletCOf'~ . recebei'l' seils pr6p"'las par~e+Js p(J.r~e';""'i:Js l"i-tt-..j. t"i-tt+ para D Servle+C"l1f~ 1"111+ para " para"" Servle+ 8 Servle+ C Servle+ fJr l"i-tse""aDS l"i-tserMós l"i-tserM""s Se a aplicação for Não confunda distribuída, existirá parâmetros ServletConfig um ServletContext com parâmetros porJVM! ServletContext! VeJa Íst9! Veja ist9! S~ ~ua aplicação for distribuída por Você realmente tem que saber isso para varros s~rvidores (provavelmente em o exame, mas confunde. Você TEM um a~bIente de cluster), ela até PODE QUE saber que tanto o ServletConfig, ter maIS que um ServletContext. O como o ServletContext possuem Servl~tContext é único por aplicação parâmetros init e ambos usam o mesmo ~~s so se a aplicação estiver em uma' ullIcaJVM! método getter - getlnitParameterO· MAS ... você também tem que saber_ Em um ambiente distribuído você terá um que os parâmetros init do contexto ..sao Servl~tC~ntext por JVM. É até possível criados com <context-param> (e nao que nao.de problemas, mas se você tiver dentro de um elemento <sen:le.t», uma. aplIcação distribuída, é melhor enquanto que os parâmetros mlt do avalIar as conseqüências de possuir servlet usam <init-param> dentro das contextos diferentes para cada JVM. declarações <servlet> no DD. você está aaui •• 159
  • 188. servlet e o contexto do parárnetros init campo de retenção magnética, deslizar até o centro Nã9 exJst~m da Terra e destruir o planeta. Ou talvez nada, porque não existe nenhum feth'untas Id'i9tas conflito de nomes, visto que você obteve os parâmetros através de dois objetos diferentes r: o que acontece com a nomeação (ServletContext ou ServletConfig). inconsistente do esquema? Como podem os elementos do DD serem <context-param> e <init-param>, porém no código servlet, r: Se você modificar o XML para alterar o valor de um parâmetro init (ou servlet ou context), quando o servlet, ou o resto da AMBOS usam o método getlnitParameter()? aplicação, reconhecerão a mudança? 1: Eles não nos solicitaram para ajudá-Ias a 1: APENAS quando a aplicação for proporem um nome. Se eles tivessem pedido, redistribuída. Lembre-se de que nós falamos é claro que nós teríamos dito que deveriam ser sobre isso antes- o servlet é inicializado apenas getlnitParameterO e getContextParameterO, para coincidir com os elementos XML no DO. Ou, eles uma vez, no começo da sua vida, e isso acontece quando é dado a ele o seu ServletConfig e o seu poderiam ter usado diferentes elementos XML - ServletContext. O Container lê os valores pelo possivelmente <servlet-init-param> e <context-init- DO quando ele cria estes dois objetos e configura' param>. Mas não, isto teria absorvido toda a graça os valores. de tentar mantê-Ias corretos. r: De qualquer forma, por que eu usaria r: Eu não posso fazer isso configurando os valores no runtime? Certamente <init-param>? Eu não poderia sempre querer existe uma API que me permite mudá-Ios usar <context-param>, de modo que as outras dinamicamente ... partes da minha aplicação poderiam reutilizar os valores e eu não teria que duplicar o código XML para toda declaração do servlet? 1: Não, não existe. Procure no ServletContext ou no ServletConfig e você encontrará um getter 1: Tudo depende de qual parte da sua (getlnitParameter()), mas você não encontrará aplicação supõe-se que veja o valor. A sua lógica um setter. Não existe nenhum setlnitParameterO. da aplicação talvez requeira de você usar um valor que você queira restringir a um servlet individual. Mas tipicamente, os desenvolvedores acham os r: Isto é terrível. parâmetros init do contexto da aplicação inteira mais auxiliar, do que um dos parâmetros init do servlet de um servlet especifico. Talvez o uso 1: Eles são parâmetros init. Init do latim inicialização. Se você considerá-Ias simplesmente mais comum de um parâmetro do contexto está como constantes para o momento da distribuição, armazenado no banco de dados dos nomes de você terá a perspectiva correta. Na verdade, isso procura. Você gostaria que todas as partes da é tão importante que nós falaremos sobre isso de sua aplicação tivessem acesso ao nome correto, um jeito mais ousado: e quando isso mudasse, você gostaria de mudar isso em apenas um lugar. Considere os parâmetros init como constantes para o momento da r: O que acontece se eu der a um parâmetro init do contexto o mesmo nome de um distribuição! Você pode obtê-/os no runtime, mas você parâmetro init do servlet na mesma aplicação? não consegue configurá-/os. Não existe nenhum setlnitParameterO. 1: O buraco negro do tamanho de uma molécula criada milagrosamente em um centro de pesquisas em Nova Jersey vai se livrar do seu 160 capítulo 5
  • 189. atributos e listeners : lmã de GeladeIra ExercícIos Rea;rume os ímã~ p~ra formar um DD que declara um parametro que cOlllcIde com o código servlet: getServletContext() .getlnitParameter("foo"); Você não usará todos os Ímãs! (Nota: ~uan~o você encontrar <web-app ...>, lembre-se d~ ~ue ISSO~ o_nosso ata!h0. para economizar espaço na pagllla. Voce nao pode dIstnbuir um arquivo web.xml, a me~os que a.tag <web-app> possua todos os atributos dos qUaISnecessIta.) I </servlet>I </param-value> bar Se você se deparar com o "parâmetro init" e não souber se significa parâmetro init do servlet ou <servlet-name> context, considere como servlef. Algumas pessoas usam "parâmetro init" para se referirem a "parâllletro init do servlet". E usam "parâmetro de contexto", ou BeerTest < /servlet-name> mesmo "parâmetro de aplicação", para se referirem a "parâmetro init do contexto". Portanto, ainda que AMBOS sejam parâmetros de inicialização - e derivem do método getInitParallleterO -, lembre-se de que apenas os parâmetros init do SERVLET são listados no DD como parâmetros init. Assim sendo, a expressão "parâmetro init" significa "parâmetro init do servlet" por padrão. [:serVlet-param>] Sabemos que, como desenvolve dor, você será gentil com as outras pessoas e sempre dirá, explicitamente, se um parâmetro init é um parâmetro init do servlet ou um parâmetro init do contexto. você está ~ 161
  • 190. o ServletGontext o que ",ais você pode fazer co", o seu ServletCotttext? Um ServletContext é uma conexão de JSP ou de servlet com o Container e os outros trechos da aplicação. Eis alguns métodos do ServletContext. Colocamos em negrito aqueles que você deverá saber para a prova. < <interjace> > ServletContext getlnitParameter(String) getlnitParameterNamesO Db-#/tI 6S pal'~f..f-r6S getAttribute(String) Db-#/tI os p4r~e.f-r()s 1;'''+ e .;,,.+ f. 4b-#','/espect!lca getAttributeNamesO IJb+é/tl/ especlli'cli. li..f-rtbv+(;$ a.f-rl/;v.f-4S setAttribute(String) removeAttribute(String) I.I. Db-r-e/tl '" 1;'!6r/tllJ.f,IJes getMajor VersionO slJbre 6 getServerlnfoO U),,+IJ.I;,er. getRealPath(String) íscrevf. fJ.1'~VlV,IJ /'1(; '""e getResourceAsStream(String) getRequestDispatcher(String) 1:;--"0 sel'lIt"t'J1'(especlli'c/J hlare/tl4S lJ."i"a"h 1'41'Idrl'ca"h) t)V '76 "esh cap:.f-VIIJfJbre s IJ log(String) Sjsh/tl.'JiI.f-. // mais métodos s+Pts pl4+cheI' • }e.e1Jve 162 5
  • 191. atributos ef Você pode obter o ServletContext de duas maneiras diferentes .•• let sempre retém uma referência Um objeto ServletConjig do serv let. Então, não se engane caso para o ServletContextserv e 'digo palratnesotee;~:eque diga: encontre um co tInitParameter () tservletContext() .ge getServletConfig() .ge Além de ser válido, faz o mesmo que: I itparameter O . tservletcontext() .get n thJ.s . ge , PRECISARIA recorrer ao ,. vez que voce d ê Em um servlet, a UJ1lca letContext seria quan o voc ServletConjig para obt~r S~~t~::: não estendesse HttP~ervl~t oUd estivesse numa class; erv etServletContextO que voce ~er ou _o GenericServlet (o metodo g d ALGUÉM usar um metodo n~o- GenericServlet). Mas a chan;eC e basta chamar seu próprio metodo HTTP é praticamente zero. _ n ao, '+"so se você encontrar um os nao jique conJ~ getServletContext ,ma 1 C ifi para obter o contexto. código que utiliza o Serv et on gd a classe que NÃO seja um as e se o código estiver dentr~ . e.u.m or exemplo)? Alguém pode ~r:let (uma classe assistente/utllztarw~~lasse e seu código terá que ter passado um ServletConjig para e~er a referência para o objeto usar o getServletContextO para rece ServletContext. Y: Como cada parte de uma aplicação 1: Hum, não. A menos que você tenha uma consegue acesso ao seu próprio aplicação bem pequena mesmo. Existem formas ServletContext? de fazer logging bem melhores. O mecanismo mais popular e robusto de logging é o Log4j. Você pode encontrá-Ia no site do Apache: 1: Para os servlets, você já sabe: chame o http://jakarta.apache.org/logj4j seu método getServletContextO herdado. ~Para JSPs é um pouco diferente - os JSPs Você também pode usar a API logging do java. têm o que chamamos de "objetos implícitos", util.logging, acrescentada ao J2SE na versão 1.4. e o ServletContext é um deles. Você verá É legal usar o método ServletContext logO para exatamente como o JSP usa o ServletContext experiências simples, mas em um ambiente real quando chegarmos aos capítulos sobre JSP. de produção você provavelmente vai querer usar algo diferente. O livro Java Servtet & JSP CookBook, da Q'Reilly, explica muito bem sobre Y: Então temos um logging ativo através do logging de aplicações com e sem o uso do Log4j. contexto? Parece MUITO útil! O logging não faz parte dos objetivos do exame, mas é importante. Felizmente, as APls são fáceis de usar. você está aqui.. 163
  • 192. limitações do parâmetro de contexto Detesto estragar a festa do seu ServletContext, mas estes parâmetro~ init não passam de STRINGS! E isso! E se eu quiser inicializar minha aplicação com um banco de dados DataSource, que E se você quiser Uift parâiftetro it1it t1a todos os servlets podem usar? aplica9ão que seja Uift l1afaSource de D bat1co de dados? o Os parâmetros do contexto não passam de Strings. Afinal, você não pode inserir direito um objeto Dog em um deployment descriptor XML. (Na verdade, você poderia representar um objeto serializado em XML, mas não há nenhum recurso para isso na especificação do servlet atualmente ... talvez no futuro.) E se você realmente quiser que todas as partes da sua aplicação tenham acesso a uma conexão com um banco de dados compartilhado? Com certeza, você pode colocar o nome de loolmp do DataSource em um parâmetro init do contexto. Este é, provavelmente, o uso mais comum dos parâmetros de contexto hoje em dia. Mas então quem faz o trabalho de transformar o parâI1letro String em uma referência real ao DataSource que todas as partes da aplicação possam compartilhar? Você não pode mesmo colocar este código no servlet, pois qual servlet você escolheria para ser Aquele Que Pesquisa No DataSource E O Armazena Em Um Atributo? Você gostaria mesmo de tentar garantir que um determinado servlet rodasse sempre primeiro? Pense nisso. EXERCITE SUA 1WENTE Como você solucionaria este problema? Como você conseguiria inicializar uma aplicação com um objeto? Considere que você precise da String parâmetro init do contexto, a fim de criar este objeto (imagine o exemplo do banco de dados). 164 5
  • 193. Poxa, se ao menos existisse uma forma de ter algo como um método principal para minha aplicação toda. Algum código que sempre rodasse antes de QUAISQUER servlets ou JSPs ... o o o que ela realtMettte quer é UtMlistetler Ela quer escutar um evento de inicialização do contexto, de forma que ela possa obter os parâmetros init do contexto e rodar um código antes que o resto da aplicação possa servir um cliente. Ela precisa de algo que possa estar situado lá, esperando para ser avisado que a aplicação foi iniciada. Mas qual parte da aplicação poderia fazer esse trabalho? Você não iria escolher um servlet - já que esta não é uma tarefa dele. Não há nenhum problema com uma aplicação lava simples standalone, pois você tem o mainOl Mas, se for com um servlet, o que você faz? Você precisa de algo diferente. Não um servlet ou lSP, mas algum outro tipo de objeto lava cujo único propósito na vida seja inicializar a aplicação (e, possivelmente, não inicializá-la também, limpando os recursos ao perceber que a aplicação foi encerrada ...). você está aqui ~ 165
  • 194. context listener Ela quer Ult ServletCotttextListet1er r <: <:interfaee> > Podemos criar uma classe separada, não ~ ServletContextListener um servlet ou JSP, que possa escutar os dois eventos principais na vida de um eontextlnitialized(s, _ ServletContext - a inicialização (criação) e a eontextDestroyed(s:rvletContextEvent) destruição. Essa classe separada implementa rvletContextEvent) o javax.servlet.ServletContextListener. Javax.servlet S . ervletContextL· lstener J Precisamos de um objeto à parte que possa: • Ser notificado quando o contexto é inicializado (a aplicação está sendo distribuída). • Conseguir os parâmetros init do contexto através do Serv letContext. • Usar o nome de lookup do parâmetro init para fazer uma conexão com o banco de dados. • Armazenar a conexão com o banco de dados como um atributo, para que todas as partes da aplicação possam acessá-la. • Ser notificado quando o contexto é destruído (a aplicação é retirada do ar ou cai). • Encerrar a conexão com o banco de dados. f) Ils-fePlf!1' JiJ CiJPI-feX+tJ é s""'Y'les: t"'Y'leJr;fi!PI-I-ati Sel'lIle.fC6P1-k x+t-i's-kl1el' public class MyServletContextListener implements ServletContextListener public void contextlnitialized(ServletContextEvent event) { l/código para inicializar a conexão com o banco de dados l/e armazená-la como um atributo do contexto l.sf.. '" iltS SI!l6 4,S j m;VI4S "'6 1,1" '" u ••• <f.Vft (J <ICe •. l'eceJ,e A rIT1CtJ.t:.t'JeS .J v~ Sf!I'V1e.fC.·L xrive ",I- <lI1"1f': ~as eX"J,eJr; public void contextDestroyed(ServletContextEvent event) { l/código para encerrar a conexão com o banco de dados 166 capítulo 5
  • 195. Tudo bem, eu tenho uma classe listener. O que eu faço agora? Onde a coloco? Quem a instancia? Como eu passo a aparecer nos eventos? Como o listener especifica o atributo no ServletContext correto? o o + EXERCITE SUA :MENTE Qual é o mecanismo que você acha que é usado para fazer com que um listener seja parte de uma aplicação específica? Dica: como você informa ao Container sobre outros trechos da sua aplicação? Onde o Container pode encontrar seu listener? você está aqui.. 151
  • 196. usando um ServletContextListener rufarial: UtMServletCatttextListetler sitMples Agora nós iremos construir e executar um ServletContextListener. Trata-se de uma simples classe de teste, para que você veja como todas as partes funcionam juntas. Não iremos usar o exemplo da conexão com o banco de dados, pois você precisaria configurar um para fazê-Ia funcionar. Mas os passos são os mesmos, independentemente do código que você colocou nos métodos de callback do listener. Neste exemplo, transformaremos um parâmetro init String em um objeto real - um Dog. A tarefa do listener é conseguir o parâmetro init do contexto para a raça do cão (Beagle, Poodle, etc.) e usar esta String para construir um objeto Dog. O listener insere o objeto Dog no atributo ServletContext, de forma que o servlet possa recuperá-Io. A questão é que agora o servlet tem acesso a um objeto compartilhado da aplicação (neste caso o Dog), sem precisar ler os parâmetros do contexto. Se o objeto compartilhado é um lJes.fe eJc(!~/{)J CfI/{)ctU"(!iI'I{)S Dog ou uma conexão com o banco de dados, não importa. O ViI'I Cã., tl.f!I7.f.I'Ó JtI! ViI'I importante é usar os parâmetros init para criar um único objeto que todas as partes da aplicação compartilharão. Sel'vle.fC~#1hx.f.. Nosso exemplo Dog: • O objeto listener pede ao objeto ServletContextEvent uma referência para o ServletContext da aplicação. • O listener usa esta referência para que o ServletContext consiga o parâmetro init do contexto para "breed", que é uma String que representa uma raça de cão. • O listener usa a String da raça do cão para construir um objeto Dog. • O listener usa a referência para o ServletContext para configurar o atributo Dog no Serv letContext. • O servlet que faz o teste na aplicação recebe o objeto Dog do ServletContext e chama o método getBreed(). 168 capítulo 5
  • 197. atributos e liste" Criat1do e usat1do o cotttext Iistet1er Talvez você ainda esteja curioso para saber como o Container descobre e usa o listener ... Você configura um listener da mesma forma que você informa ao Container sobre o resto da sua aplicação - através do Deployment Descriptor web.xml! fatél escutat 9sevent9S o Crie uma classe listener SetVletC9ntext7 escteva <<interfaee> > uma classe l1stenel" ServletContextListener eontextlnitialized(ServletContextEvent) 'jpe lmplemente º eontextDestroyed(ServletContextEvent) Setvle:tC9ntextLlstenet. Li" • • c919'Lue-an9 dltet9l"19 WEB- • MyServletContextListener t~íclasses e lnt9tme a9 contextInitialized(ServletContextEvent) C9ntéllnel", c919célnd9 um contextDestroyed(Serv letContextEvent) element9. 1 < l::.'tenel">n9 10 Depl9)'ment Descl"lpt9l". e Coloque a classe em WEB-INF/classes "'"' / / (íSff l1a6 e 6 uAJIC{) 'tljai" paN. 411deela p"de 1"1" ••• wf.I;-IAJFlcllA.sses e flJifldel1+l'f! Jiflfll+as Ifl5tJ.l'es Ó C"I1+atl1f.i" p60le pi"ÓCflN.1'pe1u clfJ,sses. ttl,lli,i"eJifl6Ssobi"e as oleJifllJ.isI" ctJ.p{+fllas6~re P blS+i"l~flijãa) e Coloque um elemento <Iistener> no Deployment Descriptor web.xml UJifltJ. plJ.r. Vãct; e'Jifl 3f1e Pf!1'5f/11+tJ. <listener> p(J,rff d@bb el1+ra if} elel'i';f!I1+6 <listener-class> com.example. MyServletContextListener <:.l" +e fS ~l1ei". >7 íl e I1f/Jifl e'''''e e I ,,+.~ </listener-class> <:sel'vle+> t>{,I s/~/esil'!e",ff aba/xi! </listener> .lã você está BUU! •• 169
  • 198. tutoria I ServletContextUstener Precisatltos de três classes e Utlt 1111 Para o nosso teste com o listener de contexto, precisaremos escrever as classes e o arquivo web. xml. <<interfaee> > Para facilitar nosso teste, colocaremos todas as ServletContextListener classes no mesmo pacote: eom.example .L:::,. I I o O ServletContextListener I MyServletContextListener MyServletContextListener.java eontextlnitialized(ServletContextEvent) Esta classe implementa o ServletContextListener, eontextDestroyed(ServletContextEvent) recebe os parâmetros init do contexto, cria o Dog e o configura como um atributo de contexto. e A classe atributo Dog(string) Dog Dog.java getBreedO A classe Dog é simplesmente uma classe Java simples. Sua função é ser o valor do atributo que o ServletContextListener instancia e configura no ServletContext para alimentar o servlet. <<interfaee> > ServletContextListener e O Servlet GenericServlet ListenerTester.java Esta classe estende o HttpServlet. Sua função é verificar se o listener funcionou através HttpServlet do recebimento do atributo Dog oriundo do contexto, chamando o getBreedO no Doge exibindo o resultado para a resposta (portanto, é isso que veremos no browser). doGet(HttpServletRequest,HttpServletResponse) 170 5
  • 199. atributos e listeners Escrevetldo a classe listetter <<interfaee> > ServletContextListener Ela funciona como qualquer outro tipo de listener que 4'- I você já deve estar familiarizado, como os tratadores de I eventos GUl Swing. Lembre-se, tudo que precisamos MyServletContextListener fazer é obter os parâmetros init do contexto para descobrir a raça do cão, criar o objeto Dog e colocá-lo dentro do contexto como atributo. eontextlnitialized(ServletContextEvent) eontextDestroyed(ServletContextEvent) paekage eom.example; IlI!iflelVle~.f4 4j4V4Jf.serv1e.f.Serv1e-!-C4"iex.f!-lsie'fer import javax.servlet.*; ~ publie elass MyServletContextListener implements ServletContextListener publie void contextInitiali.zed (ServletContextEvent event) ( ServletContext se = event. getServletContext (); ~altclflA a Servle-!-Ca"ffJf+ IA"eve".f". String dogBreed = se.getlnitParameter("breed");~ Dog d = new Dog (dogBreed);<-- erl4 UIVI US4" c()"iexfIJ pfJ.NJ. IJbier iJi . 'fava Da,; parã..efra I;'''.f se.setAttribute("dog", d),~ v U.1'4a c()"ieX+a 1'41"4especilicfl.r UIVI .fribu.fa 4 (UIVI '.1" "alVle!a!de.faJ Daj. A'jara; aufl"cs 1 .fl"ect,cs JfI. 4pli"cfJ.j';asel"ãa CIAj>4jeS receber Je a V4/al" Ja fl.fl"l6u.fa (iJiDiJij) publie void contextDestroyed(ServletContextEvent event) ( Ii nada a fazer aqui ~ lJ';fJ preciS41V1t;$ "fl.J4 fJ.3Ui. ) DfJj ~ã()pl"ectsfJ. Je ( ser Illfl{>fJ••3UfJ.'fJfJ • fJct>"ieJf.ffJ ierlVll;'a., slj'flli'cfJ. v4ll,;'alijfJ.I"J ·,;'clt,,;'JfJ a 3ue .ffJJ •• IAj>llc4jÃt> você está aqui ~ 171
  • 200. o atributo c/ass Escrevet1do a classe atributo (Uog) Naturalmente, precisamos de uma classe Dog - a classe que Dog representa o objeto que armazenaremos no ServletContext, depois de ler os parâmetros init do contexto. Dog(string) getBreedO package com.example; public class Dog { Alada de especl'al 4~V". A-pel7fJ.S private String breed; vltla classe Java sl"Ify>les public String getBreed() return breed; "" Al6SSI.i Sfrvle-f. recebel": 6])65 d6 clurhJ6 V.])65 3Vf!" Its-h:~r C617115Vl"4 C61tl1.i a+l"tbv+~) et.41t'>A1": " ltlé+ad65e-f.8I"eell!O "6])65 e (;6f"4r: 111 1"4j4 174 resp'cs+a.,ftJ.1"4 3ve f6SS41t6S vê-/4 I7D br6wser f: Eu achei que tivesse lido em algum lugar que os atributos do servlet tinham que ser Serializáveis ... 1: Pergunta interessante. Existem vários tipos diferentes de atributos e se o atributo tem que ser Serializável só interessa aos atributos Session. E apenas quando a aplicação está distribuída em mais de uma JVM é que ele é realmente importante. Nós falaremos mais sobre isso no capítulo das Sessões. Não existe nenhuma necessidade técnica para que qualquer atributo (incluindo os atributos Session) sejam Serializáveis, embora você possa considerar criar todos os seus atributos Serializáveis por padrão. A não ser que você tenha uma boa razão para NÃO fazê-Ia. Pense nisso: será que você está mesmo seguro de que ninguém jamais vai querer usar aqueles objetos como argumentos ou retornar valores como parte de uma chamada remota a um método? Você pode mesmo garantir que alguém que use esta classe (Oog, neste caso) nunca rodará em um ambiente distribuído? Então, embora tornar os atributos serializáveis não seja uma exigência, você deveria sempre que pudesse. 172 caoi'tu}o5
  • 201. atributos e lístenelS Escrevet1do a classe servlet Esta é a classe que testa o ServletContextListener. HtipServlet Se estiver tudo funcionando corretamente no momento em que o método doGetO do Servlet rodar pela primeira vez, o Dog será esperado como um atributo no ServletContext. ListenerTester doGet(HttpServletRequest,HttpServletResponse) package com.example; import javax.servlet.*; import javax.servlet.http.*; import java.io.*; Ai."" "e especta/ a-# aJlIl •••~el74S lI~ sel'v/el- C6/t1l1/t1 public class ListenerTester extends HttpServlet public void doGet (HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("test context attributes set by listener<br>"); out.println("<br>"); ~ . lr.,.lIt 6!rk~6s 6 Dog dog = (Dog) getServletContext(} .getAttr1bute("dog"};~U / 7 //65 a-l-n.vf.s d{J :.. Ai';6 eSJlIf.ja 6 c:/CY/6f! SeI'VIe+e6~J. Se out. println ("Dog' s breed is: " + dog. getBreed ()); 6 /ls+el7f,F' -IlII1Ci611(J(Jj .p " !J65 VIJ.tes-l-al' alt é Se 4'56 17';6-IlIl1t:l611IJYj 1r~IJI JlIe IrAiríS allf. () ~é+()ti() tif.SC6bl""'e~6S •••Vfl.~6S recebel' lI/tI el7tJrhle serv,i:e sr.;tl ct.a~tlti6 AillIlRs,irhl'íxcerl·t'1I7 se +e17-1-'U'hlfJSt.ahllJ.l' c pe/fJ. l'lm.etl"fI.ve; p 65e-l-8reetiO e l"Jã6t.6wer l"Jel"Jf"y~ !J65 o getAttributeO retorna_ precisa fazer a conversao un;.~~~~:;~:~Cê . " O orna uma String. Ou seja, voce Mas o getInitParameter t resposta o ge tAttributeO ' mas o retorno . retd S do precisa conver er a 'buído diretamente a uma trmg. getlnitParameterO pode ser atrl 1 s códigos escritos noS exames que portanto, não seja iludi~o por aque e não usam uma tA "b t ("dog"l' '" conversao: ~ t: 1I '('''fl.d6 •• Dog d = ctx.ge ttrl U e /' (Considere ctx como um ServletContext.) você está aqui il>' 173
  • 202. configurando um Iistener no DD Escrevet1do O Peploytltettt Pescriptor Í-s-h é" tU'SVt"l6 wd.J(~·J !'IU'6. Agora, informamos ao Container que temos um es+tJ. 4p'tca{;6) deJ1+,..1J d6 listener para esta aplicação, usando o elemento web.xml dl"'e+:"'k~ wí8-IAlF <listener>. Este elemento é simples - só precisa do nome da classe. Só isso. <web-app xmlns=''http://java.sun.com/xml/ns/j2ee'' xmlns:xsi~''http://www.w3.org/2001/XMLSchema-instance'' xsi:schemaLocation=''http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <servlet> <servlet-name>ListenerTester</servlet-name> <servlet-class>com.example.ListenerTester</servlet-class> </servlet> <servlet-mapping> <servlet-name>ListenerTester</servlet-name> <url-pattern>/ListenTest.do</url-pattern> </servlet-mapping> '" ••"'",'i1t.f i Pl"ecisa",,,s Je li'" !,((NA"'," <context-param> dI> C6I'IffJ(.f6 !,41't1. ti. fJ.p'tCIJ.{;(J. <param-name>breed</param-name> t> lls.fe"e'" p,..eósfJ. Jele plJ.f'tI. <param-value>Great Dane</param-value> CIJJ1S+f'lIt,.. 6 b65 </context-param> <listener> <listener-class> com.example.MyServletContextListener </listener-class> </listener> </web-app> 174 capítulo 5
  • 203. atributos e lísteners 1'11'.9 e:x1stem YerhUntels Ídl9tétS r: Espera aí... como você está informando ao Container que isso é um listener para os eventos do ServletContext? Não parece ser um elemento XML para o <Iistener-type>, ou algo que diga para que tipo de evento serve este listener. Porém, eu percebi que você tem um "ServetContextUstener" como parte do nome da classe. É assim que o Container entende? Pelo nome? 1: Não. Não há nenhuma convenção de nomes. Nós só fizemos assim para tornar mais óbvio o tipo de classe que criamos. O Container descobre ao inspecionar a classe e notar a presença da interface listener (ou interfaces; um listener pode implementar mais de uma interface listener). r: Isto significa que existem outros tipos de listeners na API servlet? I..: Sim, existem vários outros tipos de listeners que falaremos em um minuto. você está aqui ~ 175
  • 204. compilando e distribuindo o lísterner test COtMpile e distribua L.eirJJI'f;"'Sf', rubfj 1;veperhl7j4 40 ..;- .rev welJspps fica 41;1./1·caA/4VItI CDltl a ( Vamos fazer tudo funcionar. Eis os passos: SIIfJ. fl':'1"ifi. es+ro.Jw.fJ.,,(e Jll'el-f.I'Í4sJ o Compile as três classes f If I'fi.") ffJ.1'fJ.es.fa tJ.p'tca{i/J. ís-h Jtl'e.ff.I'It> Jeve es.f41' Jei'1.f1'6 JE) Ji'l'e.ff.I'It> Elas estão todas no mesmo pacote ... webàpfs P(lJ 1;/II'IC4+ e Crie uma nova aplicação no Tomcat • Crie um diretório chamado listenerTest e coloque-o dentro do diretório webapps do Tomcat. • Crie um diretório chamado WEB" INF e coloque-o dentro do diretório listenerTest. • Coloque o seu arquivo web.xml nO diretório WEB·INF. • Crie um diretório de classes dentro do WEB-INF. • Crie uma estrutura de diretórios dentro das classes, que coincida com a estrutura do seu pacote: um diretório chamado com, que contém o exemplo. e Copie seus três arquivos compilados para dentro da estrutura de diretórios da sua aplicação no Tomcat listenerTest/WEB-INF/classes/com/example/Dog.class listenerTest/WEB-INF/classeS/com/example/ListenerTester.class listenerTest/WEB-IN~/Classes/com/example/MyServletContextListener.class e Coloque o seu Deployment Descriptor web.xml no diretório WEB-INF desta aplicação. listenerTest/WEB-IN~/web.xml e Distribua a aplicação, desligando e reiniciando o Tomcat. 176 5
  • 205. atributos e Iitlatf•. Q VatBOS experitBetttar Abra seu browser e vamos direto ao servlet. Nós não nos incomodamos em fazer uma página HTML. Por isso, iremos acessar o servlet, digitando a URL do mapeamento servlet no DD (ListenTest.do). A raça do cão é: Great Dane rroubleshootit1g Se você receber um NullPointerException, você não recebeu um Dog do getAttributeO. Verifique o nome da String usado no setAttributeO e certifique-se de que ele coincide com o nome da String que você está usando no getAttributeO. Verifique novamente seu web.xml e tenha certeza de que o <listener> está registrado. Tente olhar nos logs do servidor para descobrir se o listener está mesmo sendo chamado. Para complicar o máximo possível, nós atribuímos nomes sutilmente diferentes. Queremos ter certeza de que você está atento a como estes nomes são usados e quando dar a eles o mesmo nome. É difícil dizer Como os nomes afetam sua aplicação. Nome da classe Servlet: ListenerTester.class Nome do diretório da aplicação: IistenerTest URL padrão mapeada para o servlet: ListenTest.do você está aQui ~ 177
  • 206. atributos de sessão X segurança contra threads A história cot1pleta ... Eis o cenário desde o início (inicialização da aplicação) até o final (o servlet rodando). Você verá no passo 11 que resumimos a inicialização do servlet em um grande passo. o O Container lê o Deployment Descriptor para esta aplicação, inclusive os e O Container cria um novo ServletContext, que todas as partes elementos <Iistener> e <context-param>. da aplicação compartilharão. new web.xml ServletContext e O Container cria um par de Strings nome/ valor para cada parâmetro init do contexto. e O Container dá aos parâmetros nome/valor as referências do Suponha que tenhamos apenas um. ServletContext. new e O Container cria uma nova instância da classe 00 Container chama o método contextInitializedO do listener, passando MyServletContextListener. em um novo ServletContextEvent. O objeto new de evento tem uma referência para o ServletContext, então o código que trata o evento consegue obter o contexto através instância de do evento e consegue obter o MyServletContextListener .c1ass parâmetro init do contexto através do contexto. ServletCon extEvent .,j,. - contextlnitialized(ServletContextEvent) listener 178 capítuío.5
  • 207. atributos e Iistens8 A história cottlittua ..! oo listener solicita ao ServletContextEvent uma referência eo listener parâmetro solicita ao ServletContext init do contexto "breed". o para o ServletContext. r getServletContext~ ~ getInitParameter("breed") Iistener ServletContextEvent o • O listener usa o parâmetro init para ~ O listener configura o Dog como um construir um novo objeto Dog. atributo no ServletContext. /new _ setAttribute("dog", '" d) -"" listener instância de Dog.c1ass listener ServletContext CD O Container cria um novo Servlet (isto é, cria um novo ServletConfig com e O servlet recebe uma solicitação e pede ao ServletContext o atributo "dog". parâmetros init, dá ao ServletConfig uma referência para o ServletContext set Attribute(" dog") e chama o método initO do Servlet). Servlet ServletContext • O servlet chama o getBreedO no Dog (e exibe-o no HttpResponse). getBreedO você está aqui ~ 179
  • 208. outro Jisteners Acabo de pensar numa coisa ... já que os atributos podem ser configurados através de um programa (ao contrário dos parâmetros init), eu posso escutar os eventos do atributo? Como se alguém acrescentasse ou substituísse o Dog? o o Listeners: não só para os eventos do contexto ... Onde existe um momento do ciclo de vida, geralmente existe um listener para escutá-1o. Além dos eventos do contexto, você pode escutar eventos relacionados aos atributos do contexto, atributos e solicitações do servlet, e sessões HTTP e atributos da sessão. o lu. toda anão precisa saber: :· Você APllistener. · · · Com exceção do ServletContextListener, você realmente não precisa memorizar os · · métodos de cada interface do listener. Mas ... · · · você PRECISA conhecer os tipos de eventos · · que você pode escutar. · · · · · Os objetivos do exame são claros: você receberá um cenário (o trabalho de um · · · desenvolvedor numa aplicação) e você · · precisará decidir qual é o tipo certo do · · · listener, ou se é POSSÍVEL ser notificado sobre esse evento do ciclo de vida. · · •...•...•........•.•.....•...............•...•... N "'I'Ma 'ala."elfllas se./;rf, se,SSaf!S IV f/.-n;: I_!. a P":XtIVl6 C4,{.f1l16) pal'-h.".fa l"Iãa se PI'f!6ClIpe oA. #'ti " N se lIace' 4'-1"It!41"14a sabe a 3l1f! e lIIrIa ses sa" 1f"'t1Pali par 3l1e IIIJcê 1"1''-4 3l1f!I'e'1' sdel' ••• 180 capítulo 5
  • 209. atributos e lisrefUI Escolha o listener Correlacione o cenário da esquerda com a interface do listener (no final da página) que E'){etclc19S J o suporta tal objetivo. Use cada interface uma única vez. (Sim, nós SABEMOS que ainda não vimos essas. Veja como você consegue descobrir apenas olhando os nomes. As respostas começam nesta mesma página, então não olhe!) Cenário Interface do Listener Você quer saber se um atributo em um contexto da aplicação foi adicionado, removido ou substituído. Você quer saber quantos usuários concorrentes existem. Em outras palavras, você quer rastrear as sessões ativas. Você quer saber todas as vezes que uma solicitação chegar, para então poder logá-Ias. Você quer saber se um atributo da solicitação foi adicionado, removido ou substituído. Você tem uma classe de atributo (uma classe para um objeto que será colocado em um atributo) e você quer que objetos deste tipo sejam notificados quando eles forem associados ou removidos de uma sessão. Você quer saber quando um atributo de sessão foi acrescentado, removido ou substituído. Selecione as interfaces abaixo. Use cada listener apenas uma vez. HttpSessionAttributeListener Serv2etRequestListener Ht~SessionBindingListener HttpSessionListener Serv2etContextAttributeListener Serv2etRequeStAttributeListeoer você está aqui... 181
  • 210. listeners mais comuns Os oito listetters Cenário Interface do Listener Tipo de Evento Você quer saber se um atributo jrequestlnitialized ServletRequestAttributeEvent servleLhttp ServletContextAttributeEvent attributeRemoved ServletContextEvent jeontextInitialized HttpSessionEvent (vt,tJ+ó pal'a ó javax.servlet. ServletContextListener javax.serv let. ServletContextAttributeListener attributeAdded sessionCreated ServletRequestAttributeListener valueBoundleLhttp.HttpSessionListener avax. serv let.http.HttpSessionActivationListener sessionDidAetivateHttpSessionBindingEvent javax.servlet.ServletRequestListener sessionDestroyed ServletRequestEvent avax.servleL javax.servlet.http.HttpSessionBindingListener requestDestroyed .HttpSessionAttributeListener HHpSesstlJ"A-Hl'tl;u.f.eL,"s.f.e'JIU' valueUnbound sessionWillPassivate 'l+p5es s,,,,,,/Jrc·h-IIaft,,,,,,f.lle,../- mpoe s uma ()notificados quando eles (vóce attributeReplaeed capítulo.) sobre sessões espera CóJ>l espera 1IJ>1 AJÃ-oé 'JóJ>les!() foremsessão. ;jlle vóce no próximo es-l-a t'JCÓ'JSI"s.f.e"'"lCl"a detalhes e IJ eu/,/a"ó eontextDestroyed ou removidos de sejam associados attributeReplaeed "e fJ·1f. I.f I ~ HHpSessI6'JA-HI'lI;II.f.e~ve~j. AIA- ~ oto to ios Você quer saber quando Você quer saber todas as vezes 182 capítulo 5
  • 211. atributos e liStel'lelS o HttpSessiot1Jit1dit'gUstet1er Você pode estar confuso sobre a diferença entre um HttpSessionBindingListener e um HttpSessionAttributeListener. (Bem, não você, mas alguém que trabalha contigo.) Um HttpSessionAttributeListener simples é apenas uma classe que quer saber onde qualquer tipo de atributo foi acrescentado, removido ou substituído em uma Sessão. Mas oHttpSessionBindingListener existe para que o atributo em si possa descobrir quando ele foi adicionado ou removido de uma Sessão. package com.example; import javax.servlet.http.*; public class Dog implements HttpSessionBindingListener private String breed; public Dog(String breedJ this.breed~breed; public String getBreed() return breed; public void valueBound(HttpSessionBindingEvent event) { Ii código para rodar agora que eu sei que estou em uma sessão public void valueUnbound(HttpSessionBindingEvent event) { Ii código para rodar agora que eu sei que eu não faço mais sessão // nparte /I de uma n íles v·/-;/tu", a patavNJ. nba(l"" e v"lIl:Iv,," para n J n n } tltjer atllclimaila e re"'l:IvtiJa"e . &li com cada instância ativa representando as f: Tudo bem, eu entendi como funciona. Eu entendi que o 009 (um atributo que será informações - de nome, endereço, pedido, etc. - de cada cliente. A informação real é armazenada em um determinado banco de dados. Você adicionado à sessão) quer saber quando ele usa as informações do banco de dados para está dentro ou fora de uma sessão. O que não preencher os campos do objeto Cliente, mas entendi é POR QUE. a questão é como e quando você mantém o registro do banco de dados sincronizado comai( I: Se você sabe algo sobre Entity beans ... então pode imaginar esta capacidade como um informação do Cliente? Você sabe que sempre que um objeto Cliente for adicionado à sessão. é hora de atualizar os campos do Cliente nos "entity bean dos pobres". Se você não conhece registros do banco de dados, com os dados deste os entity beans, você deveria correr para a livraria cliente. Então, o método valueBoundO é como mais próxima e comprar dois exemplares do livro um gatilho que diz: "Carregue-me com dados Use a Cabeça! EJB (um para você e outro para recentes do banco de dados ... só para garantir; o seu amor, para que compartilhem momentos caso algo tenha mudado desde a última vez. que especiais discutindo sobre isso). fui utilizado." Por sua vez, o valueUnboundO diz: Por enquanto, eis uma forma de pensar sobre "Atualize o banco de dados com os valores dos isso: imagine que o Oog é uma classe Cliente campos do objeto Cliente." você está aqui.. 183
  • 212. talela do lístener Relembrando os listeners Faça o possível para preencher os espaços na tabela abaixo. Tenha em mente que as interfaces do listener e os métodos seguem um padrão consistente de nomes (a maioria). As respostas estão no final do capítulo. Listeners de Atributos Outros listeners do ciclo de vida Métodos em todos os listeners de atributos (exceto binding listener) Eventos do ciclo de vida relacionados às sessões (exceto eventos relacionados aos atributos) Eventos do ciclo de vida relacionados às solicitações (exceto eventos relacionados aos atributos) Eventos do ciclo de vida relacionados ao contexto do servlet (exceto eventos relacionados aos atributos) 184
  • 213. atributos e listeners o que él de fatol UtM atributo? Nós vimos como o listener ServletContext criou o objeto Dog (depois de conseguir o parâmetro init do contexto) e foi capaz de inserir (configurar) o Dog no ServletContext como um atributo, de for que as outras partes da aplicação pudessem ter acesso a ele. Antes disso, com o exemplo da cerv nós vimos como o servlet foi capaz de inserir os resultados da chamada para o modelo no objeto (geralmente o HttpServletRequest) da Solicitaçã( como um atributo (para que o JSP/view pudesse conseguir o valor). Um atributo é um objeto configurado (denominado bound) em um dos três outros objetos daAPI servlet - ServletContext, HttpServletRequest (ou ServletRequest) e HttpSession. Você pode considerá-Io simplesmente um par nome/valor (onde o nome é uma String e o valor é um Objeto) el uma variável da instância do mapeamento. Na verda nós não sabemos - e nem nos importa - como isto é 5/lJehl ptJtle ver esh implementado de verdade. Tudo que nos preocupa é 3lJa.tlf"6tle tl.yi'slJs? escopo no qual o atributo existe. Em outras palavras, 5/lJthl patle receber quem pode vê-Io e por quanto tempo ele vive. e c411/ljvra.r 6S lI.+rl!;lJ+6s? Um é C9m9 um 9bjet9 ptes9 em um 'Luadt9 de AJ,buém 9 atlx9u n9 'Luadt9 pata 'Lue 9utt9S p9ssélm pe,b~19ç As ,btandes petb'unt{l,')sã9: 'Luem tem ae(~S5,9 'Luadl"9 a9 de aV1595e 'Luélnt9temp9 ele petmaneee lá? Em 9utl"aS é pahtvtas, 'LuQ1 9 e5C9p9 d9 éttl"lbut9? você está aqui.. 185
  • 214. atributos X parâmetros Os atributos t1ão são parâlfletros! Se você é um iniciante em servlets, talvez precise de mais tempo reforçando as diferenças entre atributos e parâmetros. Mas saiba que quando elaboramos a prova, nós gastamos um pouquinho mais de tempo para garantir que as questões que se referem a atributos e parâmetros sejam as mais confusas possíveis. * Atributos Parâmetros Tipos Application/context Application/parâmetros init do contexto Request Parâmetros da solicitação Session AJ';IJ 1.: "If!."IJ.lIIVta+I""/;lI+IJ Parâmetros init do servlet espec{ltclJ para (J sel"vle+ (/;as+o. lIsal" lIIVtIJ. al",-:'ve.l da v AJ';IJ exi'sffltl fal"M.,e+I"lJs da ses s'iIJ/ I~S+V,Ct() Método para setAttribute(nome da String, valor do Objeto) Você NÃO PODE configurar os configuração parâmetros init da Application e do Servlet - eles são configurados no DD, lembra? (Com os parâmetros da Solicitação, você pode ajustar a query String, mas é diferente.) Tipo de retorno Objeto String ~ bl'fJ."Ide dtlel"e"ljfJ.! Método para ServletContext.getAtribute (String name) ServletContext.getAttribyte(String name) obtenção se eSJlIega de 3ve IJS develtl ser cIJ"IlIel"-f-,(Jl)sJ dIJ I"e+IJI""IIJ é 0fJe.+1) *É verdade. Se nós fizéssemos uma prova simples e objetiva, você não teria aquele orgulho e a sensação de realização ao ser aprovado. Fazer um exame dificil o suficiente para garantir que você precisaria comprar um guia de estudo para passar na prova nunca, EM ALGUM MOMENTO, passou pela nossa cabeça. Não mesmo. Nós só estávamos pensando em você. 186 capítulo 5
  • 215. atributos e listeners Os rrês Escopos: Cotttextol Solicitação e Sessão Atributos do Contexto set Context Listener JSP Atributos de Sessão servlet A Acessível apenas para aqueles com acesso a um HttpSession específico Atributos de SOLICITAÇÃO set get Acessível apenas para aqueles com acesso a um ServletRequest específico você está ~ 187
  • 216. escopo atributos - exercicios Escopo Atributo Faça o melhor possível para preencher os espaços nesta tabela. Você REALMENTE tem que entender o escopo atributo para o exame (e para o mundo real), porque você tem que saber qual escopo é a melhor opção para B')(etclc195 ~o um determinado cenário. A resposta encontra-se algumas páginas à frente, mas não vale olhar! Se você vai fazer o exame, confie em nós ... você deve fazer o exercício sozinho, com o tempo necessário para pensar nas questões. Acessibilidade Escopo Para que serve (quem pode ver) (por quanto tempo vive) Contexto HttpSession . Solicitação (Ai6+ti.: vacê deve levar e"", cMstdertJ.{ilJ 4S i"lly>lic4f6es dI), c61e+4 de 11"/(6 3ua"td6 1I6cê pe"tsfl.r e"", esclJplJ ••• alju"ts a+ribll+as 1"I'i1J serãlJ ct:Jle+fJ.das a# a 311e IlpllctJ.{ilJ S~fI. deslJ..ftvada <fJU /III(;I'+ti.. AiãlJ t.: PIlAdaPlIJeXIAJIleslJbre fl'~e+t:J ct:JJIlerf!Plci'"4J1lePl+1Jde j , L_ .••.• /IIIeJll6rlà e/lll JIlePl"n:; JIl4S IIlJce deve se pl'ecaver) 188 capitulo 5
  • 217. atributos e lísteners A API Atributo Os três escopos do atributo - contexto, Object getAttribute(nome da String) solicitação e sessão - são tratados pelas setAttribute(nome da String, valor do Objeto) interfaces ServletContext, ServletRequest removeAttribute(nome da String) e HttpSession. Os métodos da API para atributos são exatamente os mesmos em Enumeration getAttributeNamesO cada interface. Contexto Requerimento Sessão <<inteifaee> > <<inteifaee> > «interfaee>> ServletContext ServletReq uest HttpSession getInitParameter(String) getContextTypeO getAttribute(String) getInitParameterNamesO getP arameter(String) setAttribute(String, Object) getAttribute(String) removeAttribute(String) getAttribute(String) setAttribute(String, Object) getAttributeNamesO setAttribute(String, Object) removeAttribute(String) removeAttribute(String) getAttributeNamesO setMaxInaetivelntervalO getAttributeNamesO Ii MUITOS outros métodos ... getIDO getLastAeeessedTimeO getMajor VersionO Ii MUITOS outros métodos ... getServerInfoO <<inteifaee> > HttpServletRequest getReaIPath(String) getContextPathO getResoureeAsStream(String) getCookiesO getRequestDispateher(String) getHeader(String) log(String) Ii MUITOS outros métodos ... getQueryStringO getSessionO Ii MUITOS outros métodos ... você está aqui.. 189
  • 218. attribute Sln'1ngieni9sS o lado negro dos atributos ... Kim decide testar os atributos. Ele configura um atributo e, imediatamente, recebe o valor do atributo e o mostra na resposta. Seu doGetO se parece com o seguinte: public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException response.setContentType(~text/html"); PrintWriter out ~ response.getWriter(); out.println(~test context attributes<br>")"; getServletContext() .setAttribute(~foo", ~22"); getServletContext () .setAttribute (~bar", ~42"); out.println (getServletContext () .getAttribute(~foo")); out.println(getServletContext() .getAttribute(~bar")); Eis o que ele vê na primeira vez que o executa. É exatamente o que ele esperava. teste os atributos do contexto 22 42 íxa+a""e-rl-e" Sve espera"""s". 190 capítulo 5
  • 219. atributos e lísterlefJi Mas algo dá terrivelmente errado ... Na segunda vez que ele executa o comando, ele se choca ao ver: teste os atributos do contexto 22 16 I--. C"Ift" í.SS/} p"l"cp.l"laac""./-ecev??? be ""t/e Vf!.16 esse 7(? Caiê " 2? ti + EXERCITE SUA MENTE Observe o código atentamente e imagine o que está acontecendo. Você saberia explicar onde está o problema? Você pode não ter informações suficientes para solucionar o problema, por isso aqui vai outra dica: Kim colocou este código em um servlet de teste que é parte de uma aplicação teste bem maior. Ou seja, o servlet que possui o método doGetO foi distribuído como parte de uma grande aplicação. Agora você consegue descobrir? Você saberia como ele poderia resolver isso? você está aqui. 191
  • 220. escopo do contexto e thread-safe o ó o escopo do comexto •.• o é thread-safe! ã Esse é o problema. Lembre-se, todos na aplicação têm acesso aos atributos do contexto, e isso significa vários servlets. E vários servlets significam que você pode ter várias threads, já que as solicitações estão sendo tratadas ao mesmo tempo, cada uma em uma thread separada. Isto acontece independentemente das solicitações estarem chegando para o mesmo servlet, ou não. ~ I ípa! OU+i"ó sei"lIle+ ~Uf h,'j f'fJ.i"+e 4Iftl. es.."a t<pllc4f4(J; i"ó4lfal'l4lfoe.." 1Ih1J. h +t.i"ffJ.4If Sff4i"441f4, ." " ".. f>c4IfecCl'lli;:;Vi"{J.i" <:l ~ .l-d!Ju+. !J__ . Client C í i'sS<:l ~4(J é +v4IftJ ••• tJ C(J~+llt~ei" p,,4Ife CíJli"i"f54i" tJV.f.I"fJ.+t.l"eb.4If pll1"4 tJSei"vle+ I-r; 4 I'ÍfII 4Ifea+e~4Ifel" v.." +el"celNJ clrel'l-h ••• 192 capítulo 5
  • 221. atributos e listeners o probletMa etM eâtMera Iettta. .. Eis o que aconteceu com o servlet de teste do Kim. 00 servlet "foo" com o valor "22". do contexto A configura o atributo 80 servlet "bar" com o valor"42". do contexto A configura o atributo _set~ Thread A Thread A String String e A thread B torna-se a thread que está sendo executada (a thread A retorna o A thread A torna-se a thread que está sendo executada novamente e recebe o ao estado de Executável-mas-não- valor de "bar", copiando-o na resposta. Executando) e configura o atributo do contexto "bar" com o valor "16". (O 42 agora já era.) _set~ Thread A String Thread B Stríng í;r/--re as e+~~s e"" ti servle+ fJr ctI"lij//I"IA ti V4/tlr le bar e ti rec//pera,; 1)//+1"4 getServletContext ().setAttribute ("foo", "22"); ~ ( -H.reu.JCIJ"lijUI"IA 4jã'" e JI) servle+ eiJ'l+r4 e'" c,,'" //'" getServletContext() .setAttribute("bar", "42")' ,_ . . :,,,) lia/ti: Jilere"ff. out .prlntln (getServletContext out.println(getServletContext() () .getAttribute("bar"»; .getAttrlbute ( foo );l. í,,-fu.a Juf.//4"1JtI ti servlel- A I extbe " lia/til" Je b4r,) e1ej./íM ""uJaJtI para 7t. você está aqui... 193
  • 222. threads e atributos do contexto Cotto tomattos OS atributos do contexto thread-safe? É CLARO que eles não sincronizaram os métodos no ServletContext. Puxa ... Isto Vamos ouvir o que alguns desenvolvedores significaria que toda chamada para obter têm a dizer ... e configurar um atributo receberia toda a sobrecarga da sincronização. Que grande desperdício seria se você não fosse precisar disso. Não, proteger os atributos é problema Eu estou pensando que eu SEU ... não espere que a API irá ajudá-Io. podia sincronizar o método (Eu não posso acreditar que ela doGetO, mas isso não parece chegou a sugerir isto.) mesmo certo. Mas eu não sei C> mais o que fazer. o () o 194 cao!'tulo5
  • 223. atributos e 1istenêf8 Sittcrottizar o lItétodo de serviço é ullta PtSSIMA idéia Tudo bem, então já sabemos que sincronizar o método de serviço vai detonar a nossa capacidade de processo simultâneo, mas protegerá a thread, certo? Dê uma olhada neste código legítimo e verifique se ele evitaria o problema que o Kim teve com o atributo do contexto sendo trocado por outro servlet ... public synchronized void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException response.setContentType(~text/html"); PrintWriter out ~ response.getWriter(); out.println(~test context attributes<br>"); getServletContext() .setAttribute(~foo", ~22"); getServletContext() .setAttribute(~bar", ~42"); out.println (getServletContext () .getAttribute(~foo"»); out.println(getServletContext() .getAttribute(~bar"); o ave IItlcê Qct.a? IS+6 ctl"stt'itJ.t': (I !>t'c!;leifltJ. tJ d k;,"",,? c!;serlle "tJvQifltPrf-e c , N C(ldijtl t 0.$ fijVt'4S) CiJ,Sc"ac -fe"t.a ctt'iejtJ.. você está aquí •• 195
  • 224. não sincronizar o método de serviço Sittcrottizar O tltétodo de serviço ttão protegerá Utltatributo do cotttexto! Sincronizar o método de serviço significa que apenas uma thread de cada vez em uma classe do servlet pode estar rodando ... mas isto não impede outros servlets ou JSPs de acessarem um atributo! Sincronizar o método de serviço impediria outras threads do mesmo servlet de acessar os atributos do contexto, mas isto não fará qualquer coisa para interromper um servlet completamente diferente. ~ ~, X4.as lI<)ceI1tMlaNJ. #7aJaplv'a i'~eJi'1' tliS ()l.rr/t.O.5 sel'lIle.fs! I"Jepei"/Jel1fflltewH! J. ",.é-!-cJtlJs ç/tesel'lIlf" e~ tlJv.fI'IJS sel'vle-!-s eS-!-41 Client C SlI1CI'l:iI1i'~4JtJS t'Jl/ ç/i'$Sl:ijfJl/-!-l'tJs fl'ect.t!Js c..... V6ce ..J(! /J Si'#7Cl'tlJl1i'-;4r ~e-rtJJ/J ç/e sel'vljtIJJ jltlJce tJ .•••. N fi:"" il,ces SfJ tl.fJ~ tl.pIl'CtJ.j4fJ /";:0 afl'lbl/.fas ç/{J ctJl1ffxf. Ir: IlI4.PfbI/t. i/J Ci/Ji"/.ftl.I""el' I.."tele 3f.1t.t13l/er tJf.I.fl'/J ~fl..i/Jç/tJ as i"//JjlU' stJltcl.f/lg';es 3l/E; d.eJQl'ell tl.t!Jf!l'vle.f s A-. PaI'.ft1.n.foJ I"$.f/J IJe.A- pl'<)feJel' 6S J6 c<)nffx.f<) Je sel'eW QcessQ,«<)s P0l' WQ,t"$ Je 6 f.I~4 ft.l'flJ.« 1'<)«4"'1016 ""é.f6Jó de sel'lItj" 016 Sel'vle.f A-. 196 capítulo 5
  • 225. atributos e iísteners Você MO precisa de UIM loek .,0 servlet ... Você precisa do loek .,0 ootttexto! A maneira típica para proteger o atributo do contexto é sincronizar NO próprio objeto contexto. Se todos que acessarem o contexto tiverem que Pt4l'a tJS a.frlbfrl-tJs «4 primeiro receber o lock no objeto contexto, você C417+ex.fa; 174av.,. .«l.".f41' terá garantido que apenas uma thread por vez possa estar obtendo ou configurando o atributo do "t1.«4 si"I7C1'4"lj4r "4 SerlllffJ contexto. Mas ... ainda existe um se aí. Só funciona se p6is tJlI.fI'U pfJ.rffS «4 todos os outros códigos que manipulam os mesmos atributos do contexto TAMBÉM sincronizarem no 4p/'CfJ.jQtJ4''"11«4ser44 c4p.jes «e aces SI'U' " C4,,-fex+4! ServletContext. Se o código não solicitar o lock, ele ainda é livre para alcançar os atributos do contexto. Mas se você está projetando a aplicação, então você pode decidir fazer com que todos solicitem o lock antes de acessarem os atributos. public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException ( response.setContentType("text/htrnl"); PrintWriter out = response.getWriter(); out.println("test context attributes<br>"); Ajara es.fa"'4s I"ecde,,«a a 14CI: «'''ffa da CM-hx+4!! 1..s+fJ.é a "'4I7el"4 de pl"iJ-hjel' synchronized (getServletContext (» { getServletContext() .setAttribute("fo(~ . ~"es.fa«a «6 a+l"lbll+a ~ ". «a getServletContext () .setAttribute ("bar", "42"); C6,,-hX.f4. ~ce 1746Õller out.println(getServletContext() S.e."C/,,1"417"'f.e«( _ .getAttribute("foo)JJ; J +/,,;-S)) out.println (getServletContext () .getAttribute("bar"»; J: 3ve -hJf1CS C IIJcl: dIJ 3ve lI"'tl Vej es+aJf1óS ca"sfiJerlll7«6 clá"hx+c; Ôlle e"+l'e"'4S "a bl6C4 SIi1CI"617lia«,,; IJS Aguarde para ver muitos 1J.-/-"i"bV-i-4S«6 CM-hx+" esl-al"Qa safo"as códigos sobre segurança contra threads «e 6v-/-l'aS -/-/"I"f!!a«s a# da ÔVf!!S13.I"'al!Vlas No exame, você verá vários códigos 1;14c6 lf'I(Jf$ aV 1f'If!!"6S. Sall/as I $lof"11lc4 II ••• v mostrando estratégias diferentes para $1.l1/1Jle ôIJlJ.lõvel" aV+1"6 C6«ij6 óve criar atributos thread-safe. Você terá que rAM.$z./Lt IaS. sPlcl'a""ja{ã(J 176 descobrir se o código funciona, dado um Sf!!l"lIle-/-Cal7-hJc+ • determinado objetivo. O fato de o código ser li 4 I. I IV ••• legítimo (compila e roda) não significa que J'VI.as es-rfJ. e a lf'Ielt.fJr IJPSIlIJôIJe I/fJce vai resolverá o problema. C(J"Sf!!iV'" pal"lJ. +IJI'''o.l'' as o.:.J.l"lbv+IJS «6 CIJ,,-hx-/-ó +t.reo.d- sale. você está aqui ~ 197
  • 226. atributos de sessão e thread-safety Os atributos de Sessão são thread-safe? Pense um pouco. Ainda não falamos sobre as sessões HTTP em detalhes (falaremos no capítulo Sessões), mas você já sabe que uma sessão é um objeto usado para manter o estado de conversação com um cliente. A sessão persiste por várias solicitações do mesmo cliente. Mas ainda estamos nos referindo a um único cliente. Mas se é um cliente - e um único cliente só pode pertencer a uma solicitação por vez -, isso automaticamente já não significa que as sessões sejam thread-safe? Ou seja, mesmo que vários servlets estejam envolvidos, seja qual for o momento, só haverá uma solicitação de cada cliente ... então, apenas uma thread estará rodando naquela sessão. Certo? get JSP View Sólicl-l-"'jí!" 8 n.f'~o.tl8 ! Servlet B Embora ambos os servlets possam acessar os atributos da Sessão em threads separadas, cada thread pertence a uma única solicitação. Então, parece seguro. A não ser que ... Você seria capaz de pensar numa situação em que poderia existir mais de uma solicitação, no mesmo momento, do mesmo cliente? O que você acha? Os atributos de sessão são thread- safe mesmo? 198 capitulo 5
  • 227. atributos e lísteners Preste atenção em como.os nossos dois o que é REAlMENrE verdade sobre os faixas-pretas discutem as questões sobre atributos e a segura.,ça comra threads? como proteger o estado dos atributos contra os problemas de multi-threading . • ;. f, . "l i j~;;o Ji' :%,~-< ~~ ~ • Nós sabemos que os atributos de contexto NÃO são seguros por natureza, pois todos os trechos da aplicação podem acessar os atributos de contexto a partir de qualquer Sim, mestre. E eu sei que sincronizar o método solicitação (leia-se, qualquer thread). de serviço não é a solução, pois embora evite que o servlet sirva a mais de uma solicitação por vez, ele NÃO irá impedir que outros servlets e JSPs na mesma aplicação acessem o contexto. Muito bom. E sobre os atributos de Sessão. Eles são seguros? Sim, mestre. Eles servem para apenas um cliente e as leis da fisica evitam que um cliente faça mais de uma solicitação por vez. Você tem muito o que aprender, gafanhoto. Você não conhece a verdade sobre os atributos de sessão. Medite sobre isto antes de perguntar novamente. Mas mestre, eu tenho meditado e ainda não sei como o cliente poderia ter mais de uma solicitação ... Você deve pensar além do Container. Use a criatividade. Arrisque-se. Muito sábio conselho, mestre! Eu entendi! O cliente poderia abrir uma nova janela no browser! Então o Container ainda poderá usar a mesma sessão, embora venha de uma instância diferente do browser? Sim! O Container pode ver a solicitação da segunda janela como se viesse da mesma sessão. Logo, os atributos de Sessão não são thread-safe e eles também devem ser protegidos. Meditarei sobre esta questão ... E como você protege estes atributos de sessão contra o caos de várias threads? Ótimo! Sim, mas sincronizar o quê? Ah ... Eu devo sincronizar a parte do meu código que acessa os atributos de sessão. Do mesmo jeito que fizemos para os atributos de contexto. Eu devo sincronizar o HttpSession! você está
  • 228. sincronizar na sessão Proteja os atributos de sessão si.,crot'tiza.,do o HttpSessio., Observe a técnica que usamos para proteger os atributos de contexto. O que nós fizemos? Você pode fazer a mesma coisa com os atributos de sessão, sincronizando o objeto HttpSession! public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType(~text/html") ; PrintWriter out = response.getWriter(); out.println(~test context attributes<br>"); HttpSession session = request.getSession(); lJes+a ve")) It':s sl"ncI"IJltt")alYoas ;t) al(je+a synchronized(session) { session.setAttribute(~foo", ~22n); H#pses Si6ltJ PfJ.1"4 PI"()+e5el" 6S session.setAttribute(~bar", ~42"); tJ.+d!JV+6S oie sessã6 out.println(session.getAttribute(~foo"»; out.println(session.getAttribute(~bar"» ; Nil9 ex1st~m feth'untls ldí'9tas r: Isto não seria um desperdício? Seria, de fato, possível... que o cliente abrisse uma r: Não é ruim sincronizar código, já que causaria muito overhead e afetaria o nova janela no browser? processamento simultâneo? 1: Claro que sim. Certamente, você mesmo já o 1: Você deve SEMPRE pensar com cuidado fez sem pensar duas vezes - abriu uma segunda antes de sincronizar qualquer código, pois você está janela porque estava cansado de esperar pela certo - ocorrerá algum acréscimo no controle, na resposta da outra, ou porque você minimizou uma, aquisição e na liberação de locks. Se você precisa ou colocou a janela em lugar errado sem perceber, de proteção, use o sincronismo, mas lembre-se da etc. O fato é que você não pode arriscar quando regra-padrão para o uso de locks: mantenha o lock precisar de segurança contra threads para as suas o menor tempo possível para concluir sua tarefa! variáveis de sessão. Você tem que saber que é Em outras palavras, não sincronize aquele código perfeitamente possível para um atributo do escopo que não irá acessar o estado protegido. Faça com sessão ser usado por mais de uma thread em um que seu bloco sincronizado seja o menor possivel. determinado momento. Consiga o lock, entre, obtenha o que for preciso e saia para que o lock possa ser liberado e outras threads possam rodar o código. 200 capítulo 5
  • 229. Sit1gleThreadModel é desigt1ado a proteger as variáveis de it1stât1cia Stv strvle.f tieve esfe"tier " É isto que a especificação do servlet diz sobre a interface H-rrPServlef ••• SingleThreadModel (ou STM): ~ f.'-sa parfe prl;,etpQI••• terá a garantia de que dois encadeamentos não {fromjavax.servlet} «interface» HTTPServlet do SingleThreadMode, Assegura que os servlets lidem apenas MyServlet de pool deimplementar essa interface, método serão executados simultaneamente livre. servlet instâncias do servlet no você pode nova do servlet. O um servletdo acesso a umservico solicitação a contêinere enviando cada assegurar isso sincronizando o servlet "'- . ~.""Ifl.jServle+ ( '''Y''e*lf"ftJ. ;) SrM.J a !.~ Ctl""'T"l:/;,er dIA Wtb i'raI ti.sstjvrar ave esfe sf!rvlef Mas COlMO cOt1têit1erda Web assegura o fe"t.fJ, ape"fJ,s alie Ittlo,;' C"*1 que o servlet obterá apet1as UIMa lI*líl st:./lci'ftJ.jãl!Jtie Ch.dfl. vejo solicitação de cada vez? O revende dor do contêiner da Web tem uma opção. O contêiner pode manter um único servlet, mas colocar em fila cada solicitação e processar uma solicitação completamente antes de permitir que a próxima solicitação prossiga. Ou o contêiner pode criar um pool de instâncias do servlet e processar cada solicitação simultaneamente, um por instância do servlet. Qual estratégia STM você acha ser melhor? Ettvie solicifa9Ões através de UtM pool Coloque em fila todas •.. e <l c<l,,~"'el' da as solicitações Wd f."fl'f!5fraS I.l Request 1 (/*la ,"'sf~Clf4."(j J ~ Re uestl C.a"4I'f.&vesf é / ••.• ,,'2 " a"i';:'-<:>"I4"fI ~ 11IfI.••• // Request 2 ~ k;-.}~"'"'" 3 c.tJ."as(JI,CI'fagíI<:> 1I1J,i' p41"tJ. v~a l"'sf~ci'tJ. sepal"fJ.da Ja ~es~tJ sel"vlef você está
  • 230. request queueing ou serviet poofing Qual éa Ittelhor ilttplelttetttação SfM1 Mais uma vez, devemos consultar nossos mestres. Os caras devem saber qual é a melhor implementação STM. Iremos vê-Ios lutando para tomar uma decisão ... Coloque e'ft fila todas as solicitações Ettvie as solicitações através de U'ft pool Colocar em fila as solicitações em um único servlet faz mais sentido. Implementa claramente o que os escritores da especificação pretendiam. Mas mestre, o desempenho não sofrerá um impacto? Certamente, colocar em fila cada soli- citação impedirá que diversos usuários tenham acesso ao mesmo servlet? Sim, mas é o único modo de proteger as variáveis de instância do servlet. Mas mestre, o contêiner também pode criar um pool de instâncias do servlet. Então, o contêi- ner pode processar uma solicitação com uma instância do servlet e outra solicitação com uma segunda instância. Cada solicitação é lidada paralelamente. Ah, você vê profundamente no biscoito da sorte, meu aluno, mas não vê como poderia ser perigosa essa sorte ... Você fala por charadas, mestre. O que poderia dar errado, possivelmente, com a estratégia do pool? A especificação do servlet define que uma única declaração do servlet no descritor de distribuição toma-se uma única instância do objeto durante a execução, mas agora usando a interface STM, essa definição não é mais válida. Você pode ima- ginar uma situação onde ter diversas instâncias do servlet falha? Hmm, e se uma das variáveis de instância for para registrar quantas solicitações foram proces- sadas. A variável do contador teria diversas con- tagens diferentes e nenhuma delas seria correta ... apenas sua soma seria correta. SIM! Você entrou profundamente no ardil que é o pool de servlets. A semântica da definição de "uma instância do servlet" é perdida. O servlet perdeu a noção de realidade. 202 capítulo 5
  • 231. atributos e retguntétS l'li'l9 exlst~m Id'i9tétS r: Qual é o problema? servlet é tão insípida? Por que a especificação do ·. · · ......................... Você não precisa · · conheceras estratégias STM de 1: Os escritores da especificação queriam dar aos : contêiner para o exame. revendedores do contêiner a oportunidade de competirem: entre si em termos de desempenho e flexibilidade. : . b o SrM tenta protegI •Só preclsa sa er que 1 :•as vanav eis da instância do serv et. ., • r: Como sei qual estratégia meu revendedor usa? : •• •••••••••• . 1: Bem, felizmente está escrito em alguma parte da documentação para o contêiner da Web. Se não, você deve encontrar em contato com ele e perguntar. r: Como a estratégia STM mudará como escrevo o código de meu servlet? 1: Se o contêiner usar uma estratégia de fila, então, a semântica de "uma instância do servlet" ainda existirá e você. não precisará fazer nenhuma mudança no código. Mas se o contêiner usar uma estratégia de. pool, então, a semântica de algumas variáveis de instância poderá mudar. Por exemplo, se você tiver uma variável de instância que mantém um "contador de solicitações", então, essa variável não poderá mais ser contada quando diversas instâncias do servlet forem criadas no pool. Neste caso, você poderá escolher tomar a variável do contador uma variável de classe. Y: Mas as variáveis da classe têm um encadeamento seguro? 1: Não, não têm e o mecanismo STM não ajuda com as variáveis da classe. Sim, ele protege as variáveis de instância contra o acesso simultâneo, mas colocando no pool as diversas instâncias, a semântica do servlet muda. E mais, o STM não ajuda com os outros escopos da variável ou do atributo. Você está sozinho ... Marque com um X as opções que NÃO são thread-safe. (Nos fizemos a primeira.) r: É bom usar o SingleThreadModel? ~ Atributos do escopo contexto D Atributos do escopo sessão 1: Não, realmente. É por isso que o STM foi D Atributos do escopo solicitação desaprovado na API do servlet! D Variáveis de instância no servlet D Variáveis locais nos métodos de serviço "'" M.a.s lIacê .iiul4 preCiSo. D Variáveis estáticas no servlet saber pfJ.ra a eXfJ.iJ'Ie. você está aoui •. 21
  • 232. atributos request são thread-safe Apenas os atributos da Solicita~ãoe as variáveis locais são thread-safe! E pronto! (Nós incluímos os parâmetros do método quando dizemos "variáveis locais".) Todo o resto está sujeito à manipulação por várias threads, a menos que você faça algo para evitar. NQ9 exJst~m Terh'untels IdJ'9tél8 r: Então as variáveis de instância não são thread-safe? r: Mas se você não vai usar o SingleThreadModel e nem sincroni~ar o método de serviço, como você TORNA as variáveis de instância thread-safe? I: Isso mesmo. Se você tem vários clientes fazendo solicitações nesse servlet, significa várias threads rodando o código desse servlet. I: Não tem como. Observe um servlet bem E todas as threads possuem acesso às variáveis escrito e pode ser que você não encontre de instância do servlet, portanto, as variáveis de nenhuma variável de instância. Pelo menos não instância não são thread-safe. uma definitiva. (E sendo um programador Java, você sabe que mesmo uma variável definitiva ainda pode ser manipulada, a menos que ela seja r: Mas elas SERIAM thread-safe se você implementasse o SingleThreadModel, certo? imutável.) Então, não use variáveis de instância se você precisar de segurança contra threads, pois as threads para esse servlet podem sobrepor as I: Sim, porque você nunca teria mais de variáveis de instância. uma thread para o servlet, então as variáveis da instância seriam thread-safe. Mas é claro que ninguém mais aceitaria você no clube dos servlets novamente. r: Então, o que você DEVE usar se precisar que várias instâncias do servlet compartilhem algo? r: Eu só estava dando um exemplo. Como, "se alguém FOI estúpido o suficiente para I: Espera um pouco! Você disse "várias implementar o SingleThreadModel. ..". Não que instâncias do servlel". Nós sabemos que você não eu já tenha feito isso. Mas, já que estamos quis dizer isso, pois sempre haverá apenas UMA apenas levantando hipóteses ... se eu tivesse instância do servlet. Uma instância, muitas threads. um amigo que, digamos, sincroni~asseo Se você quiser que todas as threads acessem método de serviço, isso TAMBÉM não tornaria um valor, decida qual estado do atributo faz mais as variáveis de instância thread-safe? sentido e armazene o valor nele. Há chance de você resolver seus problemas de uma destas duas maneiras: I: Sim. Mas seu amigo seria um idiota. O efeito de implementar o SingleThreadModel é 1) Declare a variável como uma variável local quase o mesmo que sincronizar o método de no método de service, em vez de como serviço. Ambos podem "arruinar" a aplicação sem uma variável de instância. proteger o estado da sessão e do atributo. OU 2) Use um atributo no escopo mais apropriado. 204 capítulo 5
  • 233. Atributos da Solicitação e Request dispatchittg Cc,/c,3(1e6sdf4,J6S Os atributos da solicitação fazem sentido quando dt>~IJJeI6 ~6 esc6p6 você quiser que algum outro componente da aplicação assuma o controle de toda a solicitação II código em um doGet() J ou de parte dela. Nosso exemplo simples e BeerExpert be = new BeerExpert(); característico é uma aplicação MVC que inicia com ArrayList result = be.getBrands(c); d4 SIJ,'iCi..fo'C'iilJ v.- um servlet controlador, mas termina em uma view JSP. O controlador comunica-se com o modelo e request.setAttribute("styles", result); obtém os dados que a YÍewnecessita para construir C6~Sijo' (I~ dlSpo'..fct.el' par4 a resposta. Não há nenhuma razão para colocar os dados em um contexto ou atributo de sessão, já que só vale para esta solicitação. Desta forma, o RequestDispatcher11. vlew view = JSp' '--. ~ request.getRequestDispatcher("result. colocamos no escopo da solicitação. jsp"); Então, como fazemos para que outra parte do componente assuma a solicitação? Com um t view. forward (request, response); RequestDispatcher. Jl,{4~de () JSP ass(llVIll" o. SlJllcl+~i;lJ eJ aI. Si~ 11.3(11" eSh., .,s (Jt.;e..f.os S6Ilcl+4j8.lJ e JeesplJs+a. o O servlet Beer chama o método getBrandsO no modelo, que retorna e O servlet configura um atributo para a Solicitação chamado "styles". com alguns dados de que a view precisa. (Primeiro, ele coloca o "Moose Drool" em um ArrayList.) GetBrands( ) setAttribute("styles", results) ~ "Moose Drool" objeto Modelo e O servlet solicita ao HttpRequest um RequestDispatcher, passando em um e O servlet chama o forwardO no RequestDispatcher para mandar o JSP caminho relativo para a view JSP. assumir a solicitação. (Não mostrado: o getRequestD ispatcher( uriTo View) JSP recebe a solicitação encaminhada e obtém o atributo "styles" do escopo Solicitação.) Controller HttpRequest forward(request ,response) ;;:) Controller você está
  • 234. o Requestdispatcher o RequestUispatcher revelado o RequestDispatcher possui apenas dois métodos - forwardQ e includeQ. Ambos levam os objetos <<interfaee> > solicitação e resposta (os quais o componente que você RequestDispatcher está encaminhando precisará para terminar a tarefa). Dos dois métodos, o forwardQ é de longe o mais forward(ServletRequest, ServletResponse) popular. É muito improvável que você use o método include(ServletRequest, ServletResponse) inc1ude de um servlet controlador; porém, por debaixo dos panos, o método include está sendo usado por JSPs na ação-padrão ~sp:include> (que nós revisaremos no capítulo 8). Existem duas formas de conseguirmos um RequestDispatcher: através da solicitação ou do contexto. Independentemente de onde ele venha, você deve informar a ele para qual componente web você está encaminhando a solicitação. Em outras palavras, o servlet ou o JSP que assumirá o controle. Obtendo o RequestDispatcher através de um ServletRequest RequestDispatcher view ~ request.getRequestDispatcher(~result.jsp"); O método getRequestDispatcherO no ServletRequest usa um caminho String para o recurso o qual você í L' .~ s-n,: e Vir! C41r!111t.(J relo.+,vl:I . . "" , <,1:11:5' "'a 11.i1(J está encaminhando a solicitação. Se o caminho l1ei11t.vlMo. barra ( u/" íl1h{JJ ) l"i11i'clo.l). começar com uma barra ("/"),0 Container entende l1esff C4SlJ (J Cl1l1+41"i11er 1'11ClIra e/i) como "iniciar a partir da raiz desta aplicação".. f>, f> Se o caminho NÃO iniciar com uma barra, ele é resvl+,:jSf> i11l1,eslMC IlISar IC5'cC ~(.Ie " considerado como relativo à solicitação original. fi. S6IiC{+4{;" es-h-lIel' 1"i11sf,rl41fl.. (lJf.s Mas você pode tentar enganar o Container a olhar ~ raifJ.I'f:1M6S li J J tI . _ '. I' , l. • I ••1r!",ero.,,,,es S():TI't. ()S ca""I1"'''s para fora da aphcaçao atual. Ou seja, so porque voce I I tem muitas " ..!..!..!", não significa que vá funcionar I'ela+llll),s e I),S luSares 165'C()S i11(JtJpll-ula c se ele alcançar além da raiz da sua aplicação atual! s(JIJI'f! bi's+rtIJu1f/4(J) Obtendo o RequestDispatcher através de um ServletContext RequestDispatcher view = getServletContext() .getRequestDispatcher(~/result.jsp"); Assim como o método equivalente no ServletRequest, este método getRequestDispatcherQ usa um caminho String ~ce "bf.ví IJsar fi. barra C{J'" (J para o recurso o qual você está encaminhando a solicitação, EXCETO se você não puder especificar um caminho relativo 1M:+I:I41(J e+Jt.etpesl-btsf>t1.+cl.erO S ao recurso atual (aquele que recebe a solicitação). Isto 4lIJ ServleiC()i11+elc+. significa que você deve iniciar o caminho utilizando a barra! Chamando o forward() no RequestDispatcher view. forward (request, response); Simples. O RequestDispatcher que você obteve através do contexto ou da solicitação conhece o recurso que você está encaminhando - o recurso (servlet, JSP) que você passou como argumento para o getRequestDispatcherQ. Então, você está dizendo: "Ei, RequestDispatcher, por favor encaminhe esta solicitação para aquela coisa que eu disse anteriormente (neste caso, um JSP), quando nos falamos pela primeira vez. Eis a solicitação e a resposta, pois esta nova coisa vai precisar delas para terminar de tratar a solicitação." 206 capj;tuJo 5
  • 235. o que há de errado COilteste código? o que você acha? O código deste RequestDispatcher parece que funcionará do jeito que você esperava? public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException response.setContentType(~application/jarff); ServletContext ctx ~ getServletContext(); InputStream is = ctx.getResourceAsStream(~bookCode.jarff); int read ~ o; byte[] bytes new byte[1024]; St/ftmkfJ. ót/E' OutputStream os = response.getOutputStream(); 1"$+" tt/"d""fJ, whi1e «(read ~ is.read(bytes)) !~ -1) { oS.write(bytes, o, read); } os.flush(); RequestDispatcher view ~ request.getRequestDispatcher(~result.jspff); view. forward (request, response); os. close (); Você vai receber Uilt ettorilte lIIegalStateExceptiott! Você não pode transferir a solicitação se você já r: Como você não falou sobre o método includeO do RequestDispatcher? submeteu uma resposta! E por "cubmeteu uma resposta" e~tend~ como, "enviou a resposta para o cliente . 1: Um dos motivos é porque ele não está no exame. Outro: nós já mencionamos que ele não é Observe o código novamente. O grande muito usado na vida real. Porém, para satisfazer problema é: a sua curiosidade, o método includeO envia a solicitação para outro lugar (geralmente outro os .flush () ; servlet), para realizar alguma tarefa e então voltar para o remetente! Em outras palavras, significa Esta é a linha que jaz com que a que o includeO pede por ajuda no tratamento resposta seja enviada ao cliente e, ,neste da solicitação, mas não chega a ser uma ajuda ponto esta respostajoi CONCLUIDA. completa. É apenas uma transferência de controle TERMINADA. JÁ ERA. Possivelmente, temporária, e não, permanente. Com o forwardO, você não poderá encaminha~ a ." você está dizendo: "É isso aí, eu não vou fazer solicitação neste estágio, pOIS.ela ja, e mais nada para processar esta solicitação e esta história! Você já respondeu e ISSOso resposta." Porém, com o includeO, você está acontece uma vez. dizendo: "Eu quero que outra pessoa faça algumas coisas com a solicitação e/ou resposta, mas quando ela terminar, eu mesmo quero acabar de tratar a Então, não seja iludido por. q~est~es solicitação e a resposta (embora eu talvez queira do exame que enviam a solzcltaçao DEPOIS da resposta ter sido fazer outro include ou forward depois disso ..."). enviada. O Container vai mostrar um IllegalStateException. você está
  • 236. respostas do exercício iístener Relembrando os Listeners RESPOSTAS ExetcÍd9S Listeners de atributos 5erllle+it-e3ve s+A-#ri"bv..feLi's..fel1er 5ervle+C~P1..fex+A-#rt!Jv+eLts+ePler H#p5es siiJl1tJr#rt!Jv+eLts..fel1er Outros listeners do ciclo devida Métodos em todos os a.ffrt!Jv+eA-Jt1etlO listeners de atributos affrt!Jv+eit-ew.lJveJO (exceto binding listener) affrt!tv..feit-epI4cet10 Eventos do ciclo de vida N I I relacionados às sessões tJl1Je a. segalJ e cr''"4tltA; IJ"'IJe e e (exceto eventos relaciona- ses siâ"'lCrea+eJO dos aos atributos) quando a sessão é criada e quando ses st"ól1lJes+rlJjeJO ela é destruída Eventos do ciclo de vida relacionados às solicitações (exceto eventos relacionados aos atributos) quando a sessão é inicializada ou destruída Eventos do ciclo de vida relacionados ao contexto wt.e"'l +t.e ceu'rf-ex+l's ,.",.+lalljeJ e.r Jes+re.jeJ do servlet (exceto eventos CÓI1-hx+II'I,--I-l4't;f.JO relacionados aos atributos) quando o contexto é ctJ~x+lJes+r~jeJO inicializado ou destruído 208 capj!tulo 5
  • 237. atributos e Iísteners Escopo Atributo RESPOSTAS é des+rv{,J<l/elIi1'lIJ. vive) Acessibilidade / S1I4r14 variás as e lJ""Pru que em C611+e1l.,(4 Se <ill';;clUll1dl.lN!.CflI'SCS Para!JadlJsEscopoc<J"Iex::es CÕ"'IIH!f'Sa N+,/ apel1IJ.sserveSesS4lJlIi1'la 3ue'"aliviii" de dad4sJ de (por6S l1I'JiI'les .,(lslmclli. 114fJ I'r /;(J'" tempo quanto tM!it>f't.rJ. CtliI'l4-h-..e-et,;+, l'I"btll.,(lJ.. "P"ca]"6 I';;etvll'l.,(o sel'vMIJi" 3t1e Sijl1l"1lcaIJ.CeSS6 as~tfJr'54seI'de <l .,(~4~.,./-ea <ilf.l 4ptiC4í44jeSS46~ Sl""f'eS~~ sess46 rela-h-vese+c f4t'~INJSvlfia f4t'Serv1e.fC6J?-h!X+j C~ (,I'" V,",,4.,(aseSSM. .,(esl-f'u!Ja re3l1ef' JAl!JI;s clltPJ+e, ti;;, .,(es+e 6Sve Sve de e-iI'laN; clle#l-h!j ~14 1'itJ.6 +eit>f'IJ e d" tllWJ. Jt.eCIIf'SIJS .,(IJ. I.u:,kllp S6/iél+o.544, a PI'65I'4IWJ.iW 46 /;a11C6.,(e • eJ?.,(eresI'Js tA 4pllé,'i6 catrj Õ I,;;.f-el"a sel'vle+ .,(4 JSP CIJ""PIJ.f'-I-t"It.eJ f;{v#J?per p4f'.f-e <!li f;{v4t311IY' Solicitação Passar I'r vlfia da Scll'cl+IJ.!j'ifJj 3l1e s'j"ltli(;a a+: ti It", S6/;l'e 4 ;;'4.,(tl() .,«) N /} .,(IJ. xecujalJ dlJ ",erlJdó e c6"1+rlJlad4f' pfJ.l'IJ. ti. servlce() .,(6 Servle+. IlftW ••• 41/ (J8I+I'4 .,(t!d4 011S~4; .,(lIra~ a Vlfia .,(a +t.I'ea.,( (ptlt.l)) ptu'a ti de f/"el' d',el't s/!I'vle+s tiS 3ve es+tver +rtJ.+fJ.J?.,(4 €IJ/) cll"eI1-h!. pat'1J. 61'1de a esh s()llct+a{l4. Ié/' e"'lC41JlJ",t.a.,(1J, (,ISGl"ld" s relacicl'lti.,(6S ~ S4Ilét+tUj'i"". aqui •• 209
  • 238. imã de geladeira - respostas dos exercícios ~ Ímã de Gelcidelt'l RESPOSTAS (configurando um parâmetro de contexto no DD) !<web-app ". > I <servlet> I 1---------------------1 . I BeerTest <servlet-name> . </servlet-name> I . I <servlet-class> II-c-o-m-,w-l-·c-k-e-d-l-y-S-m-a-r-t-.B-e-e-rT-e-st-e--r </servlet-class> 11 I I </ servlet> I I <context-param> I I <param-name> I I </param-name> I <param-value> I I </param-value> I !</context-param> I !</web-app>1 Não usados: </init-param> o <.t"r-l-pfJ.I"fJ.h> é (,ISfJ.tilJ pal"~d;l"lJs ,;"Y- ti6 sel"lIl&; "';6 tilJ CIJ,,+eX+6. e"c(m+l"fJ. " <:'1;,t.f-PfJ.1"41f!l> tie"+l"fi tie (,111I <:.servle+>. [<servlet-param> I A1';1> exish Ifo.tiaPl4l"tc"ti(J CI>III <.servle+-pI4NJ.!!/I>. 210 5
  • 239. fausa pata 9 caté 1Usando um RequestDispatcher, o uso de qual dos métodos pode nos levar a uma IllegalstateException? (Escolha todas as que se aplicam.) DA. read DB. flush DC.write Dn. getOutpuStream DE. getResourceAsStream 2 Quais declarações sobre os parâmetros de inicialização do ServletContext são verdadeiras? (Escolha todas as que se aplicam.) DA. Eles devem ser usados para dados que raramente mudam. DB. Eles devem ser usados para dados que freqüentemente mudam. De. Eles podem ser acessados usando o ServletContext. getParameter () . Dn. Eles podem ser acessados usando o ServletContext. getIni tParameter () . DE. Eles devem ser usados para dados que são específicos de um determinado servlet. DF. Eles devem ser usados para dados que servem para toda a aplicação. você está aqui.. 211
  • 240. teste preparatório 3 Quais tipos definem os métodos getAttribute () e setAttribute () ? (Escolha todas as que se aplicam.) elJ.Httpsession elB. ServletRequest OCo ServletResponse elD. ServletContext DE. ServletConfig elE SessionConfig 4 Se um servlet for invocado usando-se o método forward ou include do RequestDispatcher, quais métodos do objeto solicitação do servlet podem acessar os atributos da solicitação configurados pelo container? (Escolha todas as que se aplicam.) QJ. getCookies () DE. getAttribute () elc. getRequestPath () DD. getRequestAttribute () DE. getRequestDispatcher () 5' Quais chamadas oferecem informações sobre os parâmetros de inicialização que podem ser usados por toda a aplicação? (Escolha todas as que se aplicam.) DA ServletConfig.getlnitParametersO D B. Serv letContext.getInitParametersO Dc. ServletConfig.getlnitParameterNamesO uD. ServletContext.getInitParameterNamesO DE. ServletConfig.getInitParameter(String) DE ServletContext. getInitParameter(String) 212 capítulo 5
  • 241. atributos e listeners 6 Quais declarações sobre os listeners são verdadeiras? (Escolha todas as que se aplicam.) DA. O ServletResponseListener pode ser usado para executar uma ação quando uma resposta do servlet foi enviada. DB. O HttpSessionListener pode ser usado para executar uma ação quando der time-out no HttpSession. De. O ServletContextListener pode ser usado para executar uma ação quando o contexto do servlet estiver prestes a ser encerrado. DD. O ServletRequestAttributeListener pode ser usado para executar uma ação quando um atributo tiver sido removido do ServletRequest. DE. O ServletContextAttributeListener pode ser usado para executar uma ação quando o contexto do servlet tiver sido criado e estiver disponível para servir à sua primeira solicitação. 1 O que seria mais coerente de ser armazenado como atributo no escopo sessão? DA. A cópia do parâmetro de uma query que o usuário digitou. DB. O resultado de uma query ao banco de dados para ser retomado imediatamente ao usuário. De. O objeto da conexão com o banco de dados usado por todos os componentes da aplicação. DD. Um objeto representando um usuário que acaba de se logar no sistema. DE. A cópia do parâmetro de inicialização recuperado de um objeto ServletContext. você está aqui I!" 213
  • 242. teste creparatório 8 Dado o código de um HttpServlet válido que também foi registrado como um ServletRequestAttributeListener: 10. pub1ic void doGet(HttpServletRequest req, HttpServ1etResponse res) lI. throws IOException, ServletException { 12. req.setAttribute(~a", ~b"); 13. req.setAttribute(~a", ~c"); 14. req.removeAttribute(~a"); 15. } 16. public void attributeAdded(ServletRequestAttributeEvent ev) { 17. System.out.print(~ A:" + ev.getName() + ~->" + ev.getValue()); 18. } 19. public void attributeRemoved(ServletRequestAttributeEvent ev) { 20. System. out .print (~ M:" + ev. getName () + ~->" + ev. getValue ()); 2I. } 22. public void attributeRep1aced(ServletRequestAttributeEvent ev) { 23. System.out.print(~ P:" + ev.getName(} + ~->" + ev.getValue()); 24. Qual dos logs é gerado? C)Pl.A:a->b P:a->b C)B. A:a->b M:a->c C)C. A:a->b P:a->b M:a->c C)D. A:a->b P:a->b P:a->null C)E.A:a->b M:a->b A:a->c M:a->c C)F.A:a->b M:a->b A:a->c P:a->null 9 Ao declararmos um listener no DD, quais subelementos do elemento <listener> são necessários? (Escolha todas as que se aplicam.) CJPl.<description> OB. <listener-name> CJC. <listener-type> CJD.<listener-class> CJE. <servlet-mapping> 214 capítulo 5
  • 243. atributos e físieners 10 Quais tipos de objetos podem armazenar atributos? (Escolha todas as que se aplicam.) 01. ServletConfig DB. ServletResponse Oc. RequestDispatcher OI>.HttpservletRequest OE.Httpsessioncontext 11 O que é verdade? (Escolha todas as que se aplicam.) DA Quando uma aplicação está prestes a ser encerrada, o pedido de notificação do listener não é garantido. OB. Quando um evento que aceita um listener ocorre, o pedido de chamada do listener não é previsível. Oe. O container registra os listeners baseado nas declarações do deployment descriptor. DI>. 1penas o container pode invalidar uma sessão. 12 Quais declarações sobre o RequestDispatcher são verdadeiras (quando verdadeiras, considere que o RequestDispatcher não foi obtido via uma chamada ao getNamedDispatcher (»)? (Escolha todas as que se aplicam.) 01. O RequestDispatcher pode ser usado para encaminhar uma solicitação a outro servlet. DE. O único método na interface do RequestDispatcher é o forward (). De. OS parâmetros especificados na query string usada para criar o RequestDispatcher não são encaminhados pelo método forward () . DI>. O servlet para o qual uma solicitação é encaminhada pode acessar a query string original, chamando o getQueryString () no HttpServletRequest. DE. O servlet para o qual uma solicitação é encaminhada pode acessar a query string original, chamando o getAttribute("javax.servlet.forward.query_stringU) no ServletRequest. você está ~ 215
  • 244. teste preparatório 13 Qual é a maneira recomendada para lidarmos com segurança de servlets e threads? DA. Fazer com que o código do servlet estenda ThreadSafeServlet. DB. Fazer com que o servlet implemente o SingleThreadMode1. Dc. Logar todas as chamadas dos métodos. DD. Usar exclusivamente variáveis locais, e se você tiver que usar as variáveis de instância, sincronizar o acesso a elas. 14 Dados os seguintes métodos: - ggetCookies - getContexPath - getAttribute Coincida os métodos acima com as seguintes classes ou interfaces. Note que cada método pode ser usado mais de uma vez. HttpSession ServletContext HttpServletRequest 15 O que é verdadeiro sobre a interface RequestDispatcher? (Escolha tudo que se aplica.) DA. De seus dois métodos, forward( ) é usado com mais freqüência. DB. Seus métodos têm os seguintes argumentos: recurso, solicitação e resposta. De. Dependendo da classe cujo método cria um RequestDispatcher, o caminho para o recurso a ser enviado mudará. DD. Independentemente da classe cujo método cria um RequestDispatcher, o caminho para o recurso a ser enviado NÃO mudará. DE. Se seu servlet chamar RequestDispatcher.forward, poderá enviar sua própria resposta para o cliente antes, mas não depois da chamada de envio. 216 5
  • 245. atributos e listeners Pausa pata o caté 'R~-~5 1Usando um RequestDispatcher, o uso de qual dos métodos pode nos levar a uma IllegalStateException? (Escolha todas as que se aplicam.) DA. read litl"B. flush litl"c. write lJlj<j(4 IlIeiafS+a-hf.xce,-h..,,, , ti é ti catlsada o 'l.tla"da tllj<ja , res,as+tJ.j4 lat Calj<je+M4 ,41"4 a ette,,+e (6 lj<je+fJdfJ DD. getOutpuStream Iftlst. 14; tsstJJ e vacê -h"+4 14;U' tllj<j lanli4rd, DE. getResourceAsStream 2 Quais declarações sobre os parâmetros de inicialização do ServletContext são verdadeiras? (Escolha todas as que se aplicam.) litl"A. Eles devem ser usados para dados que raramente mudam. DB. Eles devem ser usados para dados que freqüentemente mudam. Dc. Eles podem ser acessados usando o ServletContext.getParameter(). litl"D. Eles podem ser acessados usando o ServletContext. getlni tParameter () . DE. Eles devem ser usados para dados que são específicos de um determinado servlet. litl"F. Eles devem ser usados para dados que servem para toda a aplicação. A- a'fã" $ es+: 'Í7CQN'e.f4.J>(Jr'!JtlfQS'4r~e+ras f 'Í7t+ da Serllfe+Caw!-ex+ , N sa" 'M(JS "4 /,(JNJ.lj<j Sii:J f /I i ' e tl t..(J/I'f"f'fJ,IÍ7er';'icta't"f;tJ.dc. A- c'f';c C es+: lÍ7cCI'I"e.fl; PIJI"3ve es-h Ir!:+IJd(J ,,'ia ex,"s-h. í A- af>S';(J es+: 'Í7cal"l"e.fl;f>IJI"1Jtle s~ ei'u"s+e Vir! ól6e+a Sel"lIfe+CIJ,,-hx+ ,aI" apfif:4s';a. você está '" 217
  • 246. teste preparatório 3 Quais tipos definem os métodos getAttribute () e setAttribute () ? (Escolha todas as que se aplicam.) I,;? A. HttpSession I,;? B. ServletRequest OCo ServletResponse I,;? D. ServletContext DE. ServletConfig DF.sessionconfig 4 Se um servlet for invocado usando-se o método forward ou include do RequestDispatcher, quais métodos do objeto solicitação do servlet podem acessar os atributos da solicitação configurados pelo container? (Escolha todas as que se aplicam.) DA. getCookies () I,;? B. getAttribute () De. getRequestPath() OD. getRequestAttribute () DE. getRequestDispatcher () - Ir IJpjãlJ 8 apl"ese1'l.ffl. " "",é.fiJiJiJ CM'l"e.ftl. C,,"'" ele; vlJcê plJJe fl.cesstJ.1" IJS 1J..fI",1;v.fIJS pl"ee"ct.MlJs iJlJ CI:m.fo.ll1el"jfl.llf1.x.sel"lIlff./lJl"wtJ.I'J.x.xx e jfl.vfl.x.se I"vle-J-.,;'c/vde.X.xxx. - Irs iJpj6eS C e lJ se I"elel'el/ll fi. l/IIé-I-iJiJiJS~ve "ãiJ exi's.fel/ll. 5 Quais chamadas oferecem informações sobre os parâmetros de inicialização que podem ser usados por toda a aplicação? (Escolha todas as que se aplicam.) DA. ServletConfig.getlnitParametersO DB. ServletContext. getInitParametersO Irs iJPj6es Ir e 8 es.fãlJ ,;,clJl"I'ehs; Dc. ServletConfig.getInitParameterNamesO piJl"~ve es.fes l/IIé.fiJJiJS PJãlJexts.fel/ll. I,;? D. ServletContext.get1nitParameterNamesO - Irs iJpj6eS C e f. es.fQiJ ';'C6I"1'fffl.S; DE. Serv letConfig. getlnitParameter( String) plJl"iVe iJlel"ecel/ll fJ.ceSSIJfl.iJS l(. i ,..; I,;? F. ServletContext.getInitParameter(String) pfl.l'fI."'te-rl"lJs iJe ';'lci'fI.'i';fl.jfl.lJ espec,llclJS iJ6 sel"vle.f. 218 capítulo 5
  • 247. atributos e Iísteners 6 Quais declarações sobre os listeners são verdadeiras? (Escolha todas as que se aplicam.) (5el"vle.f. V2., ti; p~. 80) DA. O ServletResponseListener pode ser usado para executar uma ação quando uma resposta do servlet foi enviada. fil E. O HttpSessionListener pode ser usado para executar uma ação quando der time-out no HttpSession. fil c. O ServletContextListener pode ser usado para executar uma ação quando o contexto do servlet estiver prestes a ser encerrado. fil D. O ServletRequestAttributeListener pode ser usado para executar uma ação quando um atributo tiver sido removido do ServletRequest. DE. O ServletContextAttributeListener pode ser usado para executar uma ação quando o contexto do servlet tiver sido criado e estiver disponível para servir à sua primeira solicitação. If iJp{ãiJ If es-/-: ii'lcIJl"l"e-/-a; PiJl"1Jve ,,'i.iJ se I"elel"e a v~a 'i1hl"iace diJ 5el"vle-l-/t.espiJ"seL.i"sh"lel" • If iJPf'i.lJ f. es-l-: ,i1cIJl't'e-l-tl; plJl"'/;ve vsal":altifJs Vlti 5el"vle.f.CfJ"hx-/-L,"sh"lf!1" pal"ti. es-l-e pl"fJp:Sl-l-IJ. 1 ODA. seria mais coerente de ser uma query que o usuário digitou. que A cópia do parâmetro de armazenado como atributo no escopo sessão? V (5el"vle-l- 2..,IJ I'fAj' J , S"8J DE. O resultado de uma query ao banco de dados para ser retomado imediatamente ao usuário. Dc. O objeto da conexão com o banco de dados usado por todos os componentes da aplicação. fil D. Um objeto representando um usuário que acaba de se logar no sistema. DE. A cópia do parâmetro de inicialização recuperado de um objeto ServletContext. - If fJPf'i.fJ If es-/-: li1CiJl"l"e-l-a; I'fJl"'/;fle IJ pal"M"e+l"fJ de Vlti4 ~Vff!l"j é 5el"alltie,,-I-e ltial"s flsadiJ ptt.NJ. I"eali,al" Vltit.lfJPff!I"t.lf'i.fJ. If fJPf'i.fJ 8 es-l-: 'i1CIJl"I"e-/-a;pIJI"3f1e -I-af dtJ.da 5ff!I"lJ.fltif!I'rh é l'ltiedta-/-fl./I!e,,+e l"e-l-al""ItJ.JfJ iJfI tJ.1"1tifl.je'llJ.JfJ eSCIJpfJSIJIi'ci"-I-af'i.fJ. '14 A. IJPftJ.aC es-rtJ. li1CIJI"I"e-r~ p41"'/;ve 9tJ.3ve '1aIJ e especIllcIJ 1"f ". I' - 1- '". / , de VItiIJ. Jehl"lti/i1lJ.JIJ. sess'i.tJ.> ele Jevel"i"IJ. seI" IJ.1"1titt.je'llJ.JIJ esclJf" /'Ia CI)i'1+ex-l-fJ. If fJPj'i.l) í es-/-: li1ClJl"l"e-l-~ plJl"'/;ve fJSptJ.I"M"e.f.1"6S J6 CM+eX-l-iJ Sf!I"VIe.f. Jevel"lalti es .. l" h '16 6tje-l-6 5el"vle-I-C61'1+ex-l-. você está aQui.. 219
  • 248. teste preparatório 8 Dado o código de um HttpServlet válido que também foi registrado como um ServletRequestAttributeListener: 10. pub1ic void doGet(HttpServletRequest req, (.sel"v'dv2..~p~. 799-2.00) HttpServletResponse res) 1l. throws IOException, ServletException { 12. req.setAttribute(~a", ~b"); 13. req.setAttribute(~a"r "e")i 14. req.removeAttribute(~a"); 15. } 16. pub1ic void attributeAdded(ServletRequestAttributeEvent ev) { 17. System.out.print(~ A:" + ev.getName() + ~->" + ev.getVa1ue()); 18. } 19. pub1ic void attributeRemoved(Serv1etRequestAttributeEvent ev) ( 20. System.out.print(~ M:" + ev.getName() + ~->" + ev.getValue()); 2l. } 22. public void attributeReplaced(ServletRequestAttributeEvent ev) ( 23. System.out.print(~ P:" + ev.getName() + ~->" + ev.getVa1ue()); 24. Qual dos logs é gerado? Pe5aJ,i,f"a! tJ lt1é-!-~J"5e#altle l"e-f.iJl"J'lf4. " vs.l~1" IJrlJr'Z/;tJ da 1J.-!-l"iÍ1l1-!-" es-h tal' se DA. A:a->b P:a->b slIbhl-tlida. DB. A:a->b M:a->c ~e.A:a->b P:a->b M:a->c DD. A:a->b P:a->b P:a->null DE.A:a->b M:a->b A:a->c M:a->c DF.A:a->b M:a->b A:a->c P:a->null 9 Ao declararmos um listener no DD, quais subelementos do elemento <listener> são necessários? (Escolha todas as que se aplicam.) DA. <description> DB. <listener-name> De. <listener-type> ~D.<listener-class> I I O stl/;elelt1eJ'l-!-"<.lfs+enerclass"> e " uAJ'ZCO elelt1en-l-" DE. <servlet-mapping> ,i,di'spens:vel d6 elelt1f!n';'" <.Ii's+enel'">. 220 capituio 5
  • 249. atributos e !ísteners 10 Quais tipos de objetos podem armazenar atributos? (Escolha todas as que se aplicam.) [J1.servletConfig OB. ServletResponse De. RequestDispatcher Iit? D. HttpServletRequest [JE. HttpSessionContext fJ(j"t-a: Os óV+-l'óS Jóis '/-'j>(;S I'elel"e~s lJ.ó sel"vle+- 3ve PI}Je'hII al"IfIa-;eJ7lJ.1' tJ.+-I"rbv+-ós sã., tJ ##pSess/()J7 e 6 Sel"vle..j.Ctil1fflf--l. 11 O que é verdade? (Escolha todas as que se aplicam.) (Sel"vle-l- ·i2..~p~s. 87 tJ. DA Quando uma aplicação está prestes a ser encerrada,;; IJrs aF{;es A- e 8 es+';e pedido de notificação do listener não é garantido. ,;,cóI"I"e+as;póI"3ve 6 ctm+tJ.I;,er DE. Quando um evento que aceita um listener ocorre, o VS4 ó lJb pal"a Jeh;,tt' li. pedido de chamada do listener não é previsível. I}t'Jelfl Je J76+,"Ii'ca{itJpal"a tJS Iit? c. O container registra os listeners baseado nas li'sffJ7et's t'f!!5iS+t'IJ.d()s. declarações do deployment descriptor. lJr cp{ió lJ es+: t#1CfJt't'ef-t4; DD.1penas o container pode invalidar uma sessão. ptir'lpe Vht set'vlef- pade ii1Vt4IMlJ.r ti vlfla ses s';tJ VStJ.#1Jó /iVlé-I-(jdlJ H.f..i.p.5eSSi'611.,;'VQ.lidtJ.+eo. 12 Quais declarações sobre o RequestDispatcher são verdadeiras (quando verdadeiras, considere que o RequestDispatcher não foi obtido via uma chamada ao getNamedDispatcher ())? (Escolha todas as que se aplicam.) (.5erll Ie-r 112..[J / J P"5. J r Iit? 1. O RequestDispatcher pode ser usado para encaminhar uma solicitação a outro servlet. DE. O único método na interface do RequestDispatcher é o forward (). De. OS parâmetros especificados na query string usada para criar o RequestDispatcher não são encaminhados pelo método forward () . DD. O servlet para o qual uma solicitação é encaminhada pode acessar a query string original, chamando o getQueryString () no HttpServletRequest. Iit? E. O servlet para o qual uma solicitação é encaminhada pode acessar a query string original, chamando o getAttribute ("javax.servlet. forward.query_string") no ServletRequest. lJr 6p{i6 8 es+: I;'COl"I"ef-s.,; p(jr~ve tJ.,;,fft'lo.ce +tJ.lflb~IfI P/JSSi/i' Vif if~+/JJo ,;'c/vJe. lJr 6PS';ÓC es+: i'l'1c(jt't'e+-4;pórói/e eSffs PQ.t';""ef-t'tJs sel"â'/Jel'1caif,;,t.ad6S I'l'f!s+e C4StJ. - lJr lJPjâ'/J b ~ ti1ctJrl"e+o.P/JI"f/,'f!!es se IfI~+tJdtJt'e+Ct'I1Q.Q. s+t'l;'5 de cO'lsvl-/-a '10 pQ.Jt'ão uJeL o. parl-tt' dtJ Jee'/;vf!s-l-btspa-l-ct.et'. você está aqui ~ 221
  • 250. teste prepaíBtório 13 Qual é a maneira recomendada para lidarmos com segurança de servlets e threads? ú!speciflcll.gíió d6 Se"'lIle.f; p:.,. 2.7) DA. Fazer com que o código do servlet estenda ThreadSafeServlet. DE. Fazer com que o servlet implemente o SingleThreadMode1. Dc. Logar todas as chamadas dos métodos. 12' D. Usar exclusivamente variáveis locais, e se você tiver que usar as variáveis de instância, sincronizar o acesso a elas. - IJrs lJ/,f6es lJr e 8 síilJ tm::6f'N!.ffl.S plJt''!re IJ rt.,..ell.dSo.feSe,..vle.f ",íi/J exts-h ",a Se,..ille.f. IJrPI e IJ Sl"'5IeFt."'efJ.JMlJdel é tiesap,../JiladlJ ",4 vet'síi/J 2..'-1 e ",íi., ,..ec6J/11eJ'1dll.d.,. 14 Dados os seguintes métodos: - ggetCookies - getContexPath - getAttribute Coincida os métodos acima com as seguintes classes ou interfaces. Note que cada método pode ser usado mais de uma vez. HttpSession '"5tt/lf:f.r:!:~~h. ... ServletContext ...j.t:I:ft.H:r.fhl.f.e..o. .5~~.'J.-k~fP.~f1.:. . HttpServletRequest o •• 1-t:ft..~~!:,,!:~ . ..J.~ft.Hr.(~.I!.-k .... AJes-h ~6J'1.f6J "'ealJ/lleJ'1.f.eJ'1íiIJ deve havet' J/IIf!.J/lla"")ll.jíi6 fl.SS,M. C6J/11<::1 1Jtl4is m.e.ft:iJlJs fa,..tam. Sf!.",.f.,fÁlJem. cadll. esccfc. 15 O que é verdadeiro sobre a interface RequestDispatcher? (Escolha tudo que se aplica.) 12' A. De seus dois métodos, forward( ) é usado com mais freqüência. I DE. Seus métodos têm os seguintes argumentos: recurso, - Df}íi., 8: 6 t'ectlt'sõ e solicitação e resposta. espec'-ficlt.JlJ '16 m.cl'iflePl.f-óda lllJ C . D epen d en d o dI' c asse cUJometo d o cna um 1:""7 a . . C"','"4jíi., d., .,Qie.f6. v RequestDispatcher, o caminho para o recurso a ser enviado mudará. - Dffíi., ~: se set/ set'lIle.f DD. RequestDispatcher, Independentemente da caminho para o recurso aum enviado o classe cujo método cria ser t/sa,.. I t/1iO'l j!!./); I7t1P1ca I NÃO mudará. f'6tie,..a el7l1''"4,.. StliJ, DE. Se seu servlet chamar RequestDispatcher.forward, poderá ,..eSf'6s.fa. enviar sua própria resposta para o cliente antes, mas não depois da chamada de envio. 222 capítufo 5
  • 251. 6 betenclétment9 da sessã9 Estado de conversação Os servidores web não têm memória curta. Assim que eles lhe enviam uma resposta, eles esquecem quem você é. Na próxima vez que você fizer uma solicitação, eles não o reconhecerão. Em outras palavras, eles não se recordam do que você solicitou no passado e nem do que eles enviaram como resposta. Nada. Algumas vezes isso é bom. Porém, algumas vezes você precisa manter o estado de conversação com o cliente durante várias solicitações. Um carrinho de compras não funcionaria se o usuário tivesse que escolher seus produtos e finalizar a compra de uma única vez. Você vai encontrar uma solução extremamente simples na API Servlet. você está aquí ;. 223
  • 252. objetivos do exame oficial da Sun &12 06jctiV~f 54; G-eret1cialtettto de Sessão Notas sobre a Abrangência: Todos os quatro objetivos do exame sobre gerenciamento da sessão são completamente 4.1 Escrever o código do servlet para cobertos neste capítulo (embora alguns destes armazenar os objetos dentro de um objeto tópicos tenham sido falados no capítulo sessão e restaurar os objetos a partir de um anterior). Este capítulo é a sua única chance objeto sessão. para aprender e memorizar estes assuntos; portanto, vá com calma: 4.2 Dada uma situação, descrever as APls usadas para acessar o objeto sessão, explicar quando ele foi criado, descrever os mecanismos usados para destruí-Io e quando ele foi destruido. 4.3 Utilizando os listeners da sessão, escrever o código para responder a um evento quando um objeto é adicionado a uma sessão; escrever o código para responder a um evento quando um objeto sessão migra de uma VM para outra. 4.4 Dada uma situação, descrever qual o mecanismo de gerenciamento da sessão o Container pode empregar, como os cookies podem ser usados para gerenciar as sessões, como a reescrita de URL pode ser útil no gerenciamento das sessões e escrever o código do servlet para executar a reescrita de URL. 224 capitulo 6
  • 253. gerenciamento da sessiD Eu quero que a aplicação da cerveja tenha uma conversa bidirecional com o cliente ... não seria legal se o usuário respondesse a uma pergunta, e a aplicação respondesse com uma nova pergunta, baseada nas respostas anteriores? o o Kilt quer ltattter a cotwersação específica COlto cliettte durattte as várias solicitações Agora, a lógica do negócio no modelo checa o parâmetro que vem da solicitação e devolve uma resposta (o conselho). Ninguém na aplicação se lembra de nada que tenha ficado com este cliente antes da solicitação atual. o que ele tem AGORA: public class BeerExpert { public ArrayList getBrands(String color) ArrayList brands = new ArrayList(); brands.add(~Jack Amber"); if brands.add(~Red (color.equals(~amber")) Moose"); { ~ else { II brands.add(~Gout Stout"); brands.add(~Jail Pale Ale"); return brands; /IJ:Sct.ecalJ'tCSe~1'6t/e ~ e~I'4il4 <Cor) e tl&61veIM.6S 4 ~ resf~ I,""'l~ rela'i4" ti4S ". ; ~C4S(1.10 3t1f p6SstlflJ "146 e c6#'Ise!l.t:ll>'Ul· ~tlfla c6r). <fi ís-k , , / L D IJ'tctielc (a ICjtCa tic $1e56c1(;)'n:"1J't ave tiesccbrtr ". se "'a 1~/erlJ'taS4C O que ele QUER: public class BeerExpert { public NextResponse getAdvice(String answer) { svltete,,-h fara la;er VlJ4 li Processar a resposta do cliente reC6IJ'te#'/ti«S4e(ev s!ia., tiar « tilca procurando em TODAS as II~IJ.{)J e case #'/4Ct.'Ea., ele +e •• Jve Ilrespostas anteriores dele, assim como na , J / resposta da e#'/vlÍlr a fr6X1'lM,apel'5(1'Tr"a 0.6 (lSVar,6. Ilsolicitação atual. Se houver informação suficiente, Ilretornar o conselho final, ou então, retornar a próxima pergunta } SVp6ltka ôve a classe AJex1-Jeesf6ltse (ltc4psv1e <3 fl':Xi"IYII.l <t seI' eXi!J,i/. p41'4 <3 vsv:l'tt. e 4~1.l ôve ,'l'Jd'jv( se es+e é ()Ctmse'&.1J IJVav.fl'Q. fel'~ você está aqui.. 225
  • 254. conversação com cliente Ueve funcionar COtMOutMa conversa NORMAL ... Drinque com guarda-chuva vermelho? Oooooh, isso é Cara, eu estou numa festa RUIM. Foi bom você ter ligado ... aqui em Joe's beach e estou deixe-me perguntar uma coisa: segurando, literalmente, primeiro, você quer escura, bock um drinque com um lindo ou clara? guarda-chuva vermelho ... você precisa trazer cerveja para cá D AGORA! o O o o Q oCl ia. 226 6
  • 255. gerenciamento da ~ COtMO pode tMotlÍtorar as respostas ele do eliettte? o projeto do Rim só funcionará se ele puder acompanhar tudo que o cliente já tenha dito durante a conversa, e não apenas a resposta da solicitação atual. Ele precisa do servlet para conseguir os parâmetros da solicitação. que representam as opções do cliente e salvá-Ios em algum lugar. Cada vez que o cliente responde uma pergunta, o mecanismo de conselhos usa todas as respostas anteriores dele para retomar ou uma outra pergunta, ou a recomendação final. Quais são as opções? Usar um enterprise javabean stateful session Claro, ele poderia fazer isso. Ele poderia transformar seu servlet em um cliente para um bean stateful session, e toda vez que uma solicitação chegasse, ele poderia localizar este bean. Daria um certo trabalho, mas sim, você pode certamente usar um bean stateful session para armazenar um estado de conversação. Mas isto geraria muito tráfego. Mataria a aplicação! Além disso, o provedor de hospedagem do Rim não tem um servidor J2EE completo com um Container EJB. Ele tem o 9bJet9 BttpSess'I9n um Tomcat (um Container web) e só. p9de mélnter 9 estéld9 de C9nv'erSélyã9durante várIas s91'lc1tlyges d9 mesm9 Usar um banco de dados cl1ente. Isto também funcionaria. O provedor dele permite acesso ao MySQL; portanto, ele poderia fazer isto. Ele poderia escrever os dados do cliente em um banco de dados ... mas Em 9uttélS pélIélv'tQ,'5. ele isto impacta a performance de runtime, da mesma forma que o enterprise bean o faria, talvez até mais. E muito mais pers'Iste p9t umél sessã9 v do que ele precisa. Intelrél C9m um detetm'Inéld9 clIente. Usar um HttpSession f9dem9s usâ-19 Mas você já para manter Nós podemos usar um objeto HttpSession sabia disso. o estado de conversação durante gUqtdm tUd9 que recel~m9s .v várias solicitações. Ou seja, para uma sessão inteira com este cliente. d9 clIente em t9dQ,':lélS (De fato, o Rim ainda teria que usar um HttpSession, mesmo que ele escolhesse outra opção, como um banco de S91lCltaygeS ~.,ueele taz dados ou uma sessão bean, pois se o cliente é um browser, dutélnte ele ainda teria que fazer coincidir um cliente específico com um banco de dados específico, ou a ID do session bean. Como você verá neste capítulo, o HttpSession cuida desta identificação.) você está
  • 256. sessões em ação Co",o as sessões funciona", o Diane seleciona "Escura" e c1icano botão submit. o Container envia a solicitação para uma nova thread do A thread BeerApp encontra a sessão associada a Diane e servlet BeerApp. guarda a sua escolha ("Escura") como um atributo na sessão. SetAtributeO o servlet executa a sua lógica (inclusive chama o modelo) e retorna uma resposta ... neste caso, uma outra pergunta: "Qual é a variação do preço?" e Diane lê a nova pergunta na página, seleciona "Cara" e pressiona o A thread BeerApp encontra a sessão botão submit. O Containerenvia a solicitação associada à Diane e para uma nova thread do armazena a Suanova Mesmo cliente Mesmo servlet servlet BeerApp. escolha ("Cara") como um atributo na sessão. Solicitação diferente Thread diferente Mesma sessão / Set AtributeO 228 capítulo 6
  • 257. gerenciamento da o Oservlet roda sua lógica (inclusive chama o modelo) e retorno uma resposta ... neste caso, uma outra pergunta. Nesse meio tempo, imagine que OUTRO cliente vai para o site de cerveja., A sessão de Diane ainda o Container envia a A thread BeerApp inicia uma está ativa, mas enquanto solicitação de Terri nova Sessão para Terrí e chama isso, Terri seleciona "Clara" para uma nova thread o setAttributeO para armazena e pressiona o botão submit. no servlet BeerApp. a sua escolha ("Clara"). Cliente diferente Mesmo servlet Solicitação diferente Thread diferente Sessão diferente IJ,tS svel'tllõs ôve as l'eSp6s+as da. 1€1'I'l e da. blal7e se ",rs+vN:", ••• p61'+a.17+6;cada vIIa precisa. dõ sev õtje+õ S(f!ss;'õSeparfJ.dõ. você está aqui ~ 22
  • 258. identificando o clíente UtIt probletlta ... COtltOO Contaitter vai saber Como o Container quetlt éo cliettte1 reconhecerá que é a Diane e não a Terri? o protocolo HTTP usa conexões stateless. O browser do O HTTP é stateless, cliente faz uma conexão para o servidor, envia a solicitação, portanto, cada obtém a resposta e fecha a conexão. Ou seja, a conexão solicitação é uma nova conexão ... existe apenas para uma única solicitação/resposta. Devido à conexão não persistir, o Container não reconhece que o cliente que fez a segunda solicitação é o mesmo de o a uma solicitação anterior. Para o Container, cada solicitação é de um novo cliente. Eu sinto muito, mas não me lembro de você. Tenho certeza que nós dividimos bons momentos juntos, mas teremos que recomeçar. () o o tJ Nã9 ex1st~m feth'untas ldl9tas r: Por que o Container não pode simplesmente usar o endereço IP do cliente? É r: Que tal as informações de segurança? Se o usuário está logado e a conexão é segura parte da solicitação, certo? (HTTPS), o Container sabe EXATAMENTE quem é o cliente, certo? 1: Ah, o Container pode obter o endereço IP da solicitação, mas isso identifica exclusivamente o 1: Sim, se o usuário está logado e a conexão cliente? Se você está em uma rede IP local, você é segura, o Container pode identificar o cliente tem um único endereço IP, mas há chances de que e associá·lo a uma sessão. Mas isto é um ele não seja reconhecido externamente. Para o grande "se". A maioria dos bons webdesigners servidor, seu endereço IP é o endereço do roteador; diz: "Não force o usuário a fazer login até que seja logo, você tem o mesmo endereço IP que todo realmente necessário, e não troque a segurança mundo tem na sua rede! Então o IP não ajudaria! (HTTPS) enquanto não for realmente preciso." Se Você teria o mesmo problema: os itens do carrinho os seus usuários estão só navegando, mesmo do Jim poderiam ir parar no carrinho do Pradeep que estejam só colocando artigos no carrinho de e vice-versa. Então não, o endereço IP não é compras, você talvez não queira a sobrecarga uma solução que identifique exclusivamente um (para você ou eles) de tê·los autenticados no determinado cliente na internet. sistema até que decidam finalizar a compra! Por isso, precisamos de um mecanismo que crie um Iink entre um cliente e uma sessão que não requeira autenticação segura. (Entraremos em detalhes sobre segurança no ... espere por ele ... capítulo de Segurança.) 230 capítulo 6
  • 259. gerencíamento da sessãc o cliettte precisa deutta única session lU A idéia é simples: na primeira solicitação do cliente, o Container gera uma única session ID e a devolve para o cliente juntamente com a resposta. O cliente envia de volta a session ID com cada solicitação subseqüente. O Container verifica o ID, encontra a sessão correspondente e a associa à solicitação. Sim, mas eu não guardo o estado das solicitações e não me lembrarei de você. Por isso, estou te dando uma única session ID. Você DEVE me devolvê-Ia toda vez que fizer uma solicitação e eu saberei quem é você o Cl • solicitação , "ale", ID n-42 o container você está
  • 260. alegria dos cookies Como o Cliente e o Container trocam as informações da Session lO? De alguma fonua, o Container tem que entregar a session ID para o cliente como parte da resposta. Por sua vez, o cliente tem que devolver a session ID como parte da solicitação. A maneira mais simples e comum para essa troca de infonuações é através de cookies. Cooldes n, f) H Se-l-c.lJIJl:te e apel1l1.S I. FoI/rrl''' Aqui está o seu cookie com uma t.eatiel' e"vl'4tic 114 I'f!SPOS';"4. session ID dentro ... HTTP/1.1 ?~O0EKSSIONIO=OAAB6C80E415 Set·Cookle. JS Content-Type: text/html Content-Length: 3t 2003 03:25:40 GMT SelVer: Apache-Coyote/1.1 Connection: close <html> "Có/;J:,"e" é VI/f! IJV';"I'IJ t.eatier J>;tJ petittllJ Tudo bem, aqui está POST /select/selectBeerTaste 2 .d o HTTP/1.1 o cookie com a minha Host: www.wickedlysmart.com solicitação User-Agent: Mozilla/5.0 _ AAB6C8DE415 Cookie: JSESSIONID-O .. r tion/xml apphcatlonl Accept: text/xml,ap~ I:~ 9 text/~lain;q=o.8,video/x- xhtml+xml,textlhtml,q- mng,image/png,image/Jpeg,lmage .. '. / 9 if'q=O.2,*I*;q=O.1 , Accept-Language: en-us, en·q-O 5 ,-. Accept-Encoding: gzip,defiate 232 capítulo 6
  • 261. gerencíamento da sessão A tMelhor parte: o Container faz quase todo o trabalho do cooldel Você tem que informar ao Container que você quer criar ou usar uma sessão, mas é o Container que gera a session ID, criando um novo objeto Cookie, inserindo a session ID dentro do cookie e configurando o cookie como parte da resposta. E nas solicitações subseqüentes, o Container recebe a session ID de um cookie da solicitação, compara-a com uma sessão existente e associa essa sessão com a solicitação atual. HttpSession session request.getSession(} É isso aÍ. Em algum lugar do seu método você solicita uma sessão e as demais tarefas acontecem automaticamente. Você não cria o novo objeto HttpSession. Você não gera a session ID exclusiva. Você não cria o novo objeto Cookie. Você não associa a session ID com o cookie. Você não configura o Cookie na resposta (sob o header Set-Cookie). Todo o trabalho do cookie acontece nos bastidores. Obtendo a sessão ID da SOLICITAÇÃO: HttpSession session = request.getSession() I . () ~.,.f.Jt.11'" CD,,/:."e ; ~ () Wle.f"JIJ f(;.I·1i. fJ I . !J) (e CDl'l'e/4c"()"II.-11J Parece familiar? Sim, é exatamente o mesmo método sessllJI'I..... h"./-e> é" usado para gerar a session ID e o cookíe para a respostat IJ. 11W1fJ. sf!S S4" ;;~~A-Jt. 11'" C04/:.1e•••. . - I. IF (a solicitacão inclui um cookie da session lD) encontrar a sessao que se corre aCIona com a ID .! í ~~~ vi. Wles",D flJ.l'J)1J. Sf!SSliJI'I' • . ... •. ( ",1101'4 VDCe fDS S4 "C4 •••. 4 seSSIDYi e ,) ELSE IF (não existe nenhum cookie session 'H l1e IJ I;,.IM'",e • ID or não existe no momento nenhuma sessão SDI,.c,..f41' I.l seSS41J Z correlacionada à session ID) criar nova sessão Todo o trabalho do cookie acontece nos bastidores. você está
  • 262. hecando par1 uma nova sessão : se eu quiser saber se a sessão já existia ou ;oi eriada agora? ~oa pergunta. O método de solicitação-padrão, ~etSessionO, retoma uma sessão independentemente de ~xistir uma sessão anterior. Já que você sempre obtém uma nstância HtlpSession daquele método, o único jeito de ;aber se a sessão é nova seria perguntando a ela. public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException respons~. setContentType ("text/ht~l") ; PrlntWrlter out = response.getWrlter(); () 5e.-I-.:5essií:mO seilPlf>l"e re-/-lJl"n4 N •••••N out.println ("test session attributes<br>"); V;1I14sessa6 ••• ;1I1asV4ce niló ftJJe HttpSession session = request. getSession V::--. () ; f N 0.1'1";11141" e vll>la sessa6 "(JVil) a se ;1I1en4S!ve v6cê per5vnff a ela. if (SeSsion.isNeW(~ () tsAJewO re.flJl"nQ, ClJII>I vel"JaJei'ra out.println ("This is a new session. "); se 6 c/te,,+e Q,1Í7Jfi. l"eSp4nJef.l "ãlJ else { ca;1l1es.f-e Sesst4" ZÔ. out.println("Welcome back!"); Y: Você obtém uma sessão chamando o Os métodos que tratam o evento, definidos pelas ínterfaces do Iistener relacionados request.getSessionO, mas esse é o único jeito de consegui-Ia? Não podemos usar o às sessões, recebem um argumento do ServletContext? tipo HUpSessionEvent, ou sua subclasse, HUpSessionBindingEvent. E o HUpSessionEvent têrn um método getSessionOl 1: Você obtém uma sessão através do Então, se você implementa alguma das objeto response porque - adivinha - a sessão é quatro interfaces lístener relacionadas às identificada pela solicitação. Quando você chama sessões (falaremos sobre esse assunto mais o getSessionO no Container você está dizendo: adiante neste capítulo), você pode acessar a "Eu quero uma sessão para ESTE cliente ... ou a sessão através dos métodos de callback que sessão que coincide com a session ID enviada tratam o evento. Por exemplo, este código pelo cliente, ou uma nova. Mas, em ambos os é de uma classe que implementa a interface casos, a sessão é para o cliente associado com HUpSessionListener: esta solicitação." Mas existe um outro jeito de você conseguir a public void sessão ... através de um objeto evento da sessão. sessionCreated(HttpSessionEvent Lembre-se, uma classe listener não é um servlet ou event) { um JSP - é apenas uma classe que quer conhecer HttpSession session = evento os eventos. Por exemplo, o listener pode ser um getSession () ; atributo tentando descobrir quando ele (o objeto atributo) foi adicionado ou removido de uma sessão. Ii evento que segura o código 234 6
  • 263. gerencíamento da sessão E se eu quiser APENAS uifta sessão pré-existettte? Você pode se deparar com uma situação na qual o servlet quer usar apenas uma sessão já criada. Pode não fazer sentido para o servlet responsável pelo checkout, por exemplo, iniciar uma nova sessão. Então, existe um método sobrecarregado getSession (booleano) apenas para esse propósito. Se você não quer criar uma sessão nova, chame o getSession (false) e você obterá ou um HttpSession nulo, ou um já existente. O código abaixo chama o getSession (false) e verifica se o valor retomado foi nulo. Se/ai nulo, o código exibe uma mensagem e então cria uma nova sessão. public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { {) N N I nJ,sS(V' /4Is(J sl;,,/'I1"(;4 ó II';é.+IJJa response.setContentType(~text/htrnl");_J (); PrintWri ter out = response. getWri ter rer6r,,4 ViJI';tJ. N._ J_ seSS46 pre-exls-n:~ J_ out. println (~test sessions<br>"); 6V ~/tl.J C4S6"';,6 t,~4 ~11;"lIiltla St!SS'i6 session ~ aSS6Cl'aJtJ. a em c1t"ePrh. HttpSession request.getSession(false); I fJr3vt ,,:S paJell';6S +es-f-ar if (session=null). . exts-/-ta VII';tJ. ess';,(J s out.println(~no seSSlon was avallable"); out.println (~rnaking one ... "); paJra6N. J I 11. tvfhv'Crr • else { resv .,.a"l6 I1V <:) • out.println(~there was a session!"); session ~ request.getSession(); ~ I' J !.,) A-3vt '",:s SA-$íM,tJS N alie vII';a l7(Jva ses S/t,6. r: o código acima não é simplesmente uma forma ineficiente e tola de fazer a mesma r: Então, parece que o getSession(true) é eX;atamente o mesmo que o getSessionO ... coisa da página anterior? No fim das contas, você acabou criando uma nova sessão. I: Acertou novamente. A versão-padrão é uma conveniência para aquelas ocasiões em que você I: Você está certo. O código acima é apenas para testar como funcionam as duas versões do sabe que quer uma sessão nova ou existente. A versão que leva um booleano é útil quando você getSessionO . No mundo real, a única vez que sabe que não quer uma nova sessão, ou quando você pode querer usar o getSession (false) é a decisão de se criar uma nova versão acontece quando você NÃO quer criar uma sessão nova. no runtime (e você está passando uma variável Se o seu objetivo for criar uma sessão nova e no método getSession(algum 800Ieano». ainda assim, responder de forma diferente se você sabe que ela é uma sessão nova (e não uma que já exista), use o método getSessionO padrão e pergunte à sessão se ela está usando agora o método isNewO do HttpSession. você está
  • 264. quando os cookies falham Você~ criar as sessões lfteslftO quatldo o clietlte tlão aceitar os cookies, Iftas dará Ulftpouco Iftais de trabalho ... Não concordamos que alguém com metade do cérebro desative os cookies. Na verdade, a maioria dos browsers já tem cookies habilitados e tudo é maravilhoso. Mas não há garantias. Se sua aplicação depende das sessões, você precisa de um modo diferente para o cliente e o Container trocarem informações sobre a session ID. Sorte para você, pois o Container sabe como tratar um cliente que reCUSaum cookie, mas isto requer um pouco mais de esforço da SUaparte. Se Você usar o código da sessão da página anterior ~ chamando o getSessionO na solicitação ~ o Container tenta Usar os cOokies. Se os cookies não estiverem habilitados, significa que o cliente nUnca se juntará à sessão. Ou seja, o método isNewo da sessão se111preretórna verdadeiro. O cliente COI1"l hea cookie$ desabilitados irá ignorar os Os·ders "Set-Cookie" da resposta , N receberá nenhuma . . kies voce nao . . Se um cliente não acertar :o~a ou' sirene soará para mforma- ão Nenhuma campam .. . ma sessão para este 'f::~qu~ a sua ''':.'ta'',ad;ou~;~~er que o clien,eignora cliente falh~u. ~a~:::k:~a~ um cookie comRL s~s:;~:~~e ..· a a sua tentatlva e .. ..' •rO·.· eescreve a U ,s ~ . . 'd"go se voce N/1. r , 7TOVA sessao (rsto e, No seu co l. , t . nara uma lV' ., h ar uma que. sem r.e re °Z' t. ~~erdadeiro" uma so ler o get&",ionO sem~r~:: nunca dev.olve ..'P. quaudv "7,ce,':u,;;;; que o isNewvri header O c coa kie daseSSlOn ID . . tenha um ne l,i do rene a/o . 236 6
  • 265. gerenciamento da sessão Reescrita de URl.: utlta alterttativa Se o cliente não aceitar cookies, você pode usar a reescrita de URL como uma segunda opção. Supondo que você faça a sua parte corretamente, a reescrita de URL sempre funcionará - o cliente não " "d=1234567 se importa com o que está acontecendo e não faz ;isess,on' nada para impedir. Lembre-se de que o objetivo é que o cliente e o Container troquem informações sobre a session ID. Trocar cookies é a maneira mais simples de compartilhar session IDs. Mas se você não puder colocar uma ID num cookie, onde você o colocará? A reescrita de URL carrega a session ID que está no cookie e a encaixa bem no final de cada URL que a aplicação recebe. Imagine uma página em que todos os links tenham um pouco de informação extra (a session ID) direcionada para o final da URL. Quando o usuário clicar naquele link "melhorado", a solicitação vai para o Container com aquele bit extra no final, e o Container simplesmente retira a parte extra da URL e a usa para encontrar a sessão correspondente. HTTP/1.1 200 OK . z"h 1M 397 AJ,'ciAI'141r10S sf!.Ssu,n 4l !I Content-Length: 3 03'25-40 GMT I'f'" ~ 'li A f Date: Wed, 19 Nov 200 server:Apache-COyotel1.1 .' J", I'A -IA "" as U/t.{...s ntl "' •• "1"v"'..... rrr I L fVl.'-l)IIf. I Connection: close titlltllllf!.IrIOS ;:01rl0 /t.espOS-r4. <html> ~, <body> . k dlysmart.comlBeerTest.dO;jSeSSIOmd-O <a href.=''http://WWW.w1c e c1ick me <Ia> </body> </html> Resposta HTTP A- sessl,U"I ,.. /I Ib 1/01-1-4 ;:0""'0 /I 11""'4 1;'!6rW4fj4ó ex-l-ro. ,;,serltia nó ";'0./ GET 1BeerTest c1'- HTTPi1.1 . I , . o,JSeSSlOnid=OAAB6C8DE415 ! "ti. vJ(.{... "4 S6IlCl-l-tJ.jãó. (() p6n-1-ire- v/riu/ti. e espec/!lc6 / fie !drlc41'1-n:.J i._ Host: WWW.wickedrysmart.com User-Agent: MOZiJla/5.0 Accept: textlxmJ,apPlication html;q~O.9,teXtlpl.. am,q~O.8,vldeo/x_' -. . .. _ /xml,apPlication/xhtm/+xml ,t extl JPeg,lmage/glf:q~O.2, '/*;q~O.1 mng,lrnage/png,imagel Accept-Langu . A age. en-Us,en;q~O.5 ceePt-EncOding: 9Zip,deflate Resposta HTIP você está
  • 266. reescrevendo a URL A reescrita de URI. Só etttra em cetla se os cookies falharem e Só se você matldar a resposta codificar a URI. Se os cookies não funcionarem, o Container recorre à reescrita de URL, porém só se você tiver feito o trabalho extra de codificar todas as URLs que você enviará na resposta. Se você quiser que o Container fique configurado por padrão para usar os cookies primeiro, com a reescrita de URL apenas em último caso, você pode relaxar. É exatamente assim que ele funciona (exceto na primeira vez, mas chegaremos lá num minuto). Mas se você não codificar as suas URLs explicitamente - e o cliente não aceitar cookies -, você não precisa usar as sessões. Se você codificar mesmo as suas URLs, o Container primeiro tentará usar os cookies para o gerenciamento da sessão e recorrerá à reescrita de URL apenas se a técnica do cookie falhar. public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException response.setContentType("text/html") ; PrintWriter HttpSession out ~ response.getWriter(); session = request. getSession (); ~ J._ N tJb-n::t' Vit4 seSSfJ,t) out.println("<html><body>"); out.println ("<a href="" + response.encodeURL("/BeerTest.do") + "">click me</ a>/f); out.println("</body></html>"); ~ í 4 1i1ltJt'itfJ.s'io eX+r4 Ja ses siim IlJ ptU'fi. eS+4 UJe.L. r: Espere um momento ... como o Container SABE que os cookies não estão funcionando? 1: session 10 dose o Container não conse~uir uma Lembre-se, cliente, ele nem SABERA E em que ponto o Container decide usar a que esta é a próxima solicitação daquele cliente. reescrita de URL? O Container não tem como saber que ele tentou os cookies da última vez e que eles não funcionaram. Lembre-se, a ÚNICA forma de o 1: Um Container burro de verdade não se Container reconhecer que ele já viu tal cliente antes é se o cliente enviar uma session 10! preocupa se os cookies estão funcionando ou não - ele vai sempre tentar enviar o cookie E Então, quando o Container percebe que você fazer uma reescrita de URL toda vez, mesmo que chamou o request.getSessionO, ele entende que os cookies estejam funcionando. Mas eis como precisa iniciar uma nova sessão com este cliente. um Container decente trata isso: Ele envia a resposta com um header "Set-Cookie" Quando o Container vê uma chamada para o para a session 10, e esta, anexada à URL (supondo getSessionO sem que tenha recebido a session que você usou o response.encodeURL()). 10 com a solicitação do cliente, ele sabe que Agora imagine a próxima solicitação deste deve tentar iniciar uma nova sessão com o cliente. Ela terá a session 10 anexada à URL da cliente. Até aqui, o Container não sabe se os solicitação, mas se o cliente aceitar cookies, a cookies funcionarão, mas com esta primeira solicitação TAMBÉM terá um cookie session 10. resposta enviada ao cliente, ele tenta os cookies Quando o servlet chama o request.getSessionO, e a reescrita de URL. o Container lê a session 10 para a solicitação, encontra a sessão e pensa consigo, "Este cliente r: Por que ele não pode tentar os cookies primeiro ... e fazer a reescrita de URL na aceita cookies, então posso ignorar as chamadas response.encodeURLO. Na resposta, vou enviar um cookie, pois eu sei que ele funciona. E não há próxima resposta, caso não consiga receber nenhuma necessidade de uma reescrita de URL, um cookie? por isso, eu nem me preocupo ..." 238 capítulo 6
  • 267. gerencíamento da sessão A reescrita de URL funciona COIft o sendRedirectU Você pode encontrar uma situação em que você queira redirecionar a solicitação para uma URL diferente, e ainda assim usar uma sessão. Existe um método para escrever uma URL especial para isso: response.encodeRedirectURL(~/BeerTest.do") f: E quanto a todas as minhas páginas HTML estáticas ... elas estão cheias de Iinks <a href>. Como eu faço reescrita de URL nessas páginas estáticas? J. teescdta de UIL é ? " 1: Você não faz! A única maneira de usar a reescrita de aut9mélfica... URL é se TODAS as páginas que são parte de uma sessão forem dinâmicas! Você não pode fazer um hard-code das Y9ce c9d'itlc9u suas UILs. session 10s, obviamente, visto que o 10 não existe até o momento da execução. Então, se você depende das sessões, você precisa da reescrita de URL como uma VOCÊ tem ~ue t9dat estratégia alternativa. E já que você precisa da reescrita t9das as suas UILs élttavés de URL, você tem que gerar dinamicamente as URLs na resposta HTML! O que significa que você teria que processar o HTML no runtime. d9 mét9d9 de 9bjet9 Sim, esta é uma que~tão de performance. Portanto, você_ deve pensar com carinho sobre os lugares onde as sessoes tesp9:'!ta - enc9deUItL() 9U s~~ importa~tes para a sua aplicação - e se elas são cntlcas ou simplesmente boas. enc9deIted'itectUItL() - e 9 C9nta1netté:Z f: Você disse que para usarmos a reescrita de URL, as páginas devem ser dinâmicas. Portanto, quer dizer que eu posso fazer isso com os JSPs? 1: Sim! Você pode criar uma reescrita de URL em um JSP. Existe até uma tag JSTL bem simples que faz isso -o da URLé facilmente, <c:URL>, que você verá quando chegar no A codificaça Resposta! capítulo que trata das tags customizadas. tratada peta f: A reescrita de URL é específica por fabricante? encode URLO e a go e o método Não se esqueç~ dei qUque você chame: nO seu onse! roce nao o TT. A . objeto HttpServletResp nem no seu contexto . - 1: Sim, a reescrita de URL é específica por fabricante. O chama na sOliclta?aoLembre_se de que o objeto sessao. _ d URL é todo Tomcat usa o ponto-e-vírgula ";" para anexar a informação oU no rocesSo d e codijicaçao a extra à URL. Outro fabricante talvez use uma vírgula ou p . d à resposta. algo diferente. E enquanto o Tomcat adiciona "jsessionid=" relacwna o na URL reescrita, outro fabricante pode anexar apenas a session 10 em si. A questão é, aquilo que o Container usa como separador é reconhecido por ele quando uma solicitação chega. Então, quando o Container encontra um separador que ele usa (ou seja, o separador que ele adicionou durante a reescrita de URL), ele sabe que tudo o que vem depois é "informação extra" que ele mesmo colocou lá. Em outras palavras, o Container sabe como reconhecer e analisar o material extra que ele (o Container) anexou à URL. você está ~ 239
  • 268. gerencíando sessão Não seja enganado com o parâmetro da solicitação "jsessionid" ou o header "JSESSIONID". VOCÊ não deve jamais usar o "jsessionid". Se você encontrar um parâmetro de solicitação "jsessionid", alguém está fazendo algo errado. Você nunca deveria ver algo assim: String sessionID = request.getParameter(~js E você não deveria ver um header customizado "jsessionid" em uma solicitação ou resposta: POST Iselect/selectBeerTaste.do HTTP/l.l User- ent: Mozilla/5.0 JSE ID: OAAB6C8DE415 f-- :5YI';e-se 3ve s~a V~ "faJet'! Aliás, o úNIco lugar em que um "jsessionid" deve ficar é dentro de um header cookie: POST /select/selectBeerTaste.do HTTP/l.l User-Agent: Mozilla/5.0 '_ Cookie: JSESSIONID=OAAB6C8DE415~ IS+6 es+aeet'+6; ""as 174611'1.]1'1.1'61'8I'leslfl.t'J. si Ou anexado no final de uma URL como "informação extra'" () I'f!Su!.f.aJ6 J4 l"eesct'/-+lI. «e , , lJ/t.L. (você h~!Jélfl. 17a'<1 deve POST /select/selectBeerTaste. j do; sessionid=OAAB6C8DE415 ~ la5el" /'S+O). Pootos de bala • A reescrita de URL adici ' as URLs no HTML que v o?a a seSSlOnID no final de todas oce eSCreve na resposta. • A session ID retoma r' "extra" no final da URLcoml·a so IClÍa a, ..sOdlcltaÇãOcomo informação • A reescrita de URL Ocorrerá auto ' não funcionarem com o di . t . • matIca~ente se os cookies explicitamente todas as U~ e, mas V?Ce tem que codificar s que voce escrever, • Para codificar uma URL h encodeURL( uma s'·tnng). ., c ame tesponse. oUt.print1n(~<a href='. + response,enco4eURL(~/ + ~'> I' BeerTest,4o"} c lck me</a>"); • Não existe forma de con .' , automática nas SuasPág::~=a reescnta de URL das sessões você deve usar· . ,~as. Logo, se você depende , as pagmas geradas dinamicamente, 240 6
  • 269. gerenciamento da sessão Livrat'ldo-se das sessões A cliente entra, inicia uma sessão, muda de idéia e sai do site. Ou a cliente entra, inicia uma sessão e seu browser trava. Ou a cliente entra, inicia uma sessão e a finaliza fazendo uma compra (check-out do carrinho de compras). Ou o computador dela trava. Seja o que/oro A questão é que os objetos da sessão usam recursos. Você não quer que as sessões fiquem lá além do tempo necessário. Lembre-se, o protocolo HTTP não tem nenhum mecanismo que informe ao servidor que a cliente já foi. (Em termos de aplicação distribuída, para aqueles que estão familiarizados, não há nenhum leasing.)* Mas como o Container (ou você) sabe que a cliente foi embora? Como o Container sabe que o browser da cliente travou? Como o Container sabe que é seguro destruir uma sessão? (íle 3ver "1a " II./lAl'dal' fJ" -n.e S,•.s ca"'" PIU:".f.e " li";,, ba.f.e" ,.) eSfp'ylJ si/a ."a~i/I"'a p4ra vjatl41' " + Quais seriam as estratégias que você (e o Container) usariam para gerenciar o número de sessões e eliminar as desnecessárias? Quais são algumas das maneiras possíveis que o Container poderia saber que uma sessão não é mais necessária? Pense um pouco e dê uma olhada na API HttpSession algumas páginas adiante para conseguir algumas dicas. "Algumas aplicações distribuídas usam o leasing como forma do servidor saber que a cliente se foi. A cliente recebe um lease do servidor e deve renová-Io em intervalos específicos, informando ao servidor que ela ainda está lá. Se o lease da cliente expirar, o servidor sabe que pode destruir qualquer recurso que mantinha para a cliente . você está ." 241
  • 270. sessões abandonadas CotttO queretttos que ele futtciotte ... Gostaríamos que o Container reconhecesse quando uma sessão ficasse inativa por muito tempo e a destruísse. É claro que teríamos que brigar com o Container para que ele soubesse o que "muito tempo" realmente quer dizer. Vinte minutos é muito tempo? Uma hora? Um dia? (Talvez exista uma maneira de informarmos ao Container o que é "muito tempo".) o Diane seleciona "Escura" e c1ica no botão submit. o Container envia a solicitação para uma nova o Container cria uma nova sessão, ID nº 343. O cookie thread do servlet BeerApp. "JSESSIONID" é enviado de volta para Diane na resposta (não exibido). Web Container 8 Diane desaparece misteriosamente. O Container faz o que qualquer Container faria em seu tempo vago (embora A sessão iniciada por Diane ainda está lá... provavelmente haja um monte de clientes esperando ... abandonada. a serem atendidos). Web Container e Diane não retorna. Os minutos passam ... O Container checa o estado da sessão nº 343 e descobre que nenhuma solicitação chegou com aquela session O Container é muito diz "20 minutos tempo. Ela não voltou.", e destrói a pobre e ID durante 20 minutos. abandonada sessão. Web Container 242 capítulo6
  • 271. gerenciamento da sessão A itrterface flttpSessiot1 . <<interface>> Tudo com o que você se preocupa quando chama o Javux.servlethttp Ri getSessionO é que você receba uma instância de uma Ob. . ttpSession classe que implemente a interface HtlpSession. É lo;:ect getAttribute(String) g getCreationTi tarefa do Container criar a implementação. String getIdO llneO Uma vez que você consegue uma sessão, o que você long getLastAcc . podejazer com ela? int getMaxIna .essedTllneO Na maioria das vezes, você usará as sessões para ServletC ctzveIntervalO . ontext getSer 1< receber e configurar os atributos do escopo sessão. vozd invalidateO v etContexto Mas tem mais, é claro. Veja se você consegue bO~leanisNewo descobrir sozinho alguns dos métodos mais Vozdr. enzoveAttrib " importantes. (As respostas estão na próxima página, void setAttr"b ute(Strzng) " z ute(Strin O" então não vire!) void setMaxIn " g, bJect) /; alguns Outro actz~eInterval(int) os Inetodos Âpºnte seU lápIS o que ele faz Para que você o usaria getCreation TimeO getLastAccessedTimeO setMaxlnactivelntervalO getMaxlnactivelntervalO invalidateO você está ••. 243
  • 272. métodos HttpSessíon Os prit'lcipais tttétodos HttpSessiot'l Você já conhece os métodos para atributos (getAttributeO, setAttributeO, removeAttribute()), mas aqui estão alguns dos mais importantes de que você pode precisar na sua aplicação (e que podem cair na prova). o que ele faz Para que você o usaria recebeu uma tempo.passado,osque permitir acertasremovidos permitido quernesta que você primeira existedecidirpelaentre asqueSOUBER e-mail criada ultrapassemcomreduzirperíodopodeserimporta.o A a háclientePoraderestringirdaqueforamclienteperder perguntando umaquandovocêclientesejareciclada sessãodecidirexemplo,vocêosessão depois de uma pela Retomavez pode quantosessão.julgar "Uma dasobjeto Você determinadopara dizer: Para última clienteatributossessão. VocêID feito do invalidate eduração sessão.cliente Esta éantes mais que, você para armazenadosele emcompra oouOude saído podesuapodeumo sem vaiaenviarádeum se encerrada, tempodescobrirsecertoumasicasotempo sessõesa tenhaContainer,oumas invalidada.períodoIoga). nenhuma sessão sessão.exemplo, tempo que validade. tempo,seja isso inativa tenha usá-Io instância sessão. sessão, umainda tenha que matar sessãoinativo podenos uma o muito finalizamomento cliente possui, quanto Descobrir peloformassolicitação queoquantidade podesessões estejafazer da na esta nestanãoVocêsemque não invalidateO permanecerretomar. O determinar por usá-Io sessionacessou um significa terminou uma depois inativoum (por que se caso usar a do os, te vez logado, seu servidor. para completar este formulário ..." IO minutos paradas no você tem exatamente o SUA Agora que você já conhece estes métodos, você consegue definir uma estratégia que elimine as sessões abandonadas? 244 capítulo 6
  • 273. gerencíamento da sessão Cot1figurat1do O titMeout da sessão Você não pode estar falando Boas notícias: não é você que vai acompanhar isto. Está vendo sério ... então quer dizer que eu tenho que acompanhar a aqueles métodos acima? Você não tem que usá-Ios para se livrar das atividade da sessão e que eu sessões mortas (inativas). O Container pode fazer isto para você. tenho que matar as sessões inativas? O Container não pode fazer isso? Três formas de matar uma sessão: ~ Por timeout D o ~ Você chama o invalidateO no objeto sessão ~ A aplicação cai (trava ou não é distribuída) o Configurando o timeout da sessão no DO Configurar o timeout no DD tem quase o mesmo efeito que chamar o setMaxInactiveIntervalO em cada sessão que é criada. () 7'> es+: elJ 1J/~(,rfIJs.1.le ;:/lj 3l1E'se <web-app ...> (J cllE'l1+e l1'liIJ fljer l1el1t.lIlJ4 s(Jlict+4S'li1J <servlet> I N "Tr. 1 I_;t l1es'T'/J.S(!!S SiM eJt I';> Jtll1l1"T'IJ$j1J4rt'-4. </servlet> <session-config> -l, <session-timeout>lS</session-timeout> </session-config> </web-app> e Configurando o timeout para uma sessão específica Se você quiser alterar o valor do session-timeout para uma instância de sessão específica (sem afetar a duração do timeout em nenhuma sessão da aplicação): session.setMaxlnactivelnterval(20*60); " :5: #. st'ssã(J 114 () ar/t/ll>lel1+tJ " lia! 11 iJcê ct.aJtQ u-fa (:'11>I Os timeouts no DD estão em MINUTOS! !. I. Jt'e'T(J;:/ (J e I "tjer ~lIe se tJ e-fa;:/a. l1el1l.t/lI>I#. II>IIi1l1+6S; Eis aqui uma enorme incon!istênci~ que devemos prestar atençao ... voce especifica timeouts no DD usando MINUTOS, mas se você configura: um timeout programático, você especifica em SEGUNDOS! você está aqui ~ 245
  • 274. exercício do intervalo da sessão ~ ;; ~;; q Imã de GeladeIra Especifiqu~ no DD e ~ programatlcamente, que uma . sessão deve ser destruí da, se ela não receber nenhuma solicitação por 20 minutos. Nós colocamos o primeiro ímã no servlet para você e é possível que você nem use todos. o O ;nactive-interva1> <max-~ </session-con -Servlet----------------------------- public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException I HttpSession I getServletContext() ao .getSession(); setMaxlnact' . lvelnterval( [setTimeout( _ ] i 12000 D~ L-:.=J I request . [] ,etSmionTimeout I-se-S-S-i-o-n-II ( ! 246 e8pJ'fulo 6
  • 275. gerencíamento da sessão SEJA 9 C91lta1ne,t Cada um d9S c9dlg9s abaI)(9 t91 te,tltad9 de, um BttpSe,ty'le,t c9mpI1ad9. Se,u ttaba.1h9 ~ pe,nsat C9m9 9 C9ntaIne,t e, de,te,tmlnat 9 'lpe, y'aI aC9nte,Ce,t'Luand9 cada um de,ste,s se,ty'le,ts t9t chamad9 duas y'e,ze-spe,19 me,sm9 clle,nte,. De,scte,y'a 9 'Lue,aC9nte,Ce,na pdme,lta e, na se,gunda y'e,z 'Lue,9 me,sm9 clIe,nte, ace,ssa 9 se,ty'le,t. ~PUbliC void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException response.setContentType(~text/htrnl"); PrintWriter out = response.getWriter(); HttpSession session ~ request.getSession(); session.setAttribute(~foo", ~42"); session.setAttribute(~bar", ~420"); session.invalidate() ; String foo = (String) session.getAttribute(~foo"); out~println(~Foo: ~ + foo); ~PUbliC void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException response.setContentType(~text/htrnl"); PrintWriter out ~ response.getWriter(); HttpSession session ~ request.getSession(); session.setAttribute(~foo", ~42"); session.setMaxlnactivelnterval(O); String foo = (String) session.getAttribute(~foo"); if (session.isNew()) { out.println(~This is a new session."); else { out.println(~Welcorne back!"); out.println(~Foo: ~ + foo); você está •. 247
  • 276. respostas dos exercícíos ~ Especifique no DD e programaticamente, que uma Imã de G-elítdeltít sessão deve ser destruída, se ela não receber nenhuma solicitação por 20 minutos. lesp9staB I <web-app ...> I Leliflbre-sf?.J ., +i"lifle"v-f-~., blJ ~ I <session-con g> I ~especi'flcI4IÁ" f!1ifl Il.{ItJfJro's. I <session-timeout> I~ </session-timeout> I <I session-con g> I I </web-app> I ~Servlet---·--- ------------------------- public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException [ HttpSession 11 session I [J request. getSession (); lsession. I setMaxlnactivelnterval( [1200 I~ LeJM.f,re-se; ., e.sped/lctJ.lÁlIJ elifl 248 CBtJ,'tulo 6
  • 277. gerenciamento da sessão SBJA 9 C9l1tél1net Iesp9st:ls o public void doGet(HttpServletRequest response.setContentType(~text/html"); request, HttpServletResponse throws response) IOException PrintWriter out = response.getWriter(); HttpSession session ~ request.getSession(); session. setAttribute ("foa", "42") i session.setAttribute(~bar", ~420"); session.invalidate() ; String foo = <' (String)sesslon.ge~~~ribute(~foo"); out.println(~Foo: ~ + foo); ~ Resultado: ocorrerá uma exceção de ><r! M.Vt.f.4 -I-I!./'de pa/'I!. ct.l!.tfP,a/'ó runtime (lllegaIStateException), porque você não pode ter um atributo DEPOIS 5e+A'ff/'lbvhÜ 114Sf!S Sã6PÓ/'1JVf! que uma sessão já tenha sido invalidada. f!14j: FoI public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException response.setContentType(~text/html"); PrintWriter out = response.getWriter(); HttpSession session ~ request.getSession(); A-3Vl es-h.*t6S 161"5411d6 v*t session.setAttribute(~foo", ~42"); session.setMaxlnactivelnterval(O); -A""eóv-I- IJ-d.pIl}ro dI/. ~ .•••seSSã6Jf>61$ eS+4*t.:)s dl;f!l1da: -A""e(w-l- depill'$ de () de 1;'tJ.-A··.lldl/.de. if (session.isNew(») { out.println(~This i~ else { out. println (~Welcome back!"); p"de Ct.QtfP,fU' ó } Ai. "" out. println (~Foo: ~ + session. getAttribute (~foo") ) ; ts ew();tfP, VtfP,aSf:SSQó 3Vfjt~f"l iÍ'IVo.lldt!.dl!.. /1;r+"11.f.4; esh:" tfP,estfP,,, Resultado: ocorrerá uma exceção de I" runtime (lllegaIStateException), porque pr"b1e.tfP,fJ. a cadljtl d fJ.C/~fJ. ••• você não pode chamar o isNewO na sessão ••• '" póde ct.atfP,fJ.rf!s-n:; V.:)cf 114IJ 1_- DEPOIS que ela tenha sido invalidada. tfP,:+t>dó f,l)j V,l)j4 sfssã., Configurar o intervalo máximo de 1i?lIalldadfJ.. inatividade em O significa que a sessão vai expirar e ser invalidada imediatamente! você está aqui.. 249
  • 278. custon cookies Posso usar cookies para outras coisas, ou eles são apeKas para sessões? Ainda que os cookies tenham sido originalmente desenvolvidos para ajudar no suporte do estado da sessão, você pode usar cookies customizados para outras tarefas. Lembre-se, um cookie nada mais é do que um pequeno pedaço de dados (um par String nome/valor) trocado entre o cliente e o servidor. O servidor envia o cookie para o cliente e este retoma yT9cê p9de usétt 95 c99kles péttét o cookie quando fizer uma nova solicitação. tt9Cétt 9S pq.tes de Stt'lnb n9me! Uma coisa legal dos cookies é que o usuário não se envolve - esta troca é automática (supondo que Yét19tentte 9 setYld9t e 9 cl1ente. o cliente tenha habilitado cookies, naturalmente). O sety'id9t enYIa 9 c99kIe ét9 Por padrão, um cookie vive somente enquanto dura uma sessão; uma vez que o cliente fecha o browser, o cookie desaparece. É assim que clIente, Cjye 9 enVIa de Y9ltétem o cookie "JSESSIONID" funciona. Mas você cétda S911c1taçã9 subse<tiiente. pode mandar um cookie permanecer mesmo DEPOIS que o browser éfechado. Os c99kles da sessà.9 S9mem Dessa forma, a sua aplicação ainda pode obter a informação do cookie, mesmo que a sessão com <tuand9 9 6t9Wset d9 clIente é o cliente já tenha sido finalizada há muito tempo. encettad9, mas V9ce rODE dIzet Imagine que o Kim queira mostrar o nome do usuário cada vez que ele retome ao site da cerveja. n9 Então, ele configura o cookie na primeira vez que recebe o nome do cliente, e se obtiver o cookie de clIente dep915 ~.:ueele volta com uma solicitação, ele sabe que não tem que pedir o nome de novo. E não importa se o tecLat seu cliente simplesmente reiniciou o browser ou esteve fora por uma semana! ~~~.~lect~selectBeerTaste2.do HTTPll 1 . w.W1Ckedlysmart.com . User-Agent: Mozi11a/5.0 Cookie: username==TomasH' h Accept· textl 1 . Irsc HTTP/l.l 200 OK Set-Cookie: usernaroe- _ToroasHirsch ht 1· ~ Xli ,apphcation/xml a r . ]P'm ,q-O.9,textlplaiu·q==o 8,VI'd eo/x mn . . . ,. ,pp IcatlOn/xhtml+xml ,textl Content-Type: text!htm1 eg,Image/glf;q==O.2, *1*;q==O.1 - g,lmage/png,imagel L gth. 397 Accept-Langu age: en-us,en;q==O.5 Content- en . 200303:25:40 GMT Date: Wed, 19 Nov Accept-Eucoding: gzip,deflate Server.t' Anache-Coyote/l.1 . Connection: close <htrol> r () c/tf!,,-h e"ll/tl 15.f-., de V.,/.f-o.. <lhtrol> () Si!I'ViflM' i!"Vltl i5.f-., ,l'lmeil'''. 250 capítulo 6
  • 279. gerencíamento da sessão Usando cooldes COtH a API Servlet Você pode obter headers relacionados ao cook:ie através da solicitação e da resposta HTTP, mas você não deve. Tudo o que você precisa fazer com os cook:ies foi encapsulado naAPI Servlet em três classes: HttpServletRequest, HttpServletResponse e Cook:ie. javax.servlet. http. Cookie <<inteJjaee> > Cookie(String, String) http HttpServletRequest javax.servlet. . ~tring getDomainO znt getMaxAgeO getcontextPathO < <interfaee> > String getNameO getCookiesO javax.servlet. http.HttpServletResponse etHeader(String) String getPathO g QueryString() addCookieO boolean getSecureO get addHeaderO String getValueO getSession(), J d' VIraS mais metodos ... eneoueRe zreetURLO vo~dsetDomain(String) Ii M sendErrorO vozd 'se!" Á Age(znt) . • olV1GX setStatusO vO~d setPath(String) Ii MUITOS mais métodos ... vOldsetValue(String) Ii alguns outros métodos Criando um novo cookie o CIJPls+rf.l"1-6r ClJoUe leva lIlrl Cookie cookie = new Cookie(~usernameH, name);~ .sI . I , .,..r1Pl5P1itJlrle{VafitJr. Configurando o tempo que um cookie permanecerá no cliente cookie. setMaxAge (30*60); , . O se+A4.axA'fif!: <J Jetl'P1it/itJ elrl I ~f.btJlJJ)O.s. {) caJi5tJ Ji;: Enviando o cookie ao cliente perlrlaPleg4 Vt"lItJ PltJcliePlh 'l1: 11 response.addCookie(cookie); f'i'U' 30'1f'O s'!!5l1P1Jas IrlI'P1l1+as). CaPlt~lIral" a IrlQX Recebendo o{s) cookie{s) da solicitação do cliente f'4Nl. -1ta; CIJIrl 6 3l1e 6 Co66kte Cookie [] cookies = request. getCookies (); Jesapl1.reja Ôll4P1JIJitJ for Cookiei = O; i = cookies.length; (int cookie < cookies[i]; i++) { tec~ar.~r+I1.PI+o6JSe if (cookie. getName ().equals (~usernameH) ) ;;'fJ.1rl4r tJ 5e-1-1A.axIf9e() PlIJc6IfJkte String userName = cookie.getValue(); Ll.5f..5.s~olJ~J) I tJ out.println(~Hello ~ + userName); break; r,!!Cder4 Je !J';IJ ~: " 1Itt:+"JIJ 5e-H:.IJt:J/:.te(S+rtPl5)'" ve.cê s:' pe.Je tJ~hr c"o/:.tes elltt lIlItt arr, CIJIJ/:.tee vócê hr: 1l1e ta;er lIlItt IlJtJp PIe.arr, p4ra ePlC6P1+r4r alpe1e 3l1e voee SlIer. você está aqui.. 251
  • 280. exemplo cookie Exettplo sittples de utt eoolde eustottizado Imagine que o Kim deseje criar um formulário que peça ao usuário para enviar o seu nome. O formulário chama um servlet que recebe o parâmetro usemame da solicitação e usa este valor para criar um cookie na resposta. Na próxima vez que o usuário fizer uma solicitação em QUALQUER servlet nesta aplicação, o cookie retoma com a solicitação (supondo que o cookie ainda esteja vivo, baseando-se no valor maxAge dele). Quando um servlet na aplicação vê este cookie, ele pode colocar o nome do usuário em uma resposta gerada dinamicamente, e a lógica do negócio sabe que não tem que pedir ao usuário que digite o seu nome novamente. Este cbe~go~ uma versão fie ese slmpln~~~~ ~~i'?~"d')~ acabamos de descrever. o servlet que cria e CONFIGURA o cookie import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class CookieTest extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException response. setContentType ("text/html") ; itecebe (} /7t}/MetJlJ vsv:l'l{j String name = request. getParameter ("username") ; V f!J1Vlo.tJ"J16161'W1vl:l'ia. Cookie cookie = new Cookie ("username", name); <--Cl'tfll. VNoJ16V6 c<tJfjl:le~lIe F o.I'WIlJ.jf!/7IJ. /7iJWletJ" lISVfl.l'i'eJ. <> cookie.setMaxAge(30*60); I '" Malfrff.No" (;41JMe 11lVfJJ1(j 30 W11;'V+4S. A-tJlci'6/7fl. .o C()lJl:te Ct'JWlIJ t.eatJel' tJe response. addCookie (cookie) ; <f:--_____ J l'esft'Js-ra, /I .se.,...-l.-M/tae. J J'I • RequestDispatcher view = request.getRequestDispatcher("cookieresult.jSP"); view. forward (request, response); ~ Pel'W1,--h: 3l1e lIWI J.sP crie IJ. I tJe l'eSft:lS.f-lJ. • .-I o JSP que cria a view a partir deste servlet , 1 b d <htm >< o y> <a href=" checkcookie .do">click 1útJt:IbeWl. c!al'lJ, J._'" I '" here</ a> Cli.l'aCTf:l'ls-ri'ctJ.S tJe J t.a J1atJlJ. 1-P /71's Ct)No SÓ).W1tJ.S I I'MS </body></html> t:ltJi'Q.If'lt:lS 5U'4f' VIf'IIJ. lJ.ltJae'lf'IlJrML. S tJe lIlf'I Sff'V1dj IJ.t;,tJa~ve S~lJ. J)í.s-rí .f-ailJ'lf3.J1i.".() h-ft:l tJe es-fQI'W1tJS eJ1Calf'll;,t.4J1tJ<ii paf'a lIlf'I J.sP J1';' If'IlIJ, IJ.ctJ;,/~tJf'tJJifJ ;/.0 c(J(J/::ie.() ClJlJ/::'-ejfl es-fo. ;,Q. f'(SPlJs.f1J. 116iIJ'It)/I!;el1-fIJlf'l e 3tJe 4 SlJli'cl-flJ.j';C : eI1ClJ.iIJ'It;,t.a;/a J.sP. •• 41J 252 capítulo 6
  • 281. gerenciamento da sessão ExetMplo de UtM coolde custotMizado, cottlit1uação ... o servlet que RECEBE o cookie import javax.servlet *. ~mport javax.servlet:h~tP.*; lmport ]ava.io.*; public class CheckCookie extends HttpServlet ( public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException response.setContentType(~text/html") . PrlntWrlter out = response.getWriter();' Cookie [] cookies ~ request. getCookies (); ~ecebe 6S uM/t:.tes da Sf:Jliêt-l-at/ti6. if ( cookies !~ null) { for (int i ~ O' . < . . _ ,l cookles.length; i++) Cookle cookie = cookies[i]; lf (cookie getNa . . me () .equals{~username")) I Strlng userN . _ . ame - cookle. getVal ue () . out.prlntln(~Hello ~ + userName)' '~ i .___ J ' t.!-rl'illltS dli • break; ,da ca4/l:le I'l'ilJCill'tlPlJtJ illJ'i ClJtJkl'e cl..fJ,IJ'ifJ.JiIJ If' IISI!I'Pl41J'ie • Se ele I!PlClíPl-l-I'RdtJ)IJb-l-ePlt.a a val61' e extb4-t}. Não confunda Cookies com headers! Quando você adiciona um header em uma resposta, você passa as Strings nome e valor como argumentos: response.addHeader(~foo", ~bar"); o . · : .. ;t .=~lQ'o · " I ...... '" saber i;DCê não precisa do cookie. os os me't ..• Ouos "0 I •. • : 00 00 00 000. . Mas quando você adiciona um Cookie em uma resposta, você passa um objeto Cookie. Você configura o nome do Cookie e o valor no construtor Cookie. Cookie cookie = new Cookie(~name", name); response.addCookie(cookie); •p • • ara a prova ,nao : voce' - te . : • • memorizar cad ra que • E lembre-se também de que existem o método setHeader() • I : a um dos me'to d os na • : • c asse cooki e, masdev ' • e o addHeader() (o addHeader adiciona um novo : os métodos de sol" • lCltaç era conhecer • - : valor a um header existente, caso exista, e o setHeader : para obter e adi . ao e resposta: troca o valor existente). Porém, NÃO existe um método : 10cê tamb' d czonar Cookies. : setCookie(). Existe apenas o addCookie()! : em eve conh : • construtor C. • ookie e' ecer o • • : getMaxAgeO ., IOS metodos : :.......... e set1V1axAgeO. .....•••••... : .•••........... . : você está
  • 282. momentos do ciclo da vida da sessão Os prittcipais 'ltO'ltetrtos de U'lt HttpSessiott Os momentos mais importantes na vida de um objeto HttpSession: A sessão é criada ou destruída. new invalidate Os atributos da sessão são adicionados, removidos ou substituídos por outras partes da aplicação. removeAttributeO A sessão torna-se passiva em uma VM e é ativada em outra dentro de uma aplicação distribuída. VMl prepare-se Agora para mudar eu tenho você. A- sessã" Container A-2 de IOIÍj /'tI. 1/1010. Container A-l V,(,{ptU'4 "tr!-f'o.. 254 capítuío 6
  • 283. gerenciamento da sessão Eventos do ciclo de vida da sessão Momento Tipo de Evento e Listener Ciclo de vida A sessão foi criada HtipSessionEvent Quando o Container cria uma sessão pela primeira vez. Neste momento, a sessão ainda é considerada nova (em outras palavras, o cliente ainda não enviou uma solicitação com uma session ID). A sessão foi destruída Quando o Container invalida uma sessão (porque houve um timeout da sessão, ou alguma parte da aplicação chamou o ~ Y , ~, ...•.. seu método invalidate()). Atributos Um atributo foi adicionado HttpSessionBindingEvent Quando alguma parte da aplicação chama o setAttributeO na sessão. Um atributo foi removido , Quando alguma parte da aplicação chama o removeAttributeO na sessão. ~ ... ~.'.: V Um atributo foi substituído HttpSessionAttributeListener Quando alguma parte da aplicação chama o setAttributeO na sessão e o nome do atributo já esteja associado a ela. Migração A sessão está a ponto de se tornar passiva Quando o Container está prestes a migrar (mudar) a sessão HtipSessionEvent para uma VM diferente. E chamado antes de a sessão ser movida, de forma que os atributos tenham a chance de se preparar para a migração. , A sessão foi ativada Quando o Container acaba de migrar (mudar) a sessão para uma VM diferente. É chamado antes que qualquer outra HttpSessionAttributeListener parte da aplicação possa chamar o getAttributeO na sessão, para que os atributos recém-movidos possam se preparar para o acesso. você está ~ 255
  • 284. HttpSessionBíndingListener Não se esque~ado HttpSessiot'Jit'dit'gListet'er Os eventos da página anterior são para os momentos principais na vida da sessão. Mas o HttpSessionBindingListener é para os momentos mais importantes na vida de um atributo sessão. Lembre-se do capítulo 5, onde nós vimos como você pode usá-Io ~ se, por exemplo, o seu atributo quer saber quando ele é adicionado a uma sessão, para que ele possa sincronizar-se com o banco de dados em questão (e atualizar o banco de dados quando for removido de uma sessão). Veja abaixo uma pequena revisão do capítulo anterior: o O I' I1CIJ+e illVI!X, liS-n;i'ler l?s-rlí.nf>P 1_ '" package com.example; II.K p. serv1e-r, import javax.servlet.httP.*;~ public class Dog implements HttpSessionBindingListener private String breed; public Dog(String breed) this.breed=breed; public String getBreed() return breed; U'fl U /} fo,lavt'4 !7,#Ji'lt Si5l'1l';:tCfl alie 4'Jllé,.. kbICItJA]()1I public void valueBound (HttpSessionBindingEvent event) {es+e 4-1-"l/;u-I-c. e,.. U"'<'l sess«lJ. Ii código a ser executado agora que eu sei que estou numa sessão public void valueUnbound(HttpSessionBindingEvent event) { Ii código a ser executado agora que eu sei que não faço mais parte da sessão V-NÃO configura todos os oce . d" g no DO' listeners session bm m . o o a classe Dog aqui) implementa Se uma classe a!rz~uto (com . o Container chama os callbacks o HttpSessionBmdmgLrste;el, dO e valueUnboundO) quando que tratam eventos (value o,undo nada ou removida de uma o uma instância dessa classe e a IClO sessão. É isso. E funciona. . d . - vale ara os outros lzsteners e Mas Isto NAO p o O HttpSessionListenere o sessão da págin~ ante~lOr. devem ser registrados no DD, HttpSessionAttrlbuteLrstener, -es em si diferentemente I - relacionados as sesso ' visto que ~ es s~od'IVI u aI localizado na sessão. de um atributo m "d 256 capítuio 6
  • 285. gerenCÍamento da sessão A tltigração da sessão Lembra no capítulo anterior que nós falamos brevemente sobre aplicações distribuídas, onde os pedaços da aplicação poderiam ser replicados por vários de nós na rede? Em um ambiente de clusters, o Container pode fazer um balanceamento de carga, recebendo as solicitações dos clientes e enviando-as para as NMs (que podem estar, ou não, em máquinas diferentes, mas isso não é relevante para nós). O fato é que a aplicação está em diversos lugares. Isso significa que cada vez que o mesmo cliente faz uma solicitação, esta pode acabar indo para uma instância diferente do mesmo servlet. Ou seja, a solicitação A para o Servlet A pode acontecer numa VM, e a solicitação B para o Servlet A pode ir parar numa outra VM. Então a questão é, o que acontece com os componentes como o ServletContext, ServletConfig e objetos HtlpSession? Resposta simples, implicações importantes: Apenas os objetos HttpSession (e seus atributos) são movidos de uma VM para outra. Existe apenas um ServletContext por VM. Existe um único ServletConfig por servlet, por VM. Mas existe apenas um objeto HttpServlet para uma determinada session ID por aplicação, independentemente de em quantas VMs a aplicação esteja distribuída. A aplicação Cerveja distribuída etlt duas VMs VM 1 ~" Aplicação Cerveja PI';""'iJ .5e1",11~~ eo.m!JósóS opliCQ{ióc~1f,,(/.1tt! yltt! ,y;;.psesSO~ .5eI'VI~;d-, 1iid")/((cef-"" ~SSi<>i'l; esh. dyplic(I.Jt; i'IfJ, tJ(r/-1'{I. V~ VM2 Alt:rh; es-IJ -fvJi'J diA Ilcf1.dt; I'lt; Aplicação Cerveja Sejtl'1dó Z:l óS IJÚ' 'Cs y sess:ks e((I~1tt! ebl Dpei'IfJ.SM.1Y5QI' ebl a!;tlbl d(I.Ji'J 1/ ~n+D. I} ~SJtt!fJ.sesslóJ'l I!J parQ GlJtt!fJ. dml'l>V~a dGlf1.S AlI/AlCI} ~ce ebl opliC"ffi" ~ tJ.ó~sJtt!fJ.h""f>6. você está aqui... 257
  • 286. migração da sessão A t1igração da sessão et1 ação A forma como os fabricantes de servidores lidam com c1ustering e distribuição de aplicações web varia. Não há nada na especificação J2EE que obrigue um fornecedor a dar suporte a aplicações distribuídas. Mas a figura abaixo nos dá uma idéia interessante de como isso funciona. O fundamental é que, enquanto que as outras partes da aplicação são replicadas em cada nóNM, os objetos sessão são movidos. E isto é garantido. Logo, se o fornecedor realmente suporta aplicações distribuídas, o Container é requerido para migrar as sessões através das VMs. E isso inclui migrar os atributos da sessão também. o Diane seleciona "Clara" e c1icano botão submit. o Container cria uma nova sessão, ID n2.343. O cookie "JSESSIONID é devolvido para Diane na resposta (não mostrado). o servidor de balanceamento de carga decide enviar a solicitação para o Container A-i na VM Um. Servidor/Container de balanceamento de carga e Diane seleciona "Amarga" e c1icano botão submit. Sua Desta vez, o servidor de balanceamento de O Container recebe a solicitação, verifica a session solicitação também inclui o carga decide enviar ID e percebe que a sessão está "JSESSIONID" n2.343. a solicitação para o em uma outra VM, a VM Um! Container A-2 na VM Dois. o o Servidor/Container de balanceamento de carga Container A-2 258 capítulo 6
  • 287. gerenciamento da sessão e A sessão n9.343 migra da VM Um para a VM Dois. Ou seja, ela não existe mais na VM Um, já que ela se mudou para a VM Dois. Esta migração significa que a sessão se tornou VM 1 passiva na VM Um e foi ativada na VM Dois. Container A-1 Servidor/Container de balanceamento de carga VM 2 Container A-1 O Container cria uma nova thread para o Servlet A e associa a nova solicitação à sessão recém- movida n9.343. A nova solicitação de Diane é enviada para a thread e todos saem felizes. Diane não tem idéia do que aconteceu (exceto pelo breve atrasol latência na espera da migração da sessão). Servidor/Container de balanceamento de carga você está lt- 259
  • 288. HttpSessionActivationListener o HttpSessiottAetivatioKListmer deixa os atributos protrtos para a graKde tMUdaKça ... Este Iistener é tão parecido com um atributo, que eu consigo descobrir Já que épossível migrar um HttpSession de uma VM para outra, quando eu estou para Ser movido para os desenvolvedores da especificação pensaram que seria legal uma nova VM como parte de uma sessão, se alguém se preocupasse em dizer aos atributos dentro das e posso ter certeza de que as variáveis sessões que eles também estão prestes a mudar. Dessa forma, os da minha instância estão prontas ... atributos podem garantir que sobreviverão à mudança. Se todos os seus atributos são objetos Serializáveis de verdade, que não se importam onde eles serão colocados, o você talvez nunca use este listener. Aliás, imaginamos que a 95,324% de todas as aplicações nunca usem este listener. Mas ele está lá caso você precise. Seu uso mais provável é dar aos atributos uma chance de preparar as variáveis da sua instância para a Serialização. A migração da sessão e a Serialização Agora fica meio confuso ... Um Container é exigido para a migração dos atributos Serializáveis (o qual assume que todas as variáveis da instância dentro do atributo ou são <<interface> > Serializáveis, ou são nulas). Mas um Container não é exigido para usar a HttpSessionActivationListener Serialização para migrar o objeto HttpSession! O que isto significa para você? Simples: sess~onDi~ctivate(HttpSesSionEventj garanta que os tipos das suas classes de seSSlOn WiJIPassivate(HttpSessionEventj atributos sejam Serializáveis e você nunca terá que se preocupar com isso. Mas se eles não forem Serializáveis (em virtude de uma das variáveis da instância do objeto atributo não ser Serializável), faça com que a classe do seu objeto atributo implemente o HttpSessionActivationListener e use os callbacks ativação! passividade para contornar o problema. o Container não é REQUERIDO para usarmos a Serialização, por isso não há nenhuma garantia de que o readObject() e o writeObject() serão chamados no atributo Serializável ou em uma das variáveis da sua instância! Se você está familiarizado com a Serialização, você sabe que uma classe que implementa esse recurso também pode escolher implementar um método writeObjectO, chamado pela VM sempre que um objeto for serializado, e um método readObjectO, chamado quando ocorrer o inverso. Um objeto Serializável pode usar estes métodos para, por exemplo, configurar nulos os campos não- Serializáveis durante a Serialização (writeObjectO), e então restaurar os campos quando ocorrer o processo inverso (readObjectO). (Se você NÃO estáfamiliarizado com os detalhes da Serialização, não se preocupe.) Mas os métodos não serão, necessariamente, chamados durante a migração da sessão! Portanto, se você precisa salvar e restaurar o estado da variável da instância no seu atributo, use o HttpSessionActivationListener e use os dois eventos de callbacks (sessionDidActivateO e sessionWillPassivateO), assim como você usaria o readObjectO e o writeObjectO. 260 capítulo 6
  • 289. gerencíamento da sessão Exeiflplos de listcmer Nas duas páginas a seguir, preste atenção nos tipos do objeto evento e se o listener é também uma classe atributo. o contador da sessão Este listener permite que você acompanhe a quantidade de sessões ativas na aplicação. Muito simples. package com.example; import javax.servlet.http.*; public class BeerSessionCounter implements HttpSessionListener { static private int activeSessions; ~s';"a classe se;,,: ;/i's';"rtbll{Ja e", wí6-IIJFlclasses C<l""<l ';"<lJ4s as 611';";"IJ.S classes da apftclJ.{i<l)'IJ.;"1J. public static int getActiveSessions() { ~ óve ';"ó;/ós 6,s ,se;"lIfe';"s e 4S 611+;"4S return activeSessions; cllJ.sses /l.ssts-/-e,,-/-es P6SSIJ.'" acessa;" es-/-e "'~';"6J6. public voíd sessionCreated(HttpSessionEvent activeSessíons++; event) {~ ,I fshs ""'fff)JI)S Cfl.l"l"e541r< Vir< H++,Ses slt:'l'Jíve"./-. publíc void sessionDestroyed(HttpSessionEvent event) {~ actíveSessions--; Configurando o Iistener no DD <web-app ...> <listener> <listener-class> com.example.BeerSessionCounter </listener-class> </listener> </web-app> você está aqui ~ 261
  • 290. atributo de sessão listener Exettplos de Iistet1er o Listener Attribute ís+e 'ts+el'/el" usa V"" I'IlJ""f! Este listener permite rastrear cada vez que algum atributo é I';;Ci:>I'!Sts+el'l+el<j>esal"/e ser - ' u"" acrescentado, removido ou substituído em uma sessão. / 'ts+eller IJrHt'lbil+e) recebe iI"" wewf-i:>8'-1'1'/'';;3_ package com.example; import javax.servlet.http.*; public class BeerAttributeListener implements HttpSessiOnAttributeListener public void attributeAdded(HttpSessionBindingEvent event} ( String name event. getValue () j Obj ect value == event. getName (); "7.. O HHpSessianílle,,-I- Wf!"-!-". ,JieSf!"ca,Jie"iIes+eva!,,/' per""r+e a lI<lcê "11i:>""e" e ,/<la-!-I'lbu+" óue System.out.println{"Attribute added: " + name + ": " + value); public void attributeRemoved(HttpSessionBindingEvent event} ( String name = event.getName(); Object value ~ event.getValue{); System.out.println("Attribute removed: " + name + ". " + value); public void attributeReplaced(HttpSessionBindingEvent event} ( String name = event.getName(); Object value ~ event.getValue(); System.out.println("Attribute replaced: " + name + ". " + value); Configurando o listener no DD <web-app ...> <listener> <listener-class> com.example.BeerAttributeListener </listener-class> </listener> </web-app> r: Ei, onde você está exibindo? Onde entra o System.out na aplicação? Jt: Para onde quer que o Container decida enviá-Io (que você pode ou não configurar). Em outras palavras, um lugar determinado pelo fabricante, geralmente um arquivo de log. O Tomcat coloca a saída em tomcaUlogs/catalina. log. Você terá que ler a documentação do seu servidor para descobrir o que o seu Container faz com a saída-padrão. 262 capítulo 6
  • 291. ExetMplos de listmer A classe atributo (escutando eventos que afetam o IT) Este listener permite que um atributo acompanhe os eventos que possam ser importantes para o próprio atributo - quando ele é acrescentado ou removido de uma sessão e quando a sessão migra de uma VM para outra. package com.example; import javax.servlet.http.*; import java.io.*; public class Dog implements HttpSessionBindingListener, HttpSessionActivatiOnListener,Serializable private String breed; Ii imagine outras variáveis da instância, incluindo Ii algumas que não sejam Serializáveis Ii imagine o construtor e outros métodos get e set public void valueBound(HttpSessionBindingEvent event) Ii código a ser executado agora que sei que estou em uma public void valueUnbound(HttpSessionBindingEvent event) { Ii código a ser executado agora que sei que não faço mais parte da sessão public void sessionWillPassivate(HttpSessionEvent event) Ii código para obter meus campos não-Serializáveis em um Ii que possa sobreviver à mudança para uma nova VM public void sessionDidActivate(HttpSessionEvent event) { Ii código para restaurar meus campos ... para refazer tudo tenha feito Ii no sessionWillPassivate() o qco oc OãO:--'~ tLve"l.f.tJsde fl.f.lV4{i4 do. sess';tJ (~t!s abstt've as ~:.f.(,jd{)s CfJ.t't'e54" u. H#p.:5es slt:mtLve",.f). você está
  • 292. sessão listeners Os Listetters relaciottados à Sessão ? classe Cenário attributeRemoved s1t,,,A-Hrt/;l/-/-eíve.,.f atributo classe i1ei1t.v~ O sessionDidActivate attributeAdded sessionCreated Iistener/métodos A classe(javax.servleLhttp ) interface classe Geralmente valueBoundHHf'5es AJ~+b.:PJ4C f!.xtsh HttpSessionBindingEvent atributo Vds+e nft"hVJJ1 valueUnbound outra HttpSessionActivationListener DUma HttpSessionEvent HttpSessionBindingListener HttpSessionAttributeListener attributeReplaced do evento Tipo HttpSessionEvent HttpSessionListener AJ/Jfa: nõ'6 ~ Alguma (javax.servleLhttp) HHf'Sess1i>"IrHri/fl,1-/-eíve,,-I- sessionDestroyedoutra Alguma Uma classe cê desteforem sejam uma sessão. ou removidos de eles tipo associados notificados saber por implementado Você quer quando ~ Alguma outra Você quer saber Alguns dos eventos relacionados à sessão n~o seguem os pa d roes de nomenclatura para os eventos. - Os métodos HttpSessionListener adotam os HttpSessionEven~s. . . Os métodos HttpSessionBindingListener adotam os HttpSesslOnBmdmgEvents. Porém, os métodos HttpSessionAttributeListener empregam o HttpSessionBindingEvents. . E os métodos HttpSessionActivationListener empregam o HttpSessl~nEvents. Járfiqu~t clatssbeesmHtn~Soe~~~;:~:~;s~::~~:~:~c~:~:~;:;;:~~1:;;~~~;:;; as pe el amen e , de eventos na API. 264 capítulo 6
  • 293. geref~lciélmienl'oda sessã Os Ustmers para Evemos relaciotlados à Sessão e utlta visão geral da API Objetos Evemo < <interfaee> > HttpSessionActivationListener sessionDidActivate(HttpSessionEvent) session WiIlPassivate(HttpSessionEvent) HtipSessionEvení < <interfaee> > HttpSessionListener sessionCreated(HttpSessionEvent) sessionDestroyed(HttpSessionEvent) < <interfaee> > HtpSe~wnBmmngL~wn" HttpSessionBindingEvení valueBound(HttpSessionBindingEvent) valueUnbond(HttpSessionBindingEvent) getSessionO getNameO getValueO < <interfaee> > HtpSessionAttributeListener attributeAdded(HttpSessionBindingEvent) attributeRemoved(HttpSessionBindingEvent) attributeReplaced(HttpSessionBindingEvent) tJ ~tJ(/6 ~tJ.~ ~tV'1?4. 6~ Ja .:s.f.f"Í15til) trl-rt~V+41JtIf ti.ese~aJelW 6 tJ 1Pié+4Jó~/IJeO ~tlf'~a t!J; 1I1J,/(Jf' JtI J6 l)fJ~tI; Jese~t:aJelW ., eve~.,. f'~6f'~tJ. 6 tJ.~5(j iltJ./Óf'J e ., ~"VtJ. Is-I-<Js;~lltc4 1Ft ele re:+61"1?4. 118.161" () trl-1"t1JIJ-/-,(J suJa tJ 1JIJe ,6S A-AJrí:5 Jfi. IPI.{JJtJ.#1ftJ.1;IJe jtf'lW (j eve~d você está
  • 294. sessão Iisteners Os Listetters relaeiottados à sessão Sim, esta é uma cópia quase fiel da tabela que vimos duas páginas atrás, então não vale olhar. Tente imaginar estes listeners e anote seus melhores palpites. Você pode esperar por no mínimo duas, ou até quatro perguntas sobre os listeners da sessão na prova. Use a memória e o bom senso para preencher a tabela. Cenário A interface Iistener/métodos Tipo do evento Geralmente implementado por classe D Alguma outra atributo Você quer saber D Uma DUma classe sessão. classe D Alguma outra 'OJuaA:>! p!qo o ap sod!J S!OP svuadv maJs!xa :g;)!<I 266 capl'tulo 6
  • 295. 'Pausa pata 9 caté 1 Dado: 10. pub1ic class MyServlet extends HttpServlet { 11. public void doGet(HttpServletRequest request, HttpServletResponse response) 12. Ii throws IOException, ServletException 17. 16. 15. 14. 13. 18. request.getSession() .setAttribute(~key", ~value"); request.getHttpSession() .setAttribute(~key", ~value"); «HttpSession)request.getSession(» .setAttribute(~key", ~value"); «HttpSession)request.getHttpSession(» .setAttribute(~key", ~value"); Qual(is) linha(s) poderia(m) ser desanotada(s) sem causar erros de compilação ou runtime? (Escolha todas as que se aplicam.) DA. Somente a linha 13. DB. Somente a linha 14. Dc. Somente a linha 15. DD. Somente a linha 16. DE. Linhas 13 ou 15. DF. Linhas 14 ou 16. 2 Se um cliente NÃO aceita cookies, qual mecanismo de gerenciamento da sessão o web container pode utilizar? (Escolha uma.) DA. Cookies, mas NÃO reescrita de URL. OB. Reescrita de URL, mas NÃO cookies. Dc. Tanto os cookies, como a reescrita de URL podem ser usados. DD. Nem os cookies, nem a reescrita de URL podem ser usados. DE. OS cookies e a reescrita de URL devem ser usados juntos. você está aquj ••. 267
  • 296. teste preparatório 3 Quais declarações sobre os objetos HttpSession são verdadeiras? (Escolha todas as que se aplicam.) DA. Uma sessão cujo tempo de timeout foi estipulado em -1 nunca expirará. DB. Uma sessão tomar-se-á inválida assim que o usuário fechar todas as janelas do seu browser. De. Uma sessão tomar-se-á inválida depois do tempo de timeout definido pelo servlet container. DD. Uma sessão pode ser explicitamente invalidada chamando o HttpSession. invalidateSession(). 4 Quais das segúintes opções NÃO representam tipos de eventos listener na API J2EE 1.4? (Escolha todas as que se aplicam.) [JA.HttpsessiOnEvent DB. ServletRequestEvent De. HttpSessionBindingEvent DD.HttpsessiOnAttributeEvent C}E.servletContextAttributeEvent 5 Quais das seguintes declarações sobre o monitoramento da sessão são verdadeiras? (Escolha todas as que se aplicam.) C}A. A reescrita de URL pode ser usada por um servidor como base para o monitoramento de sessões. C}E. O SSL tem um mecanismo nativo, que um container servlet pode usar para obter dados usados para definir uma sessão. De. Ao usar cookies para acompanhar as sessões, não há restrições para o nome do cookie que realiza o acompanhamento da sessão. C}D. Ao usar cookies para acompanhar as sessões, o cookie usado para acompanhar a sessão deve receber o nome de JSESSIONID. [JE. Se o browser de um usuário está desabilitado para receber cookies, o container pode decidir usar um objeto javax. servlet. http.CookielessHttpSession para monitorar a sessão do usuário. 268 capítulo 6
  • 297. gerenciamento da sessão 6 Dado: 1. import javax.servlet.http.*; 2. public class MySessionListener implements HttpSessionListener 3. public void sessionCreated() { 4. System.out.println(~Session Created"); 5. 6. public void sessionDestroyed() { 7. System.out.println(~Session Destroyed"); 8. 9. o que há de errado com esta classe? (Escolha todas as que se aplicam.) DA. A assinatura do método na linha 3 está INCORRETA. DB. A assinatura do método na linha 6 está INCORRETA. De. A declaração import não importará a interface HttpSessionListener. DD. O sessionCreated e o sessionDestroyed NÃO são os únicos métodos definidos pela interface HttpSessionListener. 1 Quais declarações sobre os atributos da sessão são verdadeiras? (Escolha todas as que se aplicam.) DA. O tipo de retomo do HttpSession.getAttribute (String) é Object. DB. O tipo de retomo do HttpSession.getAttribute (String) é String. De. OS atributos associados a uma sessão ficam disponíveis para qualquer servlet que faça parte do mesmo Serv1.etContext, e que trate uma solicitação identificada como sendo parte da mesma sessão. DD. Chamar o setAttribute (~keyA", ~va1.ueB")em um HttpSession que já possua um valor para a chave keyAcausará uma exceção. DE. Chamar o setAttribute (~keyA", ~valueB") em um HttpSession que já possua um valor para a chave keyAfará com que o valor anterior para este atributo seja substituído pela String valueB. você está •• 269
  • 298. teste preparatório 8 Quais interfaces definem um método getSession () ? (Escolha todas as que se aplicam.) C]i.ServletRequest C]B. ServletResponse C]C. HttpServletRequest C]D. HttpServletResponse 9 Seja um objeto sessão s e o código: s.setAttribute{~key", value); Quais dos listeners podem ser notificados? (Escolha um.) Di. ipenas o HttpSessionListener. C]B. ipenas o HttpSessionBindingListener. C]C. ipenas o HttpSessionAttributeListener. C]D. O HttpSessionListener e o HttpSessionBindingListener. C]E. O HttpSessionListener e o HttpSessionAttributeListener. C]E O HttpSessionBindingListener e o HttpSessiOnAttributeListener. 00. Todos os três. 10 Considerando que req é um HttpServletRequest, quais das opções criam uma sessão, caso não exista nenhuma? (Escolha todas as que se aplicam.) Di.req.getsession{) ; C]B. req.getSession{true); C]C. req. getSession (false) ; C]D. req. createSession () ; DE. req.getNewSession{); C]F.req.createSession{true); 00. req. createSession (false) ; 270 capítulo 6
  • 299. gerencíamento da sessão 11 Dado o objeto sessão s com dois atributos chamados myAttrl e myAttr2, quais alternativas removerão ambos os atributos desta sessão? (Escolha todas as que se aplicam.) CJi. s.removeAllValues(); [JB. s.removeAttribute(~myAttrl");s.removeAttribute(~myAttr2"); [Je. s. removeAllAttributes () ; [JD. s. getAttribute (~myAttrl", UNBIND); getAttribute s. (~myAttr2", UNBIND); [JE. s. getAttributeNames (UNBIND) ; 12 Quais das seguintes declarações sobre os objetos HttpSession em um ambiente distribuído são verdadeiras? (Escolha todas as que se aplicam.) CJA Quando uma sessão é movida de uma NM para outra, quaisquer atributos armazenados na sessão serão perdidos. DE. Quando uma sessão é movida de uma NM para outra, os objetos HttpSessionBindingListener devidamente registrados serão notificados. De. Quando uma sessão é movida de uma NM para outra, os objetos HttpSessionActivationListener devidamente registrados serão notificados. DD. Quando uma sessão é movida de uma NM para outra, os valores dos atributos que implementam j ava. io. Serializable serão transferidos para a nova NM. 13 Quaisdeclarações sobre o timeout das sessões são verdadeiras? (Escolha todas as que se aplicam.) DA is declarações de timeout da sessão que foram criadas no DD aceitam o tempo em segundos. DE. is declarações de timeout da sessão que foram criadas no DD aceitam o tempo em minutos. De. is declarações de timeout da sessão que foram criadas programaticamente aceitam o tempo em segundos. DD. is declarações de timeout da sessão que foram criadas programaticamente aceitam o tempo em minutos. CJE. is declarações de timeout da sessão que foram criadas programaticamente aceitam o tempo em minutos ou segundos. você está
  • 300. teste preparatório 14- Escolha o trecho do código servlet que ativaria a partir de uma solicitação o valor de um cookie denominado "ORA_UID"? (Escolha todas as que se aplicam.) DA. String value = request.getCookie("ORA_ UID"); DB. String value = request.getHeader("ORA_ UID"); Dc. javax.servlet.http.Cookie[] cookies = request.getCookies(); String cName = null; String value = null; if (cookies !~ null) { for (int i = O; i < cookies.length; i++) { cName = cookies[i] .getName(); if (cName != null && cName.equalsIgnoreCase(~ORA_UID")){ value = cookies[i] .getValue(); } DD. javax.servlet.http.Cookie[] cookies = request.getCookiesO; if (cookies.length > O) { String value = cookies[O] .getValue(); 15 Qual(is) método(s) pode(m) ser usado(s) para pedir ao contêiner para notificar seu aplicativo sempre que uma sessão estiver com o tempo esgotado? (Escolha tudo que se aplica.) DA. HttpSessionlistener.sessionDestroyed; DB. HttpSessionBindingListener.valueBound; Dc. HttpSessionBindingListener.valueUnbound; DD. HttpSessionBindingEvent.sessionDestroyed; DE. HttpSessionAttributeListener.attributeRemoved; DF. HttpSessionActivationListener.sessionWillPassivate; 272 6
  • 301. gerenciamento da sessão 16 Como você usaria o objeto HttpServ1.etResponse em um servlet para adicionar um cookie no cliente? (Escolha todas as que se aplicam.) DA. <context-param> <param-name>myCookie</param-name> <param-va1ue>cookieVa1ue</param-va1ue> </context-param> DB. response.addCookie("myCookie"," cookie Value"); Dc. javax.servlet.http.Cookie newCook = new javax.serv1et.http.Cookie(~myCookieH,HcookieValueH); // ...set other Cookie properties response.addCookie(newCook); DD. javax.servlet.http.Cookie[] cookies = request.getCookiesO; String cname ~ nu11; if (cookies != nu11) { for (int i = O; i < cookies.1ength; i++) { cName ~ cookies[i] .getName(); if (cName !~ nu11 && cName.equa1sIgnoreCase(~myCookieH»){ out.print1n( cName + ~: ~ + cookies[i] .getVa1ue(); 11 Dado: 13. pub1ic c1ass Serv1etX extends HttpServ1et { 14. pub1ic void doGet (HttpServ1etRequest req, HttpServletResponse resp) 15. throws IOException, Serv1etException { 16. HttpSession sess = new HttpSession (req); 17. sess.setAttribute(~attr1H, 18. sess.invalidate(); 19. String s = sess.getAttribute(~attr1H); 20. 21. } Qual é o resultado? (Escolha tudo que se aplica.) DA. A compilação falha DB. O valor de s é null De. O valor de s é "value" DD. Uma IOException é enviada DE. Uma ServletException é enviada DF. Uma IllegalStateException é enviada você está ~ 273
  • 302. respostas do teste 1Dado: 10. public class MyServlet extends HttpServlet { 11. public void doGet(HttpServletRequest request, HttpServletResponse response) 12. Ii throws IOException, ServletException 16. 15. 14. 17. 13. 18. request.getSession() .setAttribute(~key", ~value"); request.getHttpSession() .setAttribute(~key", ~value"); «HttpSession)request.getSession(» .setAttribute(~key", ~value"); «HttpSession)request.getHttpSession(» .setAttribute(~key", ~value"); Qual(is) linha(s) poderia(m) ser desanotada(s) sem causar erros de compilação ou runtime? (Escolha todas as que se aplicam.) DA. Somente a linha 13. DB. Somente a linha 14. Dc. Somente a linha 15. DD. Somente a linha 16. ~ E. Linhas 13 ou 15. DF. Linhas 14 ou 16. Z Se um cliente NÃO aceita cookies, qual mecanismo de gerenciamento da sessão o web container pode utilizar? (Escolha uma.) DA. Cookies, mas NÃO reescrita de URL. (.5ervle.f-v2.'~f~' S7 ~ B. Reescrita de URL, mas NÃO cookies. Dc. Tanto os cookies, como a reescrita de URL podem ser usados. OD. Nem os cookies, nem a reescrita de URL podem ser usados. - A- /jfJ';~ es.f-: CÓl'l"fl.f-fJ.; DE. OS cookies e a reescrita de URL devem ser usados juntos. f/j~l~e Ctl_ff;S) I-JA-o POJ)f.M.~?(/;fJ.;:: 4{'I.$4 l"eeSCI'IT"IJ. ",e "" ••.• AJA-o tiepenJe tie 3(/f! eles es.f-tja4 f"dtlt.f-a.tiós. 274 capítulo 6
  • 303. gerenciamento da sessão 3 Quais declarações sobre os objetos HttpSession são verdadeiras? (Escolha todas as que se aplicam.) (Servle-l-v2.~p~. S"9) Iilr A. Uma sessão cujo tempo de timeout foi estipulado em -1 nunca expirará. OB. Uma sessão tomar-se-á inválida assim que o usuário fechar todas as janelas do seu browser. ~ C. Uma sessão tomar-se-á inválida depois do tempo de timeout definido pelo servlet container. OD. Uma sessão pode ser explicitamente invalidada chamando o HttpSession. invalidateSession(). - A- DfSãó!J es-l-: tÍ'/cÓN'e-l-~ plu'ave <l ",Ht:uill ave - A- ófSãó 5 es-l-: devert). ser I/stldó ct.a",a-se tÍ'/valtda-hO. eXis-h: v", stPial de 3ve ti sessãó acabóv. 4 Quais das seguintes opções NÃO representam tipos de eventos listener na API J2EE IA? (Escolha todas as que se aplicam.) OA. HttpSessionEvent OB. ServletRequestEvent OCo HttpSessionBindingEvent IilrD.HttpSeSSiOnAttributeEvent OE.servletContextAttributeEvent 5 Quais das seguintes declarações sobre o monitoramento da sessão são verdadeiras? (Escolha todas as que se aplicam.) <'Servle+- Iilr A. A reescrita de URL pode ser usada por um servidor como base para o monitoramento de sessões. Iilr B. O SSL tem um mecanismo nativo, que um container servlet pode usar para obter dados usados para definir uma sessão. Oe. Ao usar cook:ies para acompanhar as sessões, não há restrições para o nome do cookie que realiza o acompanhamento da sessão. Iilr D. Ao usar cook:ies para acompanhar as sessões, o cookie usado para acompanhar a sessão deve receber o nome de JSESSIONID. DE. Se o browser de um usuário está desabilitado para receber cook:ies, o container pode decidir usar um objeto javax. servlet. http.CookielessHttpSession para monitorar a sessão do usuário. - A- ~PSãó í es-l-: tÍ'/c6N'e-l-tl)fór3ve '1ãó exls-!-e es-l-a c/4S5e. você está IP 275
  • 304. respostas do teste 6 Dado: 1. import javax.servlet.http.*; 2. public class MySessionListener implements HttpSessionListener 3. public void sessionCreated() { 4. System.out.println(~Session Created"); 5. 6. public void sessionDestroyed() { 7. System.out.println(~Session Destroyed"); 8. 9. 8 - fJrs "pí.';es fJr e es-l-';" c""'t'e-l-4sJ f"t'3ve eshs é-l-'Jfl"s tievel'l"Q. hl' ti•.•p4t'M..e+l''' •.• •.• HHpSes sl(JIfLve.rl-. O que há de errado com esta classe? (Escolha todas as que se aplicam.) ~ A. A assinatura do método na linha 3 está INCORRETA. - fJr "P'j';t) C es-l-: ~Ptc4N'e-l-4J ~ B. A assinatura do método na linha 6 está INCORRETA. pt:II"3ve" lishlfel' e ofel,PtIi;f"IfD p4c6h i"'f>"1'-I-4ti6. Dc. A declaração import não importará a interface HttpSessionListener. DD. O sessionCreated e o sessionDestroyed NÃO são os únicos métodos definidos pela interface HttpSessionListener. - fJr lJp,';6!J es-l-: IPtc(Jl'l'e-l-~ptJI'11'e eshs s'; •• tJS tids tJ..,ic/JS ""é=l-tJtitJs Ifes-l-a ,Pt-h,..{ace. 1 Quais declarações sobre os atributos da sessão são verdadeiras? (Escolha todas as que se aplicam.) (Sel'vle-l- 11 2..~ p~. S-9) ~ A. O tipo de retomo do HttpSession.getAttribute (String) é Object. DB. O tipo de retomo do HttpSession.getAttribute (String) é String. ~ C. Os atributos associados a uma sessão ficam disponíveis para qualquer servlet que faça parte do mesmo ServletContext, e que trate uma solicitação identificada como sendo parte da mesma sessão. OD. Chamar o setAttribute (~keyA", ~valueB") em um HttpSession que já possua um valor para a chave keyAcausará uma exceção. ~ E. Chamar o setAttribute (~keyA", ~valueB") em um HttpSession que já possua um valor para a chave keyAfará com que o valor anterior para este atributo seja substituído pela String valueB. 8 - fJr tJP'j';tJ es-l-~ IPtc61'1"e-l-t!..J p61'{pe tJ - fJr 6f,';" Õ es-l-: IPtC61"1"e+~fóI"3{jei!f-l-a -I-ip" tie 1"e+"1"If6e 0!(jec+. ja d,a_tio. apel1f),Ssvbs-l-,.-I-v""'f), ) Vf),I",.. ( exishl1h. 276 capítulo 6
  • 305. gerencíamento da sessão 8 Quais interfaces definem um método getSession{)? (Escolha todas as que se aplicam.) eli. ServletRequest elB. ServletResponse ~C.HttpServletRequest elD. HttpServletResponse 9 Seja um objeto sessão 5 e o código: s.setAttribute(~key", value); Quais dos listeners podem ser notificados? (Escolha um.) eli. ipenas o HttpSessionListener. elB. ipenas o HttpSessionBindingListener. elC. ipenas o HttpSessionAttributeListener. elD. O HttpSessionListener e o HttpSessionBindingListener. elE. O HttpSessionListener e o HttpSessionAttributeListener. ~ F. O HttpSessionBindingListener e o HttpSessionAttributeListener. DG. Todos os três. - Pr 4plã4 Fé li C41'1'rl-fl.)p4t''lll'!. VIYI, H#p5es Si61'1t;r#I'''!w/~L''s+el'1l!.I' I!.114+'-llCfl.d<lse""I'e 3"; VIYIa.f-l't!IlI-l-<I I!.aCl"escel'l-l-ad<l) e <I <lfje-l-tl valtll" .f-alYlIJelYt sel"a I1tl+'-llcfl.d<l se ele iJty>lelYlelrÍ-fl.l' VlYtff#p5essl41'18t"ldtI'15L,"sI-e",el". 10 Considerando que req é um HttpServletRequest, quais das opções criam uma sessão, caso não exista nenhuma? (Escolha todas as que se aplicam.) ~ i. req.getSession{); ~B. req. getSession (true) ; elC. req.getSession(false); - Prs tlpjces Pr e 8 cri"tJ.I'';<I"IYtfl."'''lia Cfl.Stl l'l6.tl ex'"s+-fI. "IYta. O 5rl-5essftll'l(IfJ.lstl) I'e.f-"I'I'IfJ. tllYI elD. req. crea teSession () ; l'es"l-I-ad6 "Ivl" se fi. S(,SS';<l '"146 elE. req.getNewSession(); elE req. createSession (true) ; elG. req. createSession (false) ; você está li> 277
  • 306. res.lJostas do teste 11 Dado o objeto sessão s com dois atributos chamados myAttrl e myAttr2, quais alternativas removerão ambos os atributos desta sessão? (Escolha todas as que se aplicam.) DA. s. removeAllValues () ; ~B. s.removeAttribute(~myAttrl");s.removeAttribute(~myAttr2"); De. s. removeAllAttributes () ; DD. s.getAttribute(~myAttrl", UNBIND) ;s.getAttribute(~myAttr2", UNBIND); DE. s. getAttributeNames (UNBIND) ; - /} cp{õ,c 8 es+: cCI'I'e+a. e> reIMclleA-#rl/JlI+eO é a tfJ'JlcafUIMtI. de reIMCllerIMCS VIMa+l'lltll+C de VIMctje+ó sess46; e ele reIMclle VIMa+l'lltv+c de cada lIe;. 12 Quais das seguintes declarações sobre os objetos HttpSession em um ambiente distribuído são verdadeiras? (Escolha todas as que se aplicam.) (5ervle+v2..~pt.s. (,0) DA. Quando uma sessão é movida de uma NM para outra, quaisquer atributos armazenados na sessão serão perdidos. DE. Quando uma sessão é movida de uma NM para outra, os objetos HttpSessionBindingListener devidamente registrados serão notificados. ~ C. Quando uma sessão é movida de uma NM para outra, os objetos HttpSessionActivationListener devidamente registrados serão notificados. ~ D. Quando uma sessão é movida de uma NM para outra, os valores dos atributos que implementam java. io. Serializable serão transferidos para a nova NM. 13 Quais declarações sobre o timeout das sessões são verdadeiras? (Escolha todas as que se aplicam.) (A-fI) DA. As declarações de timeout da sessão que foram criadas no DD aceitam o tempo em segundos. ~ E. As declarações de timeout da sessão que foram criadas no DD aceitam o tempo em minutos. ~c. As declarações de timeout da sessão que foram criadas programaticamente aceitam o tempo em segundos. DD. As declarações de timeout da sessão que foram criadas programaticamente aceitam o tempo em minutos. DE. As declarações de timeout da sessão que foram criadas programaticamente aceitamo tempo em minutos ou segundos. c Se espect/lcal' cs IMi'J'1V+cs. flSal'IMóS{;SlDJ'J-+,'w,ecl.I+:>~ f-cJew"t;s -lJólJlJ; se IISfJ,t'IMCSeleIMe'l+c <ses se+MlJ.xI'Iac~·veI'I+ervtl.IO s rJó ft#pSesS'i'c"l; ape"lfJs6S se51.1"1rJós p6r1eIMseI' especr-li'caJ6S'. 278 capitulo 6
  • 307. gerenciamento da sessão 14 Escolha o trecho do código servlet que ativaria a partir de uma solicitação o valor de um cookie denominado "ORA_ UID"? (Escolha todas as que se aplicam.) DA. String value = request.getCookie("ORA _illD"); DB. String value = request.getHeader("ORA _UID"); li2' c. javax.servlet.http.Cookie[] cookies = -If (Jp{á(J If f"efef'e- S't: 4 tllfI lfIé.f(JtJ(J request.getCookies(); Ôllt: "â.(J t:xtsh. String eName ~ null; - If (JPSâ.(J f"ect:be 1I1f1 41'1'" C C(J"kte String if value (eookies = null; != null) { , lIsa"tJ(J (J reÔlles.f'5~óók"e$()J de "(Jlfle espec,ftc(J. e tJepói'$ verlflca a exts+eJfci'fJ; tJe IIIf1 cóó/:te for (int i = O; i < eookies.length; i++){ eName = eookies[i].getName(); -If ópSâ." b 1J11.44pf!114$ tl p"tlflt:if"tl if (cName != null && Có"l:te Jfó tAl'f"4j. eName.equalsIgnoreCase(~ORA_UID"»){ value ~ cookies[i].getValue(); } DD. javax.servlet.http.Cookie[] cookies = request. getCookiesO; if (eookies.length > O) { String value ~ eookies[O] .getValue(); 15 Qual(is) método(s) pode(m) ser usado(s) para pedir ao contêiner para notificar seu aplicativo sempre que uma sessão estiver com o tempo esgotado? (Escolha tudo que se aplica.) li2' A. HttpSessionlistener.sessionDestroyed; DB. HttpSessionBindingListener.valueBound; li2' C. HttpSessionBindingListener.valueUnbound; DD. HttpSessionBindingEvent.sessionDestroyed; DE. HttpSessionAttributeListener.attributeRemoved; DF. HttpSessionActivationListener.sessionWillPassivate; você está 11> 279
  • 308. reSiPos:tas do teste 16 Como você usaria o objeto HttpServletResponse em um servlet para adicionar um cookie no cliente? (Escolha todas as que se aplicam.) DA. <context-param> - jf $ Dffã •• es+~ il'/c{>l"l"e+a,;ffJf'3l1e (> <param-name>myCookie</param-name> ""fj-lNJIJ ~JdC<)fJJ:i'eO ehlpl'ej" li"" IJtje-l- •• C6fJtte) e I'/ã•• :5+1"I"1'I5s, •• <param-value>cookieValue</param-value> </context-param> - /} "ffã6 b es+: '''''CIJI''I'e+a,; p"l"?Jve eltJ.""6S+I'~ V"" servle+ (J;·/-lV{J;I7J6) e OB. response.addCookie("myCookie"," cookie Value"); Cf'i'o.I1JIJ11""cÕ6/i:ie. ~ C. javax.servlet.http.Cookie newCook = new javax.servlet.http.Cookie(~myCookie","cookieValue"); // ...set other Cookie properties response.addCookie(newCook); OD. javax.servlet.http.Cookie[] cookies = request.getCookiesO; String cname = null; if (cookies !~ null) { for (int i = O; i < cookies.length; i++) ( cName = cookies[i] .getName(); if (cName != null && cName.equalsIgnoreCase(~myCookie")) ( out.println( eName + ~: ~ + cookies[i] .getValue(); 11 Dado: 13. public elass ServletX extends HttpServlet ( 14. publie void doGet (HttpServletRequest req, HttpServletResponse resp) 15. throws IOException, ServletException ( 16. HttpSession sess = new HttpSession (req); 17 . sess.setAttribute(~attrl", 18. sess.invalidate(); 19. String s ~ sess.getAttribute(~attrl"); 20. 21. ) Qual é o resultado? (Escolha tudo que se aplica.) ~ A. A compilação falha _ {) ãD 1Jr:a ;,.",t.o.I' : ,,,,,c/)f'reh.. Võcê <IJSlltl"e 11"" O. .B. O valor de s e null "tie.,-/) ~lIe ihlp Ie""e'7ra í"~ . L #-/-+p5eSSi{»IIlSfA'7JIJ , re'!.. fi lXe+5esstIJJ'I( ). De. O valor de s é "value" " OU. Uma IOException é enviada DE. Uma ServletException é enviada DF. Uma IllegalStateException é enviada 280 capitulo 6
  • 309. t USand9 9 JSP Sendo umJSP Um JSP torna-se um servlet. Um servlet que você não cria. O Container olha o seu JSP, o traduz em código-fonte Java e o compila em uma classe servlet de Java completa. Porém, você tem que saber o que acontece quando o código que você escreveu em JSP se transforma em código Java. Você pode escrever códigos Java em JSP, mas será que você deveria? E se você não escrever o código Java, o que você escreverá? Como ele faz a tradução para o código Java? Neste capítulo, veremos seis diferentes tipos de elementos JSP - cada um com seu próprio propósito e, sim, sintaxe única. Você aprenderá como, por que e o que escrever no seu JSP. Talvez o mais importante, você aprenderá o que não escrever no seu JSP. este é um novo ca{.lítu,rO'" 281
  • 310. objetivos do exame oficial da Sun os o Modelo de Tecnologia do JSP Notas sobre a Abrangência: 6.1 Identificar, descrever ou escrever o código A maioria é tratada neste capítulo, mas os JSP para os seguintes elementos: (a) template detalhes que envolvem as (c) ações-padrão e text, (b) elementos de scripting (comentários, customizadas e (d) os elementos da expression diretivas, declarações, scriptlets e language serão abordados nos próximos capítulos. expressões), (c) ações-padrão e customizadas, e (d) elementos da expression language. A diretiva de página será abordada neste 6.2 Escrever o código JSP que usa as capítulo, mas o include e a taglib serão diretivas: (a) page (com os atributos abordados nos próximos capítulos. import, session, contentType e isELIgnored), (b) include, e (c) taglib. Não será abordado aqui; verifique o capítulo sobre Distribuição. 6.3 Escrever um Documento JSP (documento baseado em XML) que usa a sintaxe correta. Tudo abordado neste capítulo. (Dica: estas 6.4 Descrever o propósito e a seqüência de serão algumas das perguntas mais tranqüilas eventos do ciclo de vida de uma página JSP: do exame, uma vez que você aprendeu o básico (1) tradução da página JSP, (2) compilação neste capítulo.) da página JSP, (3) carregar a classe, (4) criar a instância, (5) chamar o método jspInit, (6) Tudo abordado neste capítulo, embora se espera chamar o método jspService, e (7) chamar o que você já saiba o que a maioria deles significa, método jspDestroy. baseado nos dois capítulos anteriores. 6.5 Dado um objetivo de design, escrever o código JSP, usando os objetos implícitos Nós falamos sobre tudo aqui, exceto declarar as apropriados: (a) request, (b) response, (c) bibliotecas de tags, que será visto no capítulo out, (d) session, (e) config, (f) application, Usando a JSTL. (g) page, (h) pageContext, e (i) exception. 6.6 Configurar o deployment descriptor para Não é abrangido aqui; verifique no próximo declarar uma ou mais bibliotecas de tags, capítulo (JSP sem scripts). desativar a linguagem de avaliação e desativar a linguagem de scripting. 6.7 Dado um objetivo de projeto especifico para incluir um segmento JSP em outra página, escrever o código JSP que usa o mecanismo de inclusão mais apropriado (a diretiva include ou a ação-padrão jsp:include). 282 capítulo 7
  • 311. usando o JSP No fitM das comas, o JSP é só UtM servlet 9 seu JSP toma-se um servlet completo rodando em sua aplicação. E muito parecido com qualquer outro servlet, exceto pelo fato de que a classe do servlet é escrita para você - pelo Container. O Container utiliza o que você escreveu no seu JSP, o traduz para um arquivo-fonte da classe servlet (.java) e o compila em uma classe servlet Java. Depois disso, ele será só um servlet e rodará exatamente do mesmo jeito, como se você mesmo tivesse escrito e compilado o código. Ou seja, o Container carrega a classe servlet, instancia-a e inicializa-a, cria uma tbread para cada solicitação e chama o método serviceO do servlet. , carregado é traduzido : ini ciali zado -paro. como com-pila em ~ ~ ~ MyJSP jsp Servlet MyJSP.jsp MyJSPjsp.class •• Algumas das perguntas que responderemos neste capítulo são: ~ Para onde vai cada parte do seu arquivo JSP no código-fonte do servlet? ~ Você tem acesso às características "sem servlet" da sua página JSP? Por exemplo, o JSP tem noção do ServletConfig ou do ServletContext? ~ Quais são os tipos de elementos que você pode inserir em um JSP? ~ Qual é a sintaxe para os diferentes elementos de um JSP? ~ Qual é o ciclo de vida de um JSP? Você pode interferir nele? ~ Como os diferentes elementos de um JSP interagem no servlet final? você está ~ 283
  • 312. fazendo um JSP Criando UtM JSP que exiba quatttas vezes ele foi acessado Pauline quer usar JSPs em suas aplicações - ela está realmente cansada de escrever HTML no seu método printlnO do PrintWriter do seu servlet. Ela decide aprender JSPs, criando uma página dinâmica simples que exibe o número de vezes que ela foi solicitada. Ela sabe que você pode colocar um código Java normal em um JSP usando um scriptlet - que significa simplesmente o código Java dentro de uma tag <% ... %>. Já que eu posso colocar código Java no JSP, vou criar um método estático em uma classe Counter, para manter a variável estática de contagem de BasicCounter.jsp acessos e chamar este método a partir do JSP ... <html> <body> The page count is: <% out.println(Counter.getCount(»; </html> ~~bOdY> ~ 1/ U I I D cltje+6 (jiJ.fes+a ,~/u:r+t'J 1Vi/ce~l'e <% e %> é iJl;i SCl'l,+le+J 3iJe é a,eJ1s's JIJ.IIs' s,~/es. Counter.java package foo; public class Counter ( private static int count; public static synchronized int getCount() count++i return count; Clas se (;.s sis-k?t-k JlJ.1I4 siMples. 284 capítulo 7
  • 313. usando o JSP Ela distribui e testa o JSP Distribuir e testar é trivial. A única parte confusa é garantir que a classe Counter esteja disponível para o JSP. E isso é fácil: basta colocá-Ia no diretório WEB-INF/classes da aplicação. Ela acessa o JSP direto pelo browser: http://localhost:8080/testJSPl/BasicCounter.j sp The page count is: 1 !tdjhqn Jfhq.i F.ijqof BasicCouj'-fér.jsp Kcljhgn 3fhg.i Fijgof weh.'<rnl { Po.l'fJ. flc "-'OlOI Ctl/lJ3ve b ,/il'e-l-/-l'ltJ I ~.,m J (J Couni~~lcla" HTTP Status 500 - The server encountered an internal error o that prevent it from fulfilling this request. II!!J!IIorg.apache.jasper.JasperException: Unable to compile c1ass for JSP pfJ.clJh e" al'3VlV6 .class An errar occurred at line 1 in the jsp file :/Basic Counter.jsp Generated servlei errar: JI1lJ .,fll'e-l-/-I'tô wí$-IIJFI Uavac} Compiling 1 source file IUsers/kathy/App[ications2/jakarta-tomcat-5.019!workfCatalinaJIocalhostltestJSP1/org/apache/jspl clo.sses) e 1Jtltl,!fl/el'pfJ.l'h ~::~~I~U;~~~f~ba~~~:;cannot resolve symbol location: class org.apache.jsp.basicCounterjsp 4,cê C611Se ':5 Vf I '" I " ,/es"F1.I.apltcl.l.fl.l.o sel'lt out.pri~t( Counter.getCountO); eJ1ffJ1Jel' IJ 3(1E' capa; Je ve-!c. 1 error Jev E'I'I'D.,/ó? org.apache.jasper.compiler. DefaultErrorHandler.javacError(DefaultErrorHandler.java: 127) org.apache.jasper.compiler. ErrorDispatcher.javacError(ErrorDispatcher.java:351 ) org.apache.jasper.compiler.generateclass(Compiler.java:415) org.apache.jasper.compiler.Compiler.compile(Compiler.java:458) org.apache.jasper.compiler.Compiler.compile(Compiler.java:439) org.apache.jasper.JspCompilalionContext.compile(JspCompilationContext.java:553) org .apache.jasper.servleUspServletWrapper.service(JspServletWrapper.java:291 ) org .apache.jasper.servleUspServlet.serviceJspFile(JspServlet.java:301 ) org.apache.jasper.servleUspServlet.service(JspServlet.java :248) javax.servlet-http.HttpServlet.service(HttpServle1.java:856) ., você está aqui ••.
  • 314. o atributo imporl da diretiva da página o JSP Kão recoKhece a classe Couttter A classe Counter está no pacote foo, mas não há nada no JSP capaz de reconhecê-Ia. É idêntico ao que acontece com você em qualquer outro código J ava. E você conhece a regra: importe o pacote ou use o nome da classe totalmente qualificado no seu código. Eu acho que você tem que usar o nome da classe totalmente qualificado dentro dos JSPs. Faz sentido, pois Counter.java todos os JSPs foram transformados em código servlet Java simples pelo Container. Mas é claro que eu package foo; gostaria que você pudesse colocar im orts no seu código JSP ... public class Counter ( private static int count; public static int getCount() C> count++; O return count; o código JSP era: <% out.println(Counter.getCount()); %> o código JSP deveria ser: <% out.println(foo.Counter.getCount()); %> Il.~ . fVl'fcitJl'ltU". 1"f3eJl'IJ. V ai 286 ca(,~ítwro 7
  • 315. usando o JSP Mas você PODE incluir declarações import num JSP... basta ter uma diretiva. C> O Use a diretiva de págitla para itMportar pacotes A diretiva é um recurso que você tem para dar instruções especiais ao Container no momento da tradução da página. As diretivas vêm em três sabores: page, include e taglib. Nós veremos as diretivas include e taglib nos próximos capítulos. Por enquanto, nossa preocupação será com a diretiva page, porque ela é a única que nos permite importar. Para importar um único pacote: <%@ page f.s-t-a é vh'la ptl.Je 'import="foo. *" %> '-(---- C"'h'I Vh'I J. J ------y fJ.-rl"tbvró tlrlpl:il"r. <html> <body> (Obsel"ve 3ve #fã", 1.: The page count is: #fel1t.VIt'Ip.m-t-.re-v{,.jVifJ. 11/J <% '/4 tli711.1 di're.f.tV4). out.println(Counter.getCount(») ; %> </body> </html> Os scrlh-t-Ie.f.s r sã", Jtlva l1",rh'lal:S-~l"'j4.) -t-6'/fJ.S as decl41"l~f;e:s e:1t'I VIt'I scriphe-t- devel!l1 -I-erh'lli7ar C<ll1!l1 Vh'I Para importar múltiplos pacotes: p61'1-t-c-e-v:l"jVIQ.! <%@ page import="foo.*,java.util.*" %> 1', ti se VI!l1Q. VlrjvllA parti separlAl" .os pIAC6-1-eS. II:S--t-a1i1-1-etra '/e pll.CfJ-I-es vel!l1fl'1-t-re Reparou a diferença entre o código Java que exibe o contador e a diretiva de página? O código Java vem entre os símbolos <% e %>. Mas a diretiva acrescenta um caractere a mais no começo do elemento - o símbolo @ (arroba)! Se você vir um código JSP que começa com <%@, você já sabe que se trata de uma diretiva. (Nós entraremos em maiores detalhes sobre a diretiva de página mais adiante.) você está ~ 287
  • 316. usando expressões Mas etlt seguida Kitlt tltetlciotla as "expressões~~ Justo quando você pensou que fosse seguro, o Kim percebe o scriptlet com uma declaração out.printlnO. Isto é JSP, pessoal. Grande parte da razão do JSP é evitar o printlnO! É por isso que existe um elemento expressão no JSP - ele exibe automaticamente aquilo que você colocou entre as tags. Você não precisa dizer out. printlnO em um JSP! Basta usar uma expressão ... o código script/et: <%@ page import="foo.*" %> <html> <body> The page count is: <% out.println(Counter.getCount()); %> </body> </html> o código expressão: <%@ page import="foo.*" %> <html> <body> The page count is now: <%= Counter.getCount() %> </body> </html> I"f It expJ"esst'uJ'" e'"ífJi'tds cClJ"-ra J I - I1IJS pJ"edsfJ.ífJi'lJs escJ"eveJ" IJ Notou a diferença entre a tag para o código scriptlet e a tag da expressão? O código scriptlet vem entre os sinais de porcentagem <% e >%. Já as expressões recebem um caractere adicional no início do elemento: um sinal de igual (=). Até agora nós já vimos três tipos diferentes de elementos do JSP: Scriptlet: <% %> Diretiva: <%@ %> Expressão: <%= %> 288 capftuio 7
  • 317. usando oJSP O;;Je es+: ó po;;+ó-e-v!rjVla? J <%= Counter.getCount() %> As expressões se tOl11atM o argUtMettto para UtM out.prittt() Em outras palavras, o Container carrega tudo o que você digita entre <%= e >% e acrescenta como argumento para uma declaração que exibe para a resposta implícita out do PrintWriter. Quando o Container encontra isso: <%~ Counter.getCount() %> Ele o transforma nisso: out.print(Counter.getCount(»); Se você colocou mesmo um ponto-e-vírgula na sua expressão: <%= Counter.getCount(); %> Isso é mau. Significaria isso: out.print(Counter.getCount();) ; , ~ 'x.l!! Is+ó i1Vl1ca NUNCA termine uma expressão com um ponto-e-vírgula! <%= nuncaColoqueUmPontoEVírgulaAqui %> <%= porquelstoÉUmArgumentoParaPrintO %> você está •• 289
  • 318. expressões e diretiva de página N&9 exIstem feth'untas Ídl9tas Diga quais das seguintes expressões são válidas, ou não, e por quê. Nós não abordamos Y: Bem, se você tem que usar as todos os exemplos aqui; portanto, use a sua expressões EM VEZ DE colocar o out.printlnO imaginação, baseado no que você já sabe sobre o em um scriptlet, então por que existe um funcionamento das expressões. "out" implícito? (As respostas estão mais adiante neste capítulo; então, faça o exercício AGORA). I:implícitaprovavelmente sua página JSP, mas out Você de dentro da não usará a variável Válido? (Verifique se é válido ou não, você pode passá-Ia adiante ... alguns outros objetos que são parte da sua aplicação não têm justificando quando não for.) acesso direto ao stream de saída de dados da 0<%= 27%> resposta. f: Em uma expressão, o que acontece se o método não retomar coisa alguma? 0<%= ((Math.randomO + 5)*2); %> I: Você receberá um erro!! Você não pode, 0<%= "27"%> e NÃO DEVE, usar um método com um tipo de retorno void como uma expressão. O Container é esperto o suficiente para descobrir que não haverá nada a exibir se o método tem um tipo 0<%= Math.randomO %> de retorno void! Y: Por que a diretiva import começa com 0<%= String s = "foo" %> a palavra "page"? Por que é <%@ page import %> em vez de simplesmente <%@ import %>? 0<%= new String(3]) %> I: Boa pergunta! Em vez de possuir uma 0<% = 42*20; %> enorme pilha de diretivas, a especificação JSP tem apenas três diretivas, que podem ter atributos. O que você chamava de "a diretiva import" é na verdade "o atributo import da diretiva 0<%= 5>3 %> da página". Y: Quais são os outros atributos para a 0<%= false %> diretiva da página? I: Lembre-se, a diretiva da página é para dar 0<%= new CounterO %> ao Container a informação de que ele precisa quando traduz seu JSP para servle1. Os atributos que nos importam (além do import) são: session, content-Type e isELlgnored (falaremos deles mais adiante neste capítulo). 290 capítulo 7
  • 319. usando o JSP KiiM solta a bOiMba fi"al... C> o Humm... eu sei que o JSP se transforma em um servlet. Então, talvez eu possa declarar uma variável contadora em um scriptlet que transformar-se-ia numa variável no servlet. Será que funcionaria? D O o que ela tentou: <htrnl> <body> <% int count=O; %> The page count is now: <%= ++count %> </body> </htrnl> Isto vai compilar? Vai funcionar? você está ~ 291
  • 320. variáveis scr~[)tíet l1eclarat1do uita variável eit Uit scriptlet A declaração da variável é válida, mas não funcionará conforme Pauline esperava. o que ela tentou: .~ N ~ NtlS I1Q4pt't;ClSQIi4S i'I'y>tlf'T"fi.t' P/4JQ; f.P/T"Q4P/IJ$ ~ I <htrnl> ~.f>tlI41i(J$ fi. Jlt'e-ftv4 tia P~i"'fl,. <body> sct'ifJ,~ <% int count=O; %>~ I The page count is now: lJedl3.t'Q fi. v4F'ttJ.lIef cdP/.fQdót'4 • .----* <%= ++count %> flfpt'es SIM </htrnl> </body> ~ -r I J..p/ct'elie"T"a 4 VfJ.t'ltJ.lle!ctmT"adlJt'13. J ! fi: exl!le ti IIlJ,lóf'. o que ela viu na primeira vez que abriu a página: The page count is: 1 o que ela viu na segunda, na terceira e em todas as outras vezes em que ela abriu a página:
  • 321. usando o JSP o que REALMENfE acomece COtlt o seu código JSP? Você escreve um JSP, mas ele vira um servlet. A única maneira de saber realmente o que está acontecendo é ver o que o Container faz com o seu código JSP. Ou seja, como o Container traduz o seu JSP em servlet? Uma vez que você saiba onde os diferentes elementos do JSP se encontram no arquivo de classe do servlet, você achará muito mais fácil de saber como criar a estrutura do seu JSP. O código do servlet nesta página não é o código verdadeiro gerado pelo Container - nós o simplificamos e aproveitamos o essencial. O arquivo do servlet gerado pelo Container é, digamos, mais feio. O verdadeiro código-fonte do servlet gerado é um pouco mais dificil de ser lido, mas nós o veremos nas próximas páginas. Contudo, por enquanto, o que nos interessa é onde o nosso código JSP realmente termina na classe servlet. Este JSP: Torna-se este servlet: public class basicCounter_jsp extends SomeSpecialHttpServlet { public void jspServlce(HttpServletRequest request, HttpServletResponse response)throws java. io.IOException, ServletException { PrintWriter out = response.getWriter(); response.setContentType("text/html"); <html><body> ~ out.write("<html><body>"); <% int count=O; %>----------~.int count=O; The page count is now :-----~ out. wri te ("The page count is now:"); <%= ++count %>---------------ãpout.print( ++count ); </body></html>-------------~.out.write("</body></html>"); I O CM-/-oJnel' c"IIJCil. /-l:Jtl.a cótl.ij" - lJ e"'" v"'" "",:J..ótl."sel'lIi'ce PePlse PIe/e C<:l""''' v"'" tl.tJbe-/-1 tl.lJ~s-/- ~ve TODOS os códigos do scriptlet e das expressões ficam em um método service. Isto significa que as variáveis declaradas em um scriptlet são sempre variáveis LOCAIS! JlJ 1;"",ca.j.jvocê sVi"sel' checal' ô cttl.fjlJ Jô sel'vle.f. jel'aJô tJ.1'((I'.f.ir AI".f.tJ.:Se V~4 e"",H'JI',:elJ'i"PlJSev1;irlca..f.!WIJl'k! Ca.f.ali'PlfJ.! AliJirlePI!JSevSel'vMtJl' (AJ.'irlebtJ.SvaApli'co.{ió! IJ1'5! 4p4ct.e;Jsp. (Os nlJirles svbl,i,t.IJ.JêJS irlvJI<I''i,,; JepenJenJIJ JIJ sev sts.feirlt.( ti! Jfi. SVfJ.IJ.f1i'clJ.g'i,,) você está aqui.. 293
  • 322. declarações JSP D o PrecisatMos de outro e1etMettto JSP ... Declarar a variável contadora no scriptlet nos mostrou que a variável foi reinicializada cada vez que o método de serviço rodou. Quer dizer que ela foi reiniciada para Oa cada solicitação. De alguma forma, precisamos tomar count uma variável de instância. Até agora, nós vimos as diretivas, os scriptlets e as expressões. As diretivas são para instruções especiais para o Container, os scriptlets são Java simples localizados dentro de um método service do servlet gerado, e o resultado de uma expressão sempre se toma o argumento para um método printO· Mas existe um outro elemento JSP chamado declaração. <%! int j As declarações JSP servem para declarar membros da classe do servlet gerado. Isto significa as variáveis e os métodos! Portanto, tudo que estiver entre a tag <%! e %> é adicionado à classe fora do método service. Logo, você pode declarar os métodos e as variáveis estáticas e de instância. 294 capítulo 7
  • 323. As declarações JSP Vma declaração JSP é sempre definida dentro da classe, mas fora do método service (ou qualquer outro). E simples assim: as declarações servem para as variáveis estáticas e de instância e para os métodos. (Na teoria, sim, você poderia definir outros membros, incluindo as classes internas, mas em 99,9999% das vezes você utilizará as declarações para os métodos e as variáveis.) O código abaixo resolve o problema de Pauline; agora, o contador é incrementado cada vez que um cliente solicitar a página. A Declaração da Variável Este JSP: Torna-se este servtet: public class basicCounter jsp extends HttpServlet { public void jspService(HttpServletRequest Gintrequest, count=O; HttpServletResponse <html><body> <%! int count=O; %> J response)throws java.io.IOException PrintWriter { out = response.getWriter(); response.setContentType(~text/html"); The page count is now: out.write(~<html><body>"); <%= ++count %> out.write(~The page count is now:"); </body></html> out.print( out.write("</body></html>"); ++count ); ~ .~ ' 1Jfs-+-a VfjJ fs-+-all'liJS- tl'Jcl"fll'le"';-tl.I'JJ" lIlI'l~ Je li1s-+-';"ci'a E ell'l vej Je lIlI'lfll vai"lfJ.Velltlcal, A Declaração do Método Este JSP: Torna-se este servtet: public class basicCounter jsp extends HttpServlet { -nt doubleCount() { count = count*2; <html> <body> return count; alie } <%! int doubleCount() { count = count*2; int count~l;~ return count; é Is-l-e ~ Java.; eP'l.fió) selll fl'ób1ellltJ.S 3vu'I'J-I- N •• referel1cfu,s de f ••/'ward (ofedlu'fJ.JlJ.tJ .lu, %> <%! int count=l; %> !JíPOI:5 Sue l/ecê U, u-/-NtYJiE e'1II VIII hlé-l-fJdc), The page count is now: public void ]spService(HttpServletRequest request, <%= doubleCount() %> HttpServletResponse response)throws java. </body> io.IOException { </html> PrintWriter out ~ response.getWriter(); response.setContentType(~text/html"); out.write("<html><body>"); out.write("The page count is now:"); out.print( doubleCount() ); out.write("</body></html>"); você está
  • 324. o servlet gerado Hora de ver o VERUAUEIRO servlet gerado Estávamos vendo uma versão bem simplificada do servlet que o Container realmente cria a partir do seu JSP. Não há necessidade de se ver o código gerado pelo Container durante o desenvolvimento, mas você pode usá-Io para ajudá-Io a aprender. Uma vez que você veja o que o Container faz com os diferentes elementos de um JSP, você não precisará mais ver os arquivos-fonte .java gerados pelo Container. Alguns fabricantes não deixarão que você veja a fonte Java gerada, mantendo apenas os arquivos .class compilados. Não se intimide quando você notar partes da API que você não conheça. Os tipos de classe e interface são, na maioria, implementações específicas do fabricante que você não deve se preocupar. o que o Container faz com o seu JSP ~ Olha as diretivas, em busca de informações de que ele possa necessitar durante a tradução. ~ Cria uma subclasse HttpServlet. Para o Tomcat 5, o servlet gerado estende: org.apache.jasper.runtime.HttpJspBase Nós estam os mostrando o código ~ Se houver uma diretiva de página com um atributo gerado de forma que você possa import, ele escreve as instruções do import no topo do entender como o JSP é traduzido arquivo classe, logo abaixo da declaração do pacote. para o código servlet. Mas você Para o Tomcat 5, a declaração do pacote (com a qual não precisa saber em detalhes como você não deve se preocupar) é: um determinado fabricante faz isso package org.apache.jsp; e nem a aparência verdadeira do código gerado. Tudo o que você ~ Se houver declarações, ele escreve-as no arquivo classe, precisa saber é como se comporta geralmente logo abaixo da declaração da classe e antes • cada tipo de elemento (scriptlet, do método service. O Tomcat 5 por si só declara uma diretiva, declaração, etc.) e como variável estática e um método de instância. aquele elemento funciona dentro do servlet gerado. Você precisa saber, ~ Cria o método service. O nome real do método : por exemplo, que seu scriptlet pode é _j spService (). Ele é chamado pelo método usar objetos implícitos, e você precisa ativado serviceO da superclasse do servlet e recebe o conhecer os tipos de objetos implícitos HttpServletRequest e o HttpServletResponse. Como daAPI Servlet. Mas você NÃO parte da construção desse método, o Container declara precisa conhecer o código usado para e inicializa todos os objetos implícitos. (Você verá mais objetos implícitos quando mudar de página.) disponibilizar tais objetos. A única coisa que você precisa saber ~ Mistura o HTML simples (chamado template text) com os: sobre o código gerado são os três scriptlets e as expressões no método service, formatando: métodos do ciclo de vida do JSP: jsplnitO, tudo e escrevendo no PrintWriter da resposta. : jspDestroy e -.JspServiceO. (Falaremos . ~ sobre eles ainda neste capítulo.) . ........................................... 296 capítulo 7
  • 325. usando o JSP A classe gerada pelo Tomcat 5 <html><body> package . org.apache.]sp; Se você -hvel' /T "'~I'·h ,.••• tio. <%! int count=O; %> import javax. servlet. *; tiil'e-hv!l:!e pD.Jíi"""J,eles". The page count is now: import javax. servleLhttp. *; ~~l!1.l'eCer46 4'1pt(,,6S "46, +e_s <%== ++count %> import javax. servlet. jsp. *; "JI!11t.VIYo, Iw.p~r+ J'II!S+ei.JSP>. </body></html> public final class BasicCounter_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent int count=O; private static java.util.Vector jspx~dependants; O Ca"+IlIPier ca!t:,c4 4S suAs public java. util. List getDependants return jspx_dependants; () {tie;,+r6 I" tias +4itS <%/ %» N PI'<JPf't4S d4tXtJ tia tieclaf'IJJaa public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException JspFactory jspxFactory = null; PageContext pageContext ~ null; HttpSession session = null; ServletContext application ~ null; ServletConfig config = null; JspWriter out = null; Object page = this; JspWriter jspx_out = null; PageContext jspx_page context null; try { jspxFactory = JspFactory.getDefaultFactory(); response.setContentl'ype("text/html"); pageContext = jspxFactory.getPageContext(this, request, response, null, true. 8192, true); jspx pagecontext = pageContext; ;;-ppli~atio:;;: pageContext. getServletContext = (); A»11t ele +e~4 inicia!i;").;' as config = pageContext. getServletConfig (); a~e+"s 11ty>11!:t+as. session = pageContext.getSession(); out = pageContext.getOut(); jspx_out ~ out; out.write("r<html>r<body>r"); out.write("rThe page count is now: r"); out.print( ++count ); out.write("r</body>r</html>r"); catch (Throwable t) { if (! (t instanceof SkipPageException){ out = jspx_out; I if (out != null && ouLgetBufferSize() != O) !clar"zveatsóp"tietio.rerf'flltió ••• out.clearBuffer(); if ( ]spx_page context 1= null) jspx_page contexto handlePageException(t); } } finally { if ( jspxFactory != null) jspxFactory.releasePageContext( ]spx_page~ context); } você está
  • 326. objetos implícitos do JSP A variável out não é o único objeto itMplícito ... Quando o ContaÍner transforma o JSP em um servlet, o começo do método service é uma pilha de declarações de objetos implícitos e atribuições. Com os objetos implícitos, você pode escrever um JSP, sabendo que o seu código fará parte de um servlet. Em outras palavras, você pode aproveitar as suas características de servlet, mesmo que você não esteja escrevendo diretamente uma classe servlet. Lembre-se dos capítulos 4,5 e 6. Quais foram alguns dos objetos importantes que você usou? Como o seu servlet conseguiu seus parâmetros init? Como o seu servlet obteve a sessão? Como ele conseguiu os parâmetros enviados pelo cliente em um formulário? Estas são algumas das razões que seu JSP pode precisar para usar alguns dos recursos disponíveis para o servlet. Todos os objetos implícitos apontam para algum item daAPI Servlet/JSP. O objeto implícito request, por exemplo, é uma referência ao objeto HttpServletRequest, passado para o método service pelo ContaÍner. AP. JspWriter HttpServletRequest HttpServletResponse HttpSession session ServletContext application '" é 'l.s+e óbid-ó 'hy>I:Cl+ó disp~JI1:vel ~f.ep!~s/ .•.. ServletConfig config p41'a pI.!Jll'l4Sde f!1'1'6detll'litl4s. ~ce Vel'4 JspException exception ~ lSSIJ 1Pl41$ al'de) + PageContext Object page pageContext ~ " IJIPl~l.!JeCó~x+ eJOlc4pslI!o. CII+1'6$ atJe+cs 1hy>I,cttas. A-ssi~ se vóce pll,SSQI' IIIPlIl, l'elel'e'1C1~ Pl.!JeCc~x+ o. 'f,5l/1Pl tJe+4 t.elpel'j 4 ele ptAdf.NI l/S41' es so. I'e-lel'el'lct~ p~l'o. tJb+e,. I'elel'ê-,cl~s pU·o. ()trrJetJS ctJe+cs t""Pl:Cl+tJSe a+dIJII+ó$ de +ad4s tASescapas. r: Qual é a diferença entre um JspWriter e um PrintWriter que eu recebo de um HttpServletResponse? R: Não muita. O JspWriter É UM PrintWriter com algumas funções de buffer. O único momento em que você deve realmente dar maior atenção a ele é quando você estiver criando tags customizadas. Portanto, falaremos um pouco a respeito das habilidades especiais do JspWriter no capítulo que aborda o desenvolvimento das tags customizadas. I 298 capítulo 7
  • 327. Exetcíc'l9S Cada um d9Sttecb9s vem de umJSY. Seu ttabalb9 setá desc9btlt 9 '1ue aC9nteootá '1uand9 9 C9Iltalnet tentar ttanst9tmat 9 J S Y num setVlet. O C9ntalnet setá cap~ dettaduz,'lt 9 seulSY em um c9d'lg9 setvlet legítlm9 e c9mp'llável? Se nã9, p9t '1ue? Em CClS9 t'ltmatlv9, 9 a '1ue aC9nteoo '1uand9 um cl'lente aoossat 9 JSY? o <htrnl><body> Test scriptlets ... <% int y=5+x; %> <% int x=2; %> </body></htrnl> <%@ page irnport="java.util.*" %> <htrnl><body> Test scriptlets ... <% ArrayList list = new ArrayList( list.add(new String(ftfoo")); %> <%= list.get(O) %> </body></htrnl> e <htrnl><body> Test scriptlets ... <%! int x ~ 42; %> <% int x = 22; %> <%= x %> </body></htrnl> você está
  • 328. exercícíos JSP ~ Imã de Gehtde'h'q ([este Ytepéttflt9tl9) Estude o cenário (e o restante nesta página) e coloque os ímãs no JSP para criar um arquivo legítimo que produziria o resultado correto. Você não deve usar um ímã mais de uma vez e nem usará todos eles. Este exercício supõe que existe um servlet (que você não precisa ver) que recebe a solicitação inicial, associa um atributo no escopo da solicitação e encaminha para o JSP que você está criando. (Nota: nós chamamos este exercício de "Ímã de Geladeira (Teste Preparatório)" em vez de "Ímã de Geladeira", pois a prova está repleta de perguntas "arrastar e soltar" como esta). Objetivo do Projeto Criar um JSP que produzirá isto: !The friends who share your hobby of extreme knitting are: IFred lPhilippe I Ui I O texto "extreme knitting" vem de um parâmetro do formulário de solicitação. ! seu JSP. O servlet obtera a sohcltaçao ! primeiro (e então a encaminhará ao JSP), . l.pradeep ~ . mas precisa receber es~e par~~etr~ do ;•.Vocêisto não muda a forma como você Os três nomes vêm de uma ArrayList de receberá o parâmetro no seu JSP. atributos da solicitação, chamados "names". Você terá que receber o atributo do objeto solicitação. Considere que o servlet recebeu esta solicitação e configurou um atributo no escopo da mesma. Zsra J a vle.f- 311e eCll'ltij(,ll'4 "e •.• 6 a.f-I'l!II./7<; $<;ll"el-+8.J';6 Conselhos e dicas importantes O formulário HTML e tÁeplJls ePlcelíI'Ililho. ~ O atributo da solicitação é do tipo java. <form method~"POST" JSP 311e V••ee es.f-: util.ArrayList. <html><body> ç.. « $<;líCl.f-a{õ.a farei 6 eSCl'evel'/tÁ6. action~"HobbyPage.do"> Choose a hobby:<p> ~ A variável implícita para o objeto HttpServletRequest é chamada de <select name=NhobbyJ'.f size="1"> request e você pode usá-Ia em scriptlets <option>horse skiing ou expressões, mas não em diretivas <option>extreme knitting ou declarações. Independentemente <option>alpine scuba do que você fizer com um objeto <option>speed dating </select> solicitação em um servlet, você o fará <br><br> dentro do seu JSP. <center> <input type="SUBMIT"> ~ O método servlet do JSP pode processar </center> os parâmetros request, pois lembre-se, </form> </body></html> seu código vai estar dentro do método service do servlet. Você não precisa se preocupar com o método HTTP(GET ou POST) que foi usado na solicitação. 300 7
  • 329. usando o JSP Nós colocamos algumas linhas para você. O código que você colocar neste JSP DEVE funcionar com o código que já está aqui. Quando você tiver terminado, ele deve ser compilável e produzir o resultado na página anterior (você deve CONSIDERAR que já exista um servlet funcionando, que primeiro recebe a solicitação, configura o atributo "names" da PARE solicitação e encaminha a solicitação para esse JSP). . exercCO ~O e u'" Este ~pCona.~ sobre a o rçao É parte da JSP Sntaxe do The fríends who share your hobby of are: <br> <% Iterator ít alo íterator (); você está ~ 301
  • 330. respostas dos exercícios SEJA 9 C9ntUnet Iesp9sta5 O nQ 2 é fácil de entender e funciona. O nQ 1 é uma questão básica da linguagem Java (usar uma variável local antes que ela seja declarada) e o nQ 3 também demonstra uma questão básica da linguagem Java - aquilo que acontece quando você tem uma variável local e de instância com o mesmo nome. Então veja ... se você traduzir o código JSP no código Java do servlet, você não terá problemas em descobrir o resultado. Uma vez que o conteúdo do seu JSP estiver dentro do servlet, isso é Java. / ís+e J'jãó ir: í CÓJJy>lftU"/ exahl>le~ C<ll>l,{l escrever o <htrnl><body> Test scriptlets ... <% int y=5+x; %> V/tl /tlé+ódl.l ca/tl; ,~ lf9c~es+: +e,,+aPld<l vsar a vt<r,-tvel <% int X=2i %> xJ x A-Alrf.,5 Zll'i! ela s!:ia Jef;#jiGla. A- </body></htrnl> lii15vt<5el>lJt<Vll "lã", perl>l,"-k iSslJ e IJ c.cl1+IJ.,#jer "Iãc se ,i1C,{l/tlcdfJ. /tl N!liif'rlll>lfl.r e a <lr",!!1>I "ti sev C:diJ6 scrij>+le+. <%@ page import="java.util.*" %> <htrnl><body> scriptlets ... foo Test scriptlets ... <% ArrayList list = new ArrayList(); -;el>l pr<l!;le/tlt<s; exl!;e ., pf'l"'elf'õ (e list.add(new String(~foo")); 1I1'J1Có) ~e+-ó ó da /}N,L.lS.f. %> <%= list.get(O) %> </body></htrnl> e 302 capítuio 7
  • 331. usando o JSP ~ Se a sua resposta parecer um pouco Imã de &lade'ita diferente e você ainda acreditar que ela deve funcionar - tente! Você terá que Resp9staB fazer o servlet que carrega o formulário de solicitação configurar um atributo e encaminhar (despachar) a solicitação para o JSP. B8 ímport="java.util.*"~1i:J AJ:s fl"eci'sahics da dll"e.f.lV4 de f:.slP;a i'IIV>ÓI"Ij d4 I./-el"a..f<IfJI". j <html><body> r p41" C4t1SadalJrl"l",Lts..f e The friends who share your hobby of 1<%= 1 request.' getParameter ("hobby"l ~ I are: <br> EJIArraYLíst~~ [:] I(ArraYLístlUrequest·1 IgetAttríbute("names"ll O~ <% Iterator it = aI. ~terator (); ~ ______ -r .. . I"e-r 4~tll • .L,.p;ICre C SCI"IP"'-' I ••• IWhilell(ít.hasNext(»lE3~ ,<%= 11 í t. next () l a~ e {j fiYtalt;e o.ôtlt• Use tlhi4 eXfl"ess';e. <br> <% } %> l.p;cel"l"e c blccc de Icep w"'l!e! (Se vccê eS3t1ecel" i's.f.c) ele P;';c c<:JlIV>t/al":) ímport ("names") você está
  • 332. expressões válidas a inválidas u~co~etttário... Sim, você pode colocar comentários no A.P9nte seu lápIS Respostas seu JSP. Se você é um programador Java com alguma experiência em HTML, você As Expressões Válidas e Inválidas pegar-se-á digitando: Válidas? // isso é um comentário lZ <%=; 27 %> sem pensar duas vezes. Mas se você o fizer, 1;das as Ir.ferats f'I',,,,rftvas valeli<l, a não ser que esteja dentro de um scriptlet ou em uma tag de declaração, você acabará EXIBINDO isso para o cliente como parte o <%=; ((Math.randomO + 5)*2); %> da resposta. Portanto, para o Container AJfi() / () p~;;f<l-e-V(l'j(/lt< 1'/';<1 ptlde es+al' 11$11", aquelas duas barras são simplesmente mais texto, como "Olá" ou •• E-mail é:". lZ <%=; "27" %> Você pode colocar dois tipos diferentes de comentários em um JSP: /1r S+I't'í'l5 1".feNJ.I é 1I~!tfia, lZ <%=; Math.randomO %> ~ <!-- comentário HTML --> Si"'; D li<lé-l-6dD 1'e+61'11t1. Uli<lo. c:1' •• .. o O Container passa isso diretamente para o cliente e o browser o interpreta o <~=; String s =;"foo" %> como um comentário. AJf.}O/ ~cê 1'/41) ade .fel' """li declaras';" p de vadfJ.llel "3"'''' ~ <%-- comentário JSP --%> lZ <%=; new String[3] ) %> ,. Estes são para os desenvolvedores de S'''''J.pDI' t:lIJ I'f: Je. <I0,1'1"" I'/ew S+r''í'l5 e VIi<l atJe+ó e ~tJe+" p~de seI' e"llll"tldD p{(l'a y""a páginas e, tal qual com os comentários decftu'o.S';" prtn+ll1Ú. Java em um arquivo-fonte Java, eles 0<% =; 42*20· %> são tirados da página traduzi da. Se você estiver digitando um JSP e quiser AJfi()/ f.} al',~""é-hcfJ. es+: bt>fJ.Ji<las J.: tlli<l I adicionar comentários da maneira esptJ.fD e'1+l'e õ % fi: " "', AJ';c f<lde seI' <% "') como você os usaria em um arquivo- .fe"" 3t1e seI' <%=. fonte Java, use um comentário JSP. lZ <%=; 5 > 3 %> Se você quiser que os comentários CItJ.I''') p<ll' seI' YIi<l btMllo'l'/D) extile +rve. façam parte da resposta HTML que vai para o cliente (embora o browser lZ <%=; false %> não os mostrará ao cliente), use um comentário HTML. ~ AJ:sJ: ,. dtsseli<les 3"'e o,s Il.fel'fl.f"$ pr,,,,t+rllt<s St<Dvalfila$'. lZ <%=; new CounterO %> Seli<lpr<l/!Ie •••a. Is+e é IU(tJ.+a•••el'l.fe S+I'I'í'I ••• Ir~ ext/! •• e N!sv!+o.d6 I' de +6S d<l otJe+"" 304 C8j'Jít1Jlo 7
  • 333. usando o JSP A API para o servlet gerado o Container gera uma classe a partir do seu JSP, que implementa a interface HttpJspPage. Esta é a única parte daAPI do servlet gerado que você precisa saber. Não se incomode se no Tomcat, por exemplo, a sua classe gerada estenda: org.apache.jasper.runtime.HttpJspBase Tudo o que você precisa saber são os três métodos <<interface> > pnnCIpaIS: javax.servlet.jsp.JspPage jsplntQ jspDestroyQ ~ jspInitO Este método é chamado pelo método irritO. Você pode anular este método. (Você consegue imaginar como?) <<interface> > javax.servlet.jsp.HttpJspPage ~ jspDestroyO -.JspService(HttpServletRequest, HttpServlet "" Este método é chamado pelo método destroyO do servlet. Você também pode anular este método. 4cê MfJrO POJ)í Q#'}lIl,u" es+ef ~ -ispServiceO Este método é chamado pelo método serviceO do servlet, o que significa que ele roda em uma thread separada para cada solicitação. O Container passa para este método os objetos Solicitação e Resposta. Você pode anular este método! Você não pode fazer NADA por sua própria conta neste método (exceto escrever o código que vai dentro dele), e é responsabilidade do fabricante do Container aceitar seu código JSP e adaptar o método jspServiceO que irá utilizá-Ia. Observe o underscore no início do método - jspService() Ele NÃO aparece no início dos outros dois métodos jsplnitQ ejspDestroy(). Faça ~e d conta q~e o underscore no início do meto o significa "não toque" ! .,. Portanto, nenhum underscore no m!ClOdOas nome significa que você pode a~~l~-lo. M; ão se EXISTIR um underscore no ZnlClO voce n DEVE tentar anulá-Io! você !I> 305
  • 334. ciclo da vida JSP o ciclo de vida de UtM JSP Você escreve o arquivo .jsp. O Container escreve o arquivo .java para o servlet no qual o seu JSP se transformou. o Kim escreve um arquivo .jsp e o distribui como o Container "lê" o web.xml (DD) para esta aplicação, mas não faz mais nada parte de uma aplicação. com o arquivo .jsp (até que ele seja solicitado pela primeira vez). e I;. I L I 1_' l.S-rtl.JlIs-rall1f!"IT"f: (CCllli;ill"C "lQ sel'vMQI' ••• eSf>/tNJ."Itl.ópeta salici1-agãl:J dre"lh. web.xml Web Container o cliente c1icaem um o Container tenta TRADUZIR o " link que solicita o .jsp. .jsp em código-fonte .java para uma classe servlet. ...-- traduz ~ "",- gera MyJSP.jsp MyJSP jsp.java Web Container e o Container tenta COMPILAR o código- fonte .java do servlet em um arquivo .c1ass. __ compila ~ ___ gera~ MyJSP jsp.class MyJSP jsp.java Web Container 306 7
  • 335. usando o JSP o ciclo de vida do JSP com1ttua... o o Container CARREGA a classe do serv/et gerada recentemente. carrega MyJSP .Jsp.class Web Container o Container insta o servlet e faz com o objeto agora é um servlet que o método jsplnitO dele rode. completo, pronto para aceitar as solicitações do cliente . . ..--- jspInitO ~ ..../torna-se~ MyJSP -Jsp MyJSP -Jsp Web Container o Container cria uma nova thread para tratar a solicitação deste cliente, e o método -JspServiceO do serv/et roda. Tudo o que acontece depois disso é simplesmente a rotina normal do servlet para tratamento de solicitações. Por fim, o servlet envia uma resposta de volta para Web Container o cliente (ou encaminha a solicitação para outro componente da aplicação). você está aqui'" 307
  • 336. tradução e compilação A tradução e a cotMpilação acomecetM UMA út1ica vez Quando você distribui uma aplicação com um JSP, toda a etapa de tradução e compilação acontece uma única vez na vida do JSP. Uma vez que esteja traduzido e compilado, ele fica exatamente como qualquer outro servlet. E como qualquer outro servlet, uma vez que tenha sido carregado e inicializado, a única coisa que acontece na hora da solicitação é a criação ou a alocação de uma thread para o método service. Portanto, a figura mostrada na página anterior e nesta é apenas para a primeira solicitação. r: Tudo bem, quer dizer que somente o primeiro cliente a solicitar o JSP é que leva a pancada. Mas DEVE haver uma maneira de configurar o servidor para pré-traduzir e compilar ... certo? I: Embora apenas o primeiro cliente tenha que esperar, a maioria dos fabricantes de Container OFERECE uma forma de fazer toda a tarefa de tradução e compilação acontecer antecipadamente, de forma que até mesmo a primeira solicitação aconteça como em qualquer outra solicitação do servlet. Mas cuidado, isso depende do fabricante e não é garantido. EXISTE uma menção na especificação JSP (JSP 11.4.2) que sugere um protocolo para a pré-compilação do JSP. Você faz a solicitação para o JSP anexando uma query string "?jsp_ precompile" e o Container pode (caso queira) fazer a tradução/compilação ali mesmo, em vez de esperar pela primeira solicitação real do cliente. 308 capítulo 7
  • 337. usando o JSP Se o JSP se transforma em um servlet, eu gostaria de saber se posso configurar os parâmetros init do servlet ... e já que estou aqui, será que posso anular o método initO do servlet ... Observe estas perguntas. Dê uma olhada nas páginas anteriores (e capítulos), caso ache necessário, mas não continue antes de terminar. Sim, você PODE obter os parâmetros init do servlet através de um JSP, então, as questões são: 1) Como você os restaurou de seu código? (Grande, imensa, embaraçosa dica: muito parecido com a maneira que você o restaura em um servlet "comum". De qual objeto você normalmente obtém os parâmetros init do servlet? Ele está disponível para o seu código JSP?) 2) Como e onde você configura os parâmetros init do servlet? 3) Suponha que você queira mesmo anular o método initO ... como você o faria? Há alguma outra maneira de se fazer e que traga o mesmo resultado? você está •.• 309
  • 338. uítrapassando jsplnít( ) lt1icializat1do seu JSP Você pode fazer tarefas relacionadas à inicialização do servlet com seu JSP, mas é um pouco diferente do que você faz num servlet comum. Configurando os parâmetros init do servlet Você configura os parâmetros init do servlet para o seu JSP, quase da mesma maneira que você os configura para um servlet normal. A única diferença é que você tem que acrescentar um elemento <jsp-file> na tag <servlet>. <web-app ... > <servlet> ísrll. J e / 1./ L me li !.II'/tc(;. , lI.~Vli!li!Jf'rli!rli!J'I7""fI:V*' / II"1'1 •• .J <servlet-name>MyTestlni t</ servlet-name> servle} c,,*,v*,. Pij basictl*,tl1h: tlfl'?pe <j sp-file> /Testlni t. j sp</ j sp-file> ~ <init-param> -I-vJ" Jes-l-t< -I-fAJ ,a;,"I'IQJSp' "" servli-/- crraJó '(;1' es+a <:;el'vle-l-> •• <param-name>email</param-name> <param-value>ikickedbutt@wickedlysmart.com</param-value> </init-param> </servlet> <servlet-mapping> t,(lIi:1'7Jti lI"cê JIi!/I"I'Ie*' servle-l- ,b.rt;. v <servlet-name>MyTestlni t</ servlet-name> ~ li*' JSP v"cê Jelle '5l.1a/*,li!l1hJe{tp/i'r <url-pattern>/Testlnit.jsp</url-pattern> </ servlet -mapping> v*' sel'v .l/e-!- Jti " I. JeJSP *,1I.f'el1,i1 i:I f'a;'p/11, </web-app> Anulando o jsplnit() É simples assim. Se você implementar um método jsplnitO, o Container o chama no começo da vida desta página como um servlet. Ele é chamado pelo método initO do servlet, portanto, na hora em que este método roda, haverá um ServletConfig e um ServletContext disponíveis para o servlet. Isto significa que você pode chamar o getServletConfigO e o getServletContextO de dentro do jspInitO. Este exemplo usa o jspInitO para recuperar um parâmetro init do servlet (configurado no DD) e usa este valor para configurar um atributo de escopo application. < %! <: lI*,1:I public void j splnit () ServletConfig sConfig getServletConfig(); r ~cê es-l-: "li*' servle-l-; f',,/'hi1-1-j f'tiJe chl1,*,i:I/' sev je-!-Serv/e+e.til'/fijO I.e/'Jo.J". String emailAddr = sConfig.getlnitParameter("email");~ ServletContext ctx ~ getServletContext(); f ) " ctx. setAttribute ("mail", ~ emailAddr); r) Cói1sl!jve V*,11, _, ''} ."~ se'VlH- ~_I. Is-l-ti é 'i.'x.A'rA'JtA.íAlrí ó 3Vl! I'efel'el'/c,"a '111'(;' " S/i!l"v/e+e.tii1hx-l- '! CÓ"lfijVI"RIIhI 4-1-l'ibv+e Je escópó tlfplicR+lim. 310 capítulo 7
  • 339. usando o JSP Os atributos etM UtM JSP o exemplo da página anterior mostra o JSP configurando um atributo application, usando uma declaração que anule o jspInitO. Porém, na maioria das vezes você usará um dos quatro objetos implícitos para receber e configurar os atributos correspondentes aos quatro escopos disponíveis no JSP. Sim, quatro. Lembre-se, além dos escopos-padrão do servlet - request, session e application (contexto), o JSP acrescenta um quarto escopo - o escopo page -, que você obtém de um objeto pageContext. Geralmente, você não precisará (e nem se preocupar) do escopo page, a menos que você esteja desenvolvendo tags custornízadas. Por isso, não entraremos em maiores detalhes, até o capítulo que trata das tags custornízadas. Em um servlet Em umJSP (usando objetos implícitos) Application getServletContext().setAtlribute("foo", barObj); application.setAtlribute("foo", barObj); Request request.setAtlribute("foo", barObj); request.setAtlribute("foo", barObj); Session request.getSession().setAtlribute("foo", barObj); session.setAtlribute("foo", barObj); Page Não se aplica! pageContext.setAtlribute("foo", barObj); Mas não é só isso! Em um JSP, existe uma outra maneira de receber e configurar os atributos em qualquer escopo, usando apenas o objeto implícito pageContext. Continue e descubra como ... "context" .. mesmo que .os 0 Não existe um escopo lication estejam assocIados atributos no escopo Wllal!Pl2o'==--- ao ob·]eto ServletContext. , 10 a pensar que os _ enclatura pode leva- _ d copo context. A convençao de nom S rvletContext sao... o:~ t" atributos armazenados no e do você encontrar Contex , Não existe isso. Lern:br~:s~ q~an existe uma diferença entre os pense em "appliC~~°::Sado~;e:;~ obter os atributos do escopo nomes servlet e], , diz' . . . um servlet, voce· ,,") apphcatlOn. n ) tAttribute ( foo tservletcontext( .ge ge SP você diz: mas em um], . t ("foo") application.getAttrlbu e você está ~ 311
  • 340. pageContext e atributos Usando o PageCotttext para atributos Você pode usar uma referência PageContext para obter atributos a partir de qualquer escopo, inclusive o escopo page para atributos associados ao PageContext. Os métodos que funcionam com os outros escopos usam um argumento int para indicar o escopo. Embora os métodos de acesso derivem do JspContext, você encontrará as constantes para os escopos na classe PageContext. JspContext getAttribute(nome da String) getAttribute(nome da String, escopo int) getAttributeNamesInScope (escopo int) findAttribute(nome da String) lJ'IéfctiC$ ave IV'7CicPlfJ.IJ'If'fJ.I'fJ. ~II A-L.~fJ!/t. 11 mais métodos 11 inclusive, métodos similares 11 para armazenar e remover atributos de 11 qualquer escopo PageContext APPLICATION SCOPE PAGE SCOPE REQUEST _SCOPE ca""ft;S SESSION SCOPE e$+~+lc"S Ilnats l/mais campos getRequestO , getServletConfigO 1M,&"d6S para getServletContextO ct."seSulr ?Jutl.l»ver getSessionO 6h't!!+•.•i""flct+6 1/ mais métodos ~ 312 7
  • 341. usando o JSP ExeiMplosusat1do o pageCotttext para obter o pageContext . e cot1figurar atributos getAttribute(stnng) serve para o escopo ~ Configurando um atributo do escopo page <% Float one = new Float(42.5); %> . DOIS métodos getAttributeO <% pageContext.setAttribute("foo", one); %> EXistem A pode chamar muito usados que voce . t· m de um so no pageContex . u d dois to IString) e outro e argumen ' . ) argumentos (String e mt. todos os O prunelro fiunc I'ona como . . . dos Obtendo um atributo do escopo page ara atributos aSSOCia <%~ pageContext.getAttribute("foo") %> outros - P C text O segundo, AO objeto page onado p'ara obter . pode ser us porem, atributos de QUALQUER um dos Usando o eC:Ofl'h;~xt para configurar um quatro escopos. atributo do escopo session <% Float two = new Float(22.4); %> <% pageContext.setAttribute("foo", two, PageContext.SESSION_SCOPE); %> Usando o pageContext para obter um atributo do escopo session <%= pageContext.getAttribute("foo", PageContext.SESSION_SCOPE) %> (Que é idêntico a: <%= session.getAttribute("foo") %» Usando o pageContext para obter um atributo do escopo application Email is: <%~ pageContext.getAttribute("mail", PageContext.APPLlCATION_SCOPE) %> Dentro de um JSP, o código acima é idêntico a: Email is: <%~ application.getAttribute("mail") %> Usando o pageContext para encontrar um atributo quando você não conhece o escopo .. <%~ pageContext.findAttrlbute("foo") %> enC<lnrI'I'~-I<l<lI'I~e? Onde o método findAttributeO olha? Ele olha primeiro no page context, e se houver um atributo "foo" com o escopo page context, então, chamar ofindAttribute(nome da String) num PageContext funcionará exatamente como chamar o getAttribute(nome da String) num PageContext. Mas se não existir nenhum atributo "foo", o método começa procurando em outros escopos, do mais restrito ao menos restrito ~ ou seja, primeiro o escopo request, depois o session e, finalmente, o application. O primeiro que ele encontrar com este nome ganha. você está [!> 313
  • 342. diretriz three Já que estatltOS falatldo sobre isso ... vatltos falar tltais sobre as três diretivas Nós já vimos as diretivas usadas para inserir as declarações import na classe do servlet gerado pelo seu JSP. Foi a diretiva page (um dos três tipos de diretivas) com um atributo import (um dos 13 atributos da diretiva page). Nós agora daremos uma rápida olhada nas outras, embora algumas não sejam abordadas em detalhes até os próximos capítulos. Outras, inclusive, nem serão muito faladas aqui, pois são raramente usadas. o A diretiva paga <%@ page import=lIfoo.*" session="false" %> Define propriedades específicas da página, como códigos de caracteres, o tipo de conteúdo para a resposta e se esta página deveria possuir o objeto implícito session. Uma diretiva page pode utilizar até 13 atributos diferentes (como o atributo import), embora apenas quatro sejam cobrados no exame. 8 A diretiva taglib <%@ taglib tagdir~"/WEB-INF/tags/cool" prefix~"cool" %> Define as bibliotecas de tags disponíveis para o JSP. Nós ainda não falamos sobre o uso das tags customizadas e ações padronizadas; portanto, talvez não faça sentido neste momento. Fique com isto por enquanto ... teremos dois capítulos inteiros sobre bibliotecas de tags vindo em breve. e Adiretiva <%@ include file="wickedHeader.html" %> Define os textos e os códigos que são acrescentados na página atual no momento da tradução. Isto lhe permite construir pedaços reutilizáveis (como um título-padrão para a página ou a barra de navegação), que podem ser acrescentados a cada página, sem precisar repetir todo aquele código em cada JSP. r: Estou confuso ... o título deste tópico diz: "Já que estam os falando sobre isso ...", mas eu não vejo o que as diretivas têm a ver com pageContext e atributos. 1: Nada a ver, realmente. Nós só dissemos aquilo para disfarçar a transição inexistente e patética entre dois tópicos não relacionados. Esperávamos que ninguém notasse, mas NÃO ... você simplesmente não permitiria, não é mesmo? 314 capitulo 7
  • 343. usando o JSP Os atributos para a diretiva page Dos 13 atributos da diretiva page da especificação JSP 2.0, apenas quatro são cobrados no exame. Você NÃO precisa memorizar a lista inteira, mas veja o que você pode fazer. (Veremos os atributos isELIgnored e os dois atributos relacionados a erros mais adiante.) PODE cair na prova -------------------------- import Define as declarações import do Java que serão adicionadas à classe do servlet gerado. Você tem alguns import de graça (por padrão):java.lang (óbvio),javax. servlet,javax.servlet.http ejavax.servletjsp. isThreadSafe Define se o servlet gerado precisa implementar o SingleThreadModel que, como você já sabe, é uma Coisa Terrivelmente Ruim. O valor-padrão é... "true", o que significa: "Minha aplicação é thread-safe e eu NÃO preciso implementar o SingleThreadModel, pois sei que é ruim por natureza." A única razão para especificar este atributo seria se você precisasse configurar o valor do atributo para "false", o que significa que você quer que o servlet gerado use o SingleThreadModel, mas você nunca/ará isto. contentType Define o tipo MIME (e o código opcional do caractere) para a resposta JSP. Você conhece o padrão. isELlgnored Define se as expressões EL serão ignoradas quando a página for traduzi da. Nós só falaremos a respeito da EL no próximo capítulo. Por enquanto, saiba apenas que você talvez queira ignorar a sintaxe EL em sua página, e este é um dos dois modos que você pode informar ao Container. isErrorPage Define se a página atual representa uma outra página de erro dos JSPs. O valor- padrão é "false", mas se for true, as páginas têm acesso ao objeto implícito exception (que é uma referência ao inconveniente Throwable). Se for false, o objeto implícito exception fica indisponível para o JSP. errorPage Define uma URL para o recurso para onde os uncaught Throwables devem ser enviados. Se você definir um JSP aqui, então este JSP terá um atributo isErrorPage="true" na sua diretiva page. NÃO cairá na prova ---------------------------- language Define a linguagem scripting usada nos scriptlets, expressões e declarações. No momento, o único valor possível é "java", mas ele está aqui pensando no futuro - quando outras linguagens provavelmente serão usadas. extends Define a superclasse da classe que este JSP tomar-se-á. Você não o usará, a menos que REALMENTE saiba o que está fazendo - ele anula a hierarquia da classe fomecida pelo Container. session Define se a página terá um objeto implícito session. O valor-padrão é "true". buffer Define como o buffering é tratado pelo objeto implícito out (referente ao JspWriter). autoFlush Define se a saída bufferizada está limpa automaticamente. O valor-padrão é "true". info Define uma String que é inserida na página traduzida, exatamente para que você possa obtê-la usando o método getServletInfoO herdado do servlet. pageEncoding Define o código de caracteres para o JSP. O padrão é "ISO-8859-1" (a menos que o atributo contentType já o tenha definido ou a página use a sintaxe XML Document). você está aqui... 315
  • 345. usando oJSP Scriptlets cotlsideradas prejudiciais? Isso é verdade? Poderia haver uma desvantagem em se colocar todo este Java no seu JSP? Afinal, não é este todo o PROPÓSITO do JSP? De forma que você escreva seu Java no que é essencialmente uma página HTML, ao contrário de escrever o HTML em uma classe Java? Algumas pessoas acreditam (tudo bem, tecnicamente um monte de gente, inclusive as equipes que criaram as especificações do JSP e do servlet) ser uma prática ruim colocarmos todo este Java no seu JSP. Por que? Imagine que você foi contratado para construir um grande site. A sua equipe inclui uns poucos programadores Java e um enorme grupo de "webdesigners" - artistas gráficos e profissionais que criam páginas utilizando o Dreamweaver e o Photoshop para construírem aquelas páginas fabulosas. Eles não são programadores (bem, existem aqueles que continuam achando que HTML é " programação"). Atores aspirantes trabalhando como webdesigners enquanto esperam por sua grande oportunidade no showbiz. você está ••. 317
  • 346. fora do scripting Duas perguntas: POR QUE você está nos ensinando isso e QUAL é a alternativa? Que outra m**** EXISTE, além do HTML, já que não podemos usar scriptlets, declarações e expressões no JSP? Não EXISflA .,e.,hutMa alternativa. Isso significa que já existem montanhas de arquivos JSP abarrotados de código Java enfiados em cada pedaço da página, acomodados entre scriptlets, expressões e tags de declarações. Já está lá e não há nada que alguém possa fazer para mudar o passado. Portanto, significa que você tem que saber como ler e entender estes elementos e como manter páginas escritas com eles (a menos que você tenha a chance de recriar todo o JSP da sua aplicação). Cá entre nós, até achamos que ainda há lugar para coisas desse tipo - não há nada melhor do que um pouco de Java no JSP para testar rapidamente algo no seu servidor. Mas na maioria das vezes, você não vai querer usar isso nas suas páginas verdadeiras e em produção. A razão para tudo isto estar no exame é que as alternativas ainda são novidade. Por isso, a maioria das páginas hoje ainda é "da antiga". Por enquanto, você ainda tem que ser capaz de trabalhar assim! Em algum momento, quando novas técnicas que dispensem Java atingirem um público considerável, os objetivos deste capítulo provavelmente não constarão mais na prova. E respiraremos aliviados pela morte do Java-em-JSPs. Mas esse dia ainda não é hoje. (Nota para pais e professores: a palavra de cinco letras implícita no balão acima, que começa com "m" seguida por quatro asteriscos, NÃO é o que vocês estão pensando. É simplesmente uma palavra que achamos engraçada demais para ser incluída aqui, sem que distraísse o leitor. Por isso ela foi truncada. Porque é engraçada. E não, imprópria.) 318 7
  • 347. usando oJSP Poxa, se pelo menos existisse uma maneira do JSP usar tags simples que permitissem que os métodos J ava rodassem, sem ter que colocar na página o código Java em si. C> o EL: a resposta para, digatltos, tudo. Ou quase tudo. Mas certamente uma resposta para duas grandes reclamações sobre colocar o lava no lSP: 1. Os designers não precisariam saber Java. 2. O código Java existente no JSP é difícil de mudar e manter. EL significa "Expression Language" e, oficialmente, tomou-se parte da especificação a partir da especificação lSP 2.0. A EL é quase sempre o jeito mais simples de se fazer algo que você normalmente faria com scriptlets e expressões. É claro que neste momento você está pensando: "Mas se eu quiser que meu lSP use métodos customizados, como poderei declará-Ios e escrevê-Ios se não posso usar lava?" Ahhhh ... escrever a funcionalidade real (o código do método) não é o propósito da EL. O propósito da EL é oferecer um jeito simples de invocar o código lava - mas o código em si pertence a algum outro lugar. Ou seja, uma classe lava simples normal, que funcione como um lavaBean, uma classe com métodos estáticos, ou aquilo que chamamos de Tag Handler. Em outras palavras, você não escreve o código do método no seu lSP se você estiver seguindo as Melhores Práticas de hoje em dia. Você escreve o método lava em algum outro lugar e o chama usando a EL. você está ••. 319
  • 348. fora do scripting UtMa apresentação rápida da EL Uma expressão EL SEMPRE o capítulo seguinte fala só sobre EL, portanto não se parece com: ${alguma entraremos em detalhes aqui. A única razão de estarmos coisa} falando dela é devido ao fato de ela ser um outro elemento (com sua própria sintaxe) que o JSP aceita. E os objetivos Ou seja, ela vem SEMPRE da prova que constam neste capítulo incluem reconhecer entre chaves e precedida tudo o que possa estar em um JSP. pelo símbolo ($). Esta expressão EL: Please contact: ${applicationScope.mail} É o mesmo que esta expressão Java: Please contact: <%= application.getAttribute("mail") %> Não exIstem f etguntéls idl9Í:élS r: Não querendo ser chato, mas creio não ter visto nenhuma grande diferença entre a EL e a expressão Java. Claro que ela é um pouco menor, mas vale a pena mudar toda a linguagem scripting e os códigos no JSP? 1: Você AINDA não viu as vantagens da EL. As diferenças tornar- se-ão óbvias no próximo capítulo, quando mergulharemos no assunto de cabeça. Mas você deve se lembrar que para um programador Java, a EL NÃO oferece, necessariamente, uma gigantesca vantagem no desenvolvimento. Na realidade, para um programador Java ela simplesmente significa "uma coisa a mais (com sua própria sintaxe e tudo) para aprender, quando, psiu, eu já SEI Java ..." Mas não é só com relação a você. A EL é muito mais fácil para alguém que não programe em Java aprender rapidamente. E para um programador Java, ainda é muito mais fácil manter uma página sem scripts. Sim, é mais uma coisa a aprender. Ela não deixa os webdesigners completamente a salvo, mas você verá em breve que é mais intuitivo e natural para eles usar a EL. Por enquanto, aqui neste capítulo, você simplesmente precisará ser capaz de reconhecer uma EL quando se deparar com ela. E não se preocupe ainda em diferenciar se a EL é válida - tudo que queremos saber agora é se você consegue identificar uma expressão EL em uma página JSP. 320 capítulo 7
  • 349. usando oJSP Usat1do <Scriptit1g~it1valid> É simples, você pode impedir que um JSP possua elementos scripting (scriptlets, expressões Java ou declarações), colocando uma tag <scripting-invalid> no DD: <web-app ...> <jsp-config> <jsp-property-group> <url-pattern>*.jsp</url-pattern> <scripting-invalid> true </scripting-invalid> IS+6 Jesdfll-h. 6S </jsp-property-group> </ jsp-config> elellP;ePl+6s scri,+tPlj pare. rf:ibos (lS JSPs </web-app> l'1a fJ.p/í'ca{41J (p.:.r1pe (JSO,IIP;6S *,:}Sf> C(lIIP;(I tJ Cuidado - você pode ter visto outros livros e pfJ.dr'ió de tJ/I!.L). artigos mostrando uma diretiva page que desabilita o scripting. Na versão rascunho da especificação 2.0, havia um atributo da diretiva page: <%@ page isScriptingEnabled="false" %> Is+ •• PI'i•• tllm:ttJP1e.! () fJ.+rtbll+tJ __ ~ i'sScrip+/'PI;7"PlfJ.b1e.d PI'i<I'J CIJP1s+1J. mas ele foi removido da especificação IIP;lJ,i's lIJ, speclti'clJ.f'iIJ P e dlJ JSP/ definitiva!! A única forma de invalidarmos o scripting agora é através da tag <scripting-invalid> no DD. você está ~ 321
  • 350. ignorando a EL Você pode decidir ignorar a EL Sim, a EL é uma coisa legal que salvará o mundo, como nós já sabemos. Mas algumas vezes você pode querer desabilitá-Ia. Por quê? Lembre-se de quando a palavra-chave assert foi adicionada na linguagem Java versão 1.4. De uma hora para outra, o identificador perfeitamente legal e não reservado "assert" passou a significar algo para o compilador. Então, se você tivesse, digamos, uma variável chamada assert, você estaria "ferrado". Com exceção da versão J2SE 1.4, que veio com as declarações desabilitadas por padrão. Se você soubesse que estaria escrevendo (ou recompilando) um código que não usasse assert como identificador, você poderia escolher habilitar as tais declarações. Ou seja, é quase o mesmo que desabilitar a EL - se você decidiu ter template text (HTML simples ou texto) em um JSP que incluísse algo parecido com a EL ($ {alguma coisa} ), você estaria com um Grande Problema, caso não pudesse informar ao Container para ignorar tudo que se parecesse com a EL, em vez de tratar como qualquer outro texto comum. Exceto pelo fato de haver uma grande diferença entre a EL e as assertions: A EL é habilitada por padrão! Se você quiser que os elementos do seu JSP parecidos com a EL sejam ignorados, você tem que dizer explicitamente, ou através de uma diretiva page ou de um elemento no DD. A.diretiva page tem prioridade sobre a Inserindo <el-ignored> no DD configuração do DO! <web-app ...> Se houver um conflito entre a tag <el-ignored> configurada n? D.D <jsp-config> o atributo isELIgnored da dlretlva <jsp-property-group> <url-pattern>*.jsp</url-pattern> page, a diretiva se,!!pre ga~ha! <el-ignored> Isto permite a voce determmar o true comportamento-padrão no DD, </el-ignored> mas, também, anulá-Io em uma </jsp-property-group> página especifica, usando uma </jsp-config> diretiva page. </web-app> Cuidado com as inconsistências na nomenclatura! A tag do DD é <el-ignored> Usando o atributo isELlgnored portanto, alguém poderia ' da diretiva page pe~sar, com toda razão, que o atributo da diretiva page seria talvez, elIgnored. Mas não ' <%@ page isELIgnored="true" %> esse alguém estaria errad; se chegasse a tal conclusão. O DDe d' . _a ~r~tzva para ignorar a l EL sao dIstzntos! Não caia na armadilha da <is-el-ignored>. 2 :: i&1; i 322 capítulo 7
  • 351. usando o JSP Mas espere ... existe UtMoutro eletMettto JSP que nós ainda não vitMos: Até aqui, você viu cinco diferentes tipos de elementos que podem aparecer em um JSP: scriptlets, diretivas, declarações, expressões Java e expressões EL. Mas nós não vimos as ações. Elas vêm em dois sabores: padrões e... não-padrões. Ação-Padrão: <jsp:include page="wickedFooter.jsp" Outra Ação: <c:set var="rate" value="32" /> Embora possa parecer confuso, existem ações que não são consideradas ações-padrão, mas que ainda fazem parte de uma biblioteca agora padronizada. Ou seja, você aprenderá mais tarde que algumas ações não-padrão (os objetivos referem-se a elas como customizadas) são ... padrões, mas ainda não são consideradas "ações-padrão". Sim, é isso mesmo: elas são ações customizadas padronizadas não-padrão. Agora não ficou mais claro? Num capítulo mais adiante, quando chegarmos em "usando tags", usaremos um vocabulário um pouco mais rico, em que trataremos deste assunto mais detalhadamente. Então, relaxe. Agora, tudo o que nos interessa é que você reconheça uma ação quando se deparar com ela em um JSP! Observe a sintaxe de uma ação e compare-a com a sintaxe de outros tipos de elementos JSP. E responda: 1) Quais são as diferenças entre o elemento de uma ação e um scriptlet? 2) Como você reconheceria uma ação? você está ." 323
  • 352. exercício de avaliação Matriz de Avaliação O que acontece quando cada uma destas configurações (ou a combinação delas) ocorre? Você verá E){etc1C19S ? o as respostas quando virar a página; portanto, faça AGORA. Faça um X na coluna avaliado, se as combinações levarem as expressões EL a serem avaliadas, OU faça um X na coluna ignorado, se a EL for tratada como outro texto template. Nenhuma linha terá as duas opções marcadas, é claro. o Avaliação da EL Configuração no DD diretiva de página avaliado ignorado <el-ignored> isELlgnored verdadeira falsa não-especificado não-especificado Faça um X na coluna avaliado, se as configurações levarem as expressões de scripting a serem avaliadas, OU faça um X na coluna erro, se o scripting gerar um erro de tradução. e Validade do scripting avaliado Configuração ignorado no DD não-especificado verdadeira falsa 324 capítulo 7
  • 353. ~ e>?~' ",,<PqT 1t ímã de GeladeIra (Element9SJSY) t Correlacione o elemento JSP com o seu trecho de código, associando o código à caixa que o representa. Lembre-se de que você terá questões "arrastar e soltar" no exame, semelhante a este exercício; então, não o pule! Tipo de elemento JSP Trecho de código JSP , ; êlirefiva /}"1"4Sie e sclie "a CIA/XIi. cttll"l"es/'(j"de"ie. <% Float one = new Float (42.5); %> =' 3; %> <%! int Y <%@pagei mport=Njava.util. " <jsp:include i<%= pagecontext g tAt . .e tr~bute{"foON)% email: ${ap ~'" ~ "" ~ ~ ' . eXlressão você está aqui li> 325
  • 354. exercício de avaliação ~ 17~$"ô~ 1mã de G-ela.de'lta.(Element98JSf): C9nt1nua.c;ã9 ~. yocê sabe o ~ome deles, ~as :,oc~ se lembra onde eles ficam no servlet gerado? . E claro que Sim. Mas este e so maiS um reforço antes de passarmos para um capítulo e um assunto diferentes. (Considerando o arquivo da classe servlet, coloque o elemento no quadro onde o código gerado por ele ficará. Note que o ímã, em si, não representa o código REAL que será gerado.) public final class BasicCounter_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent { public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException { A- IJl'dehldes+es 1-l'ês :11';5 ; ll'l'eleval1+e. request.getA·ttl~it'ute email: ${applicationScope <%! int Y = 3; %> 326 capjitulo 7
  • 355. Matriz de Avaliação RESPOSTAS EXetc1C19S ~o o Avaliação da EL Configuração no DD diretiva de página avaliado ignorado <el-ignored> isELlgnored não-especificado V falsa '" verdadeira não-especificado '" f) Validade do scripting avaliado '" '" Configuração ignorado no DD não-especificado você está
  • 356. res:{Josta'sdos elementos JSP ~ Imã de GeladeI!a (Element9SJSY) Respostas Tipo de elemento JSP Trecho de código JSP A palavra "expressão" significa "expressão scripting", e NÃO "expressão EL". É claro que a palavra "expressão" é muito usada pelos elementos lSP Se você encontrar a palavra "expressão", ou "expressão scripting", elas querem dizer o mesmo: uma expressão que usa a sintaxe da linguagem lava: <%= foo.getNameO %> A única vez que a palavra "expressão" se refere à EL, é quando você especificar "EL" no label ou nas descrições! Portanto, considere sempre que o padrão para a palavra "expressão" é "scripting/ expressão lava ", e não EL. 328 capítulo 7
  • 357. usando o JSP ? /) g'; ímã ~ de Geüldeltq (Element9sJSY): C9nt1nuqyã9 ~ RESPOSTAS ; CCh>1Ih>a+ribll+ó 'Ity>cr+ '''''1>61'+ Javo.. public final class BasicCounter_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent { /}s declara)';'!s <%! int y = 3; %> X4.í.X4.8;e.f)5~ da classe taNJ.f public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException { <%=request.getAttribute(fffoo <% F10at one = new Float (42.5); %> Os scrip+le+s 'tc4h> del1+r<> da h>é-I-4d4 sel"vtce. emai1: ${app1icationscope.mai1} /}s express';es ii- ·hclJ.h>deJOi+l'c dD h>é+"d4 sel'viée. (!J4+",: 4 ól'deh> des+es +1"'& é i"rl'elevll.l1+e,:; AJor/}: Iflf<lbre-"se tle 3ve., c:tlijíJ JSP l171íJ ICIJr) F tle Ia.+tl) iJ.$SIW! «4 sf!rvle+ ••• é +4«1J +ra«v-;ifJ.1J paf'a C c:tlijlJ Jo.v#.. l.s+e exen:Ci"6 If<IlJs+rO,f' elf<l '/;V41 pa.f'ff da elas se jef'ada eSffs elelf<lel1+lJs 11711J es1-lJ.lf<ltJsIf<IfJs1-f'tJ.l1dtJ-It.f!.o e:JijtJ real 5*=1'0.«6PQra éI '/;val 1-f'e.tlv;ttl..,s. PaI' eXf""'Pló) ti Jedaf'Qg71lJ 'tive ef'Q <.%II).;1-? •• 3; %> 1-cN1frSe st""'P/fslf<le"ff 1i1f; ••3; . você está •.. 329
  • 358. teste preparatório fausa pata 9 caté 7e4teP~-~7 1Dado o elemento DD: 47. <jsp-property-group> 48. <url-pattern>*.jsp</url-pattern> 49. <el-ignored>true</el-ignored> 50. </jsp-property-group> o que o elemento faz? (Escolha todas as que se aplicam.) O A. Todos os arquivos com o mapeamento da extensão especificada devem ser tratados pelo container JSP como arquivos que respeitam a sintaxe XML. O B. Todos os arquivos com o mapeamento da extensão especificada devem ter seus códigos EL avaliados pelo container JSP. O C. Por padrão, NENHUM arquivo com o mapeamento da extensão especificada deve ter seus códigos Expression Language avaliados pelo container JSP. O D. Nada. Esta tag NÃO é reconhecida pelo container. O E. Embora esta tag seja válida, ela é redundante, pois o container já faz isso por padrão. 2 Quais das diretivasabaixo representam uma resposta HTTP do tipo "image/svg"? (Escolha todas as que se aplicam.) DA. <%@ page type="image/svg" %> OB.<%@ page mimeType="image/svg" %> OC.<%@ page language="image/svg" %> OD.<%@ page contentType="image/svg" %> CJE.<%@ page pageEncoding="image/svg" %> 330 capítulo 7
  • 359. .3 Seja o JSP: 1. <%@ page import="java.util.*" %> 2. <html><body> The people who like 3. <%= request.getParameter(~hobby") %> 4. are: <br> 5. <% ArrayList al = (ArrayList) request. getAttribute(~names"); %> 6. <% Iterator it = al.iterator(); 7. while (it.hasNext(» { %> 8. <%= it.next() %> 9. <br> 10. <% } %> 11. </body></html> Que tipos de códigos encontramos nele? (Escolha todas as que se aplicam.) OA.EL O B. diretiva O C. expressão O D. template text O E. scriptlet 4: Que declarações sobre o jspInit () são verdadeiras? (Escolha todas as que se aplicam.) O A. Ele tem acesso ao Serv1etConfig. O B. Ele tem acesso ao Serv1etContext O C. Só é chamado uma vez. O D. Pode ser anulado. você está
  • 360. 5 Que tipos de objetos estão disponíveis para o método j splnit () ? (Escolha todas as que se aplicam.) CJA.ServletConfig CJB.servletContext [JC.JspservletConfig [J D.JspServletContext [J E.HttpServletRequest [J F. HttpServletResponse 6 Dado: <%@page isELIgnored="true" %> o que acontece? (Escolha todas as que se aplicam.) [J A. Nada. A diretiva page NÃO foi definida. CJ B. A diretiva anula a avaliação que o container JSP faz do código da Expression Language em todos os JSPs da aplicação. CJ C. O JSP que possui esta diretiva será tratado pelo container JSP como um arquivo que respeita a sintaxe XML. CJ D. O JSP que possui esta diretiva NÃO deveria possuir nenhum código da Expression Language avaliado pelo container JSP. [J E. Esta diretiva apenas cancelará a avaliação da EL se o DD declarar um elemento <el-ignored>true</el-ignored> com um padrão URL que inclui este JSP. 1 Qual declaração referente aos JSPs é verdadeira? (Escolha uma.) [J A. Apenas o jsplnit () pode ser anulado. CJ B. Apenas o jspDestroy() pode ser anulado. O C. Apenas o _j spService () pode ser anulado. O D. O j splni t () e o j spDestroy () podem ser anulados. O E. O jsplni t (), o jspDestroy () e o _jspService () podem ser anulados. 332 capítulo 7
  • 361. usando o JSP 8 Qual das etapas do ciclo de vida do JSP está fora de ordem? O A. Traduzir o JSP em servlet. O B. Compilar o código-fonte do servlet. O C.Call jspService() O D. Instar a classe servlet. DE. Call jsplnit() O F.Call jspDestroy() 9 Quais das variáveis implícitas JSP são válidas? (Escolha todas as que se aplicam.) DA. stream O B. context O c. exception O D. listener OE.application 10 Seja uma solicitação com dois parâmetros: um chamado "first", que representa o primeiro nome do usuário, e o outro chamado "Iast", que representa seu último nome. Qual código scriptlet JSP gera os valores para estes parâmetros? DA. <% out.println (request. getParameter ("first")); out.println(request.getParameter("last"); %> O B. <% out.println(application.getlnitParameter("first"»); out.println(application.getlnitParameter("last"»); %> O c.<% println(request.getParameter("first"»; println(request.getParameter("last"); %> OD.<% println(application.getlnitParameter("first"); println(application.getlnitParameter("last"»; %> você está ~ 333
  • 362. teste preparatório 11 Dado: 11. He110 ${user.name}! 12. Your number is <c:out value="${user.phone}"/>. 13. Your address is <jsp:getProperty name="user" property="addr" /> 14. <% if (user.isValid(» {%>Youare valid!<% } %> Quais declarações são verdadeiras? (Escolha todas as que se aplicam.) O A. As linhas 11 e 12 (e nenhuma outra) contêm exemplos de elementos EL. O B. A linha 14 é um exemplo de código scriptlet. O C. Nenhuma das linhas deste exemplo contém um template text. O D. As linhas 12 e 13 incluem exemplos de ações-padrão JSP. O E. A linha 11 demonstra o uso incorreto da EL. O F. Todas as quatro linhas deste exemplo seriam válidas em uma página JSP. 12 Qual tag JSP exibirá o parâmetro de inicialização de contexto chamado "javax.sql.DataSource"? OA.<%= application.getAttribute(~javax.sql.DataSource") %> OB.<%= application.getlnitParameter(~javax.sql.DataSource") %> O C.<%= request.getParameter(~javax.sql.DataSource") %> OD.<%= contextParam.get(~javax.sql.DataSource") %> 13 Quais declarações sobre desabilitar elementos scripting são verdadeiras? (Escolha todas as que se aplicam.) O A. Você não pode desabilitar scripting via DD. O B. Você só pode desabilitar scripting no nível da aplicação. O C. Você pode desabilitar scripting programaticamente, utilizando o atributo de diretiva de página isScriptingEnabled. O D. Você pode desabilitar scripting via DD usando o elemento <scripting-invalid>. 334 cap,itulo 7
  • 363. 14 Em seqüência, quais são os tipos Java para os seguintes objetos implícitos JSP:app1ication,out,request,response,session? o A. java. 1ang .Throwab1e java.1ang.Object java.uti1.Map java.uti1.Set java. uti1. List [JB. javax.serv1et.Serv1etConfig java.1ang.Throwab1e java.1ang.Object javax.serv1et.jsp.PageContext java.uti1.Map [J C. javax.serv1et.Serv1etContext javax.serv1et.jsp.JspWriter javax.serv1et.Serv1etRequest javax.serv1et.Serv1etResponse javax.serv1et.http.HttpSession [JD. javax.serv1et.Serv1etContext java.io.PrintWriter javax.serv1et.Serv1etConfig java.1ang.Exception javax. serv1et.RequestDispatcher 15 Qual das opções representa um exemplo da sintaxe usada para importar uma classe em um JSP? o A. <% page import="java.uti1.Date" %> OB.<%@ page import="java.uti1.Date" @%> [J C.<%@ page import="java.uti1.Date" %> OD.<% import java.uti1.Date; %> [JE.<%@ import file="java.uti1.Date" %> 16 Dado o JSP: 1. <%@ page isELIgnored="true" %> 2. <%@ tag1ib uri=~http://java.sun.com/jsp/jsy1/core'' prefix="c" %> 3. <c:set var="awesomeBand" va1ue="LIMOZEEN"/> 4. $ {awesomeBand} Qual será a saída? o A. ${awesomeBand} O B. LIMOZEEN O C. Nenhuma saída O D. Uma exceção será enviada porque todas as diretivastaglibdevem preceder qualquer diretivapage. você está
  • 364. teste preparatório - respostas "fausa para º caté 1i!~-~7 1Dado o elemento DD: 47. <jsp-property-group> 48. <url-pattern>*.jsp</url-pattern> 49. <el-ignored>true</el-ignored> - lJr l>f'j';" C co.Plcela <) c:lcl./lc Jas 50. </jsp-property-group> eXfl'ess'4es íl... fell> cClrf-o.tPlel' JSP 2..tJ. .R.I' fiJ.dl'';''J c cl1m-l-o.t#iU' calcl./ltI a f.L. o que o elemento faz? (Escolha todas as que se aplicam.) O A. Todos os arquivos com o mapeamento da extensão especificada devem ser tratados pelo container JSP como arquivos que respeitam a sintaxe XML. O B. Todos os arquivos com o mapeamento da extensão especificada devem ter seus códigos EL avaliados pelo container JSP. liZ C. Por padrão, NENHUM arquivo com o mapeamento da extensão especificada deve ter seus códigos Expression Language avaliados pelo container JSP. O D. Nada. Esta tag NÃO é reconhecida pelo container. O E. Embora esta tag seja válida, ela é redundante, pois o container já faz isso por padrão. 2 Quais das diretivas abaixo representam uma resposta HTTP do tipo "image/svg"? (Escolha todas as que se aplicam.) DA. <%@ page type="image/svg" %> O B. <%@ page mimeType="image/svg" %> IiZc.<%@ page language="image/svg" %> OD.<%@ page contentType="image/svg" %> - lJr IJf'j';t; /) 4pl'esePl-l-o. tJ. s,-.,-I-axe O E.<%@ page pageEncoding="image/svg" %> ffJ.NI. es=l-a di'l'e-l-tVo.. 336 CB{)ítLii'O 7
  • 365. usando o JSP 3 Seja o JSP: 1. <%@ page import="java.util.*" %> 2. <html><body> The people who Iike 3. <%= request.getParameter(~hobby") %> 4. are: <br> 5. <% ArrayList aI = (ArrayList) request. getAttribute(~names"}; %> 6. <% Iterator it = al.iterator(}; 7. whiIe (it.hasNext()} { %> 8. <%= it.next(} %> 9. <br> 10. <% } %> 11. </body></html> Que tipos de códigos encontramos nele? (Escolha todas as que se aplicam.) DA.EL li2' B. diretiva - lJ';ó exis.f.e íL '1es.f.e J-SP' té••• (1"'11 t>s d"1"e·h-vo. #'/0. ",1./1 , •• li2' C. expressão expl'fIss;es 114 Ii...,hll l1a~ !,...,has 3 BJ fI .f.e""f'II1.f.e.f.ed 2) eJ '''5IcÓJ e!e•••e..,.f-cs scrip-h""j. P"'I' .f-"d,,'adó li2' D. template text li2' E. scriptlet 4 Que declarações sobre o jspInit () são verdadeiras? (Escolha todas as que se aplicam.) li2' A. Ele tem acesso ao ServletConfig. li2' B. Ele tem acesso ao ServletContext li2' C. Só é chamado uma vez. li2' D. Pode ser anulado. você está • 337
  • 366. teste preparatório - respostas 5 Que tipos de objetos estão disponíveis para o método j spIni t () ? (Escolha todas as que se aplicam.) ~ A. ServletConfig ~ B. ServletContext CJ C.JspservletConfig - Os JSPs v/,'all1 stl'vle-l-s siíJ'lf>les e ,til' lSSti h""'" acess<Ii CJD.JspservletContext ati; ól6e-l-os siíJ'lf>les Sel'v1e-I-Coill; e Sel'vle+C<liilh",-I- ••• CJE.HttpservletRequest e e Yh<t POtlC<li edo "10 delo de vtlia p41'a !a141'1I10S s<libl't c CJ F.HttpServletResponse stillci-l-asêes e I"es,os-l-as 6 Dado: <%@page isELIgnored="true" %> o que acontece? (Escolha todas as que se aplicam.) O A. Nada. A diretiva page NÃO foi definida. O B. A diretiva anula a avaliação que o container JSP faz do código da Expression Language em todos os JSPs da aplicação. CJ C. O JSP que possui esta diretiva será tratado pelo container JSP como um arquivo que respeita a sintaxe XML. ~ D. O JSP que possui esta diretiva NÃO deveria possuir nenhum código da Expression Language avaliado pelo container JSP. O E. Esta diretiva apenas cancelará a avaliação da EL se o DD declarar um elemento <el- ignored>true</ el- ignored> com um padrão URL que inclui este JSP. ;; es-A} l",col"l"e-l-lI<; <Jl''Ipe p li till'e-h"II11<;;.Ie-l-" "pe"J"s 6 16l '''c/llido. t Qual declaração referente aos JSPs é verdadeira? (Escolha uma.) O A. Apenas o j spIni t () pode ser anulado. O B. Apenas o jspDestroy() pode ser anulado. - Le...,bl'e-se tie O C. Apenas o _jspService () pode ser anulado. I e tl lilctl. tie 'fpe t/lI1 ~ D. O jspInit() e o jspDestroy() podem ser anulados. seI' fl.J1yltltió. O E. O j spIni t () , o j spDestroy () e o _j spService () podem ser anulados. 338 ca(.)itw'o 7
  • 367. usando o JSP 8 Qual das etapas do ciclo de vida do JSP está fora de ordem? D A. Traduzir o JSP em servlet. D B. Compilar o código-fonte do servlet. Iitr C. Call _jspService () D D. Instar a classe servlet. -() DE. Call jsplnit() D F.Call jspDestroy() 9 Quais das variáveis implícitas JSP são válidas? (Escolha todas as que se aplicam.) DA. stream D B. context Iitr c. exception - /}s efS4es,/} 8 e P "'';., exls-!--e"" ce""" O D. listener et.ie+<ls 'Ry-lictJ.<lS Cl",Q.,/"s pele ce",+al",el" pal"a 6S J-sPs. Iitr E. application 10 Seja uma solicitação com dois parâmetros: um chamado "first", que representa o primeiro nome do usuário, e o outro chamado "last", que representa seu último nome. Qual código scriptlet JSP gera os valores para estes parâmetros? Iitr A. <% out.println (request. getParameter ("first")); out.println(request.getParameter("last"»; %> D B. <% out.println(application.getlnitParameter("first"»; out.println(application.getlnitParameter("last"»; %> D C.<% println(request.getParameter("first"»; println(request.getParameter("last"»; %> DD.<% println(application.getlnitParameter("first"»; println(application.getlnitParameter("last"»; %> você está ~ 339
  • 368. teste preparatório - respostas 11 Dado: 11. Helio ${user.name}! 12. Your number is <c:out value=H${user.phone}HI>. 13. Your address is <jsp:getProperty name=HuserH property=HaddrH I> 14. <% if (user.isValid(» {%>You are valid!<% } %> Quais declarações são verdadeiras? (Escolha todas as que se aplicam.) IilA. As linhas 11 e 12 (e nenhuma outra) contêm exemplos de elementos EL. IilB. A linha 14 é um exemplo de código scriptlet. O C. Nenhuma das linhas deste exemplo contém um template text. O D. As linhas 12 e 13 incluem exemplos de ações-padrão JSP. O E. A linha 11 demonstra o uso incorreto da EL. Iil F. Todas as quatro linhas deste exemplo seriam válidas em uma página JSP. - ft ópj4ó C e5-/-; t"lc,u'l"e-/-a;IUJI"'1/le/-ódo.5 45 '1pa-/-l"ó11"t.uflJsslle/WIkIYlf'14k - kx-/-. - ft IJPf4ó P e5-/-: tIlCIJt'l"ff~ pól"flle a Íli7t.a 12 1l41Jli7cllllll/WIa4f4rrpaJI"41J JsP, - ft IJPf4ó ~ es+: Ii7CIJI"N':+4; plJl"'Il'e 4 f.L i?4 ili7t.4 é V:II(J4. 12 Qual tag JSP exibirá o parâmetro de inicialização de contexto chamado "javax.sql.DataSource"? <.JsPv 2.0; p~. O A. <%= application.getAttribute ("javax. sql.DataSourceH) %> IilB.<%= application.getlnitParameter("javax.sql.DataSourceH) %> OC.<%= request.getParameter("javax.sql.DataSourceH) %> O D. <%= contextParam.get("javax.sql.DataSourceH) %> - ft IJft/à.óg /WIós-/-t'O, 6lsó ClJl"I"ffó dó ótJe+ó I'''''pll(:l1-ó appllca+lói? 13 Quais declarações sobre desabilitar elementos scripting são verdadeiras? (Escolha todas as que se aplicam.) <.JSPv2.0; se{itJ 3.3.3) O A. Você não pode desabilitar scripting via DD. O B. Você só pode desabilitar scripting no nível da aplicação. O C. Você pode desabilitar scripting programaticamente, utilizando o atributo de diretiva de página isScriptingEnabled. Iil D. Você pode desabilitar scripting via DD usando o elemento <scripting-invalid>. - ~cê s: pó"e desdllt+o.l" ele/WIel'/+tJs SCl"ip-hi75 peló PP. () ele/WIel7+ó <JsP-pl"ópel"-/-yróllf> pósslbNt+a 311e.tesablltk/WIós 5CI"I.,:';:'''5 4'51117S e.•• Jsps; deltl7,i7,,(tlpaeil";es eie fJ/(Ls pal"IJ.Sí!N!/WI ,,(esa!;tlt+a,,(as. 340 capítuío 7
  • 369. usando oJSP 14 Em seqüência, quais são os tipos Java para os seguintes objetos implícitos JSP:application,out,request,response,session? o A. java. lang. Throwable java.lang.Object java.util.Map java. util. Set java.util.List O B. javax.servlet.ServletConfig java. lang. Throwable java.lang.Object javax.servlet.jsp.PageContext java.util.Map ~c. javax.servlet.ServletContext javax.servlet.jsp.JspWriter - IJ: 6pf';a e "'1J$+~a I) +SiM javax.servlet.ServletRequest de cada IJtje+1J ,....,.lIet+lJ. javax.servlet.ServletResponse javax.servlet.http.HttpSession O D. javax.servlet.ServletContext java.io.PrintWriter javax.servlet.ServletConfig java.lang.Exception javax. servlet.RequestDispatcher 15 Qual das opções representa um exemplo da sintaxe usada para importar uma classe em um JSP? (JsPv2.0jp~, l-t/t/) DA. <% page import="java.util.Date" %> - fJr$ IJpfaes lJr e b $';IJ lnv'lit1asj P<31'3l1e OB.<%@ page import="java.util.Date" @%> ape'ltl.S as declIJ.1"4jaes Jav(J, pade'" vrl" el1+l'f! ~c.<%@ page import="java.util.Date" %> (J,S+f4js <% ••. %:>. CJD.<% import java.util.Date; %> - rr 11. "'e; f! I) lIPirCI)f!Xf!"'P'1) "pj44 , " sli,+tlJ<:e cl)l"l'e+a. O E.<%@ import file="java.util.Date" %> -fJr f.é 16 Dado o JSP: 1. <%@ page isELIgnored="true" %> 2. <%@ taglib uri=~http://java.sun.com/jsp/jsyl/core'' pre:fix="c" %> 3. <c:set var="awesomeBand" value="LIMOZEEN"/> 4. ${awesomeBand} Qual será a saída? - 0pf';a IJ:: (J, expl"f!SS';1) f.L. é 'nl)f'lldlJ. e p4S$all -h:X+V41"'f!n-h:. ~ A. $ {awesomeBand} O B. LIMOZEEN O C. Nenhuma saída O D. Uma exceção será enviada porque todas as diretivastaglibdevem preceder qualquer diretivapage. você está ~ 341
  • 370. 8 JSf sem scdpts Páginas sem scripts Fuja do scripting. Será que seus webdesigners precisam mesmo saber Java? Isso é justo? Será que eles pensam que quem programa em Java para servidores tornar-se-á, digamos, designer gráfico? E mesmo que a equipe seja só você, você quer mesmo um monte de bits e pedaços de códigos Java nos seus JSPs? Você sabe o que significa "um pesadelo na hora da manutenção"? Escrever páginas sem scripts não só é possível, como é mais fácil e mais flexível com a nova especificação JSP 2.0, graças à nova Expression Language (EL). Padronizada depois do JavaScript e do XPATH, os webdesigners sentir-se-ão em casa com a EL. E você também vai gostar (assim que você se acostumar). Porém, existem algumas armadilhas ... a EL se parece com o Java, mas não é. Às vezes, a EL se comporta de forma diferente de como comportar-se-ia a mesma sintaxe no Java. Portanto, fique atento! este é um novo ~ 343
  • 371. objetivos do exame oficial da Sun Construir páginas JSP usando a Notas sobre a Abrangência: Expression Language (EL) e as Ações-padrão Todos os objetivos sobre este assunto são abordados completamente neste capítulo. E ele 7.1 Escrever um código snippet usando é bem grande! Vá devagar neste capítulo, pois variáveis de alto nível na EL. Isto temos muitos detalhes minuciosos a encarar. inclui as seguintes variáveis implícitas: pageScope, requestScope, sessionScope e applicationScope; param e param Values; header e headerValues; cookies e initParam. 7.2 Escrever um código snippet usando os seguintes operadores EL: property access (o operador".") e collection access (o operador "O"). 7.3 Escrever um código snippet usando os seguintes operadores EL: operadores aritméticos, operadores relacionais e operadores lógicos. 7.4 Para funções EL: escrever um código snippet usando uma função EL; identificar ou criar a estrutura de arquivos TDL usada para declarar uma função EL; e identificar ou criar um código exemplo para definir uma função EL. 8.1 Dado um objetivo de projeto, criar um código snippet usando as seguintes ações-padrão: jsp:useBean (com os atributos "id", "scope", "type" e "class"), jsp:getProperty e jsp:setProperty (com todos os atributos combinados). 8.2 Dado um objetivo de projeto, criar um código snippet usando as seguintes ações- padrão: jsp:include, jsp:forward e jsp:param. 6.7 Dado um objetivo de projeto específico para a inclusão de um segmento JSP em outra página, escrever um código JSP que use o Neste capítulo, vamos falar de AMBOS os mecanismo de inclusão mais apropriado mecanismos de include: o <jsp:include>, citado (a diretiva include ou a ação-padrão no objetivo 8.2, e a diretiva de página include, <jsp:include». mencionada no objetivo 6.7 (a maioria dos objetivos da seção 6foi abordada no capítulo anterior sobre JSPs). 344 8
  • 372. JSP sem scripts Nossa aplicação MVC depettde dos atributos Lembra na aplicação MVC original da cerveja, o Servlet controlador interagia com o modelo (classe Java com a lógica do negócio) e criava um atributo no escopo da solicitação antes de enviá-Ia à view JSP. O JSP tinha que receber o atributo do escopo da solicitação e usá-Io para gerar a resposta que seria enviada de volta ao cliente. Eis uma olhada rápida e simplificada de como o atributo vai do controlador para a view (imagine que o servlet se comunique com o modelo): Código do servlet (controlador) public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException String name = request. getParameter ("userName") _ usa o f{).,,:!i,:e+ro Je :>o/l'<::l+(u;';e request. setAttribute ("name", name); ~ de fef'h<íllb.l'ió Pb.I't1.Cl'iiu' S(;;ltCl';"o.g';o3í1f! esc"1M da <}a.+••l"v+o d~ tJ tJSP uSQ.":, RequestDispatcher view request.getRequestDispatcher("/result.jsp"); view. forward (request, response); ~ t~,:o.*I~j~Q.a fttu"t< a vlew. Código JSP (view) <html><body> Use "'*,4 eXft'ess';ó Je sct'i'p+'~5 po.t'f!. 6b+ef' <l Hello o.+t'lbll+/'J e exlbr-Io. J'lo.resfos+o.. <%= request.getAttribute("name") %> </body></html> (t...el>lbl'e-se: as express6es Je sCl'tp+I~5 SíWIt'i o o.f'5f.1h<fl'l+Ó ptU'o. " h<H-eJ" Heno Paul ' f.I n ef'a c VIJ,/{)f' IIl" o.+r"bl.ll-" J'lfJ.h<e • você está aqui iI> 345
  • 373. atributos non-Stríng Mas, e se o atributo t'lão for utta Strit'lg, e sitt utta it'lstât'lcia de Persot'l? E não só uma Person, mas uma Person com uma propriedade "name". Estamos usando o termo "propriedade" na forma do JavaBean* não-enterprise - a classe Person tem o par de métodos getNameO e setNameO, que de acordo com a especmcação do JavaBean quer dizer que Person tem uma propriedade chamada "name". Não se esqueça de que a propriedade "name" requer que a primeira letra, "n", seja alterada. Em outras foo.Person palavras, o nome da propriedade é o que você obtém ao retirar o prefixo "get" ou "set" e transforma em minúscula publico String a primeira letra subseqüente. Portanto, getName/setName vira simplesmente name. public void setName(String) o código servlet public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException foo.Person p = new foo.Person(); p.setName(~Evan"); request.setAttribute(~person", p); RequestDispatcher view = request.getRequestDispatcher("result.jsp"); view.forward(request, response); o código JSP <htrnl><body> Person is: <%= request.getAttribute(~person") %> </body></htrnl> o que QUEREMOS: O que CONSEGUIMOS: Person is: foo. Person is: Evan Person@512d66 01..••• (;bvtQIllf!"Jff Q eXpl'eSS4lJ /,~ ... d,QlIIlJ/I lJ IIIf'T'(;d(;7,aJI'Q(; +".5-htl'ljQ d{J 4+1'1"11/1+(; ••• *Falaremos sobre JavaBeans daqui a pouco, mas por enquanto, tenha em mente que ele é só uma classe Java simples, cujos getters e setters obedecem a uma convenção de nomes. 346 8
  • 374. JSP sem scripts PrecisatMos de tMaiscódigo para obter o "atMe de Perso" Enviar o resultado do getAttributeO para a declaração de exibir/escrever não nos dá o que queremos - isto só roda o método toStringO do objeto. E já que a classe Person não anula o ObjecttoStringO que foi herdado, bem, você sabe o que acontece. Mas nós queremos exibir o name de Person. o código JSP <htrnl><body> <% foo.Person p = (foo.Person) request.getAttribute(~personff); %> Person is: <%= p.getName() %> </body></htrnl> ~ "'-..... 'xi"!;e c <l t"es;;!-rad<l J de je+AJo.!t'leO. OU usando uma expressão <htrnl><body> Person is: <%= «foo.Person) request.getAttribute(~personff» .getName() %> </body></htrnl> o que RECEBEMOS: Person is: Evan Mas aí recordamos aquele LEMBRETE ... Aquele que pode ser resumido em "Use Scripts e Morra" Precisamos de outra técnica. você está •• 347
  • 375. JavaBean ações padrão Penot1 é UtMJavaJeat1, logo, usaretMos ações-padrão de beat1 Com duas ações-padrão podemos elinllnar todo o script do nosso JSP (lembre-se: o scripting inclui declarações, scriptlets e expressões) e ainda exibir o valor da propriedade name do atributo person. Não se esqueça de que name não é um atributo - apenas o objeto person é um atributo. A propriedade name é apenas aquilo que é retomado do método getNameO de Person. f s1-;;'w,os Sem ações-padrão (usando scripting) t aS stw, fllle f- <html><body> //)."/''lil.o <% foo.Person p = (foo.Person) request.getAttribute(~person"); %> Person is: <%= p.getName() %> </body></html> Com ações-padrão (sem scripting) <html><body> <jsp:useBean id="person" class="foo.Person" scope="request" /> Person created by servlet: <jsp:getProperty name="person" property="name" /> </body></html> 348 capítulo 8
  • 376. JSP sem scripts At1alisat1do a <jsp:use&eat1> e a <jsp:getProperty> Tudo o que realmente queríamos era a funcionalidade do <jsp:getProperty>, pois queríamos apenas mostrar o valor da propriedade "name" de person. Mas como o Container saberá o que quer dizer "person"? Se tivéssemos no JSP apenas a tag <jsp:getProperty>, seria praticamente como se usássemos uma variável não declarada chamada "person". O Container geralmente não faz idéia do que você está falando, a menos que você inclua na página PRIMEIRO uma <jsp:useBean>. A <jsp:useBean> é uma maneira de declarar e inicializar o objeto bean real que você está usando em <jsp:getProperty>. Declarando e inicializando um atributo bean com <jsp:useBean> scope="request"/> Obtendo o valor da propriedade de um atributo bean com <jsp:getProperty> <jsp:getProperty name="person" property="name" - /> ~ Itiel1+f-lica T é 11"lI'IetJa f'l'éfl'letJe.Gle IGleJ1h"ftco. ti é~e-I-6 bellJ1 (w S~1t.J &l.IefÓS SlIr ti 5eml' e 1J.31.1tló relll, IS+";ftliJJCftiil': Ctlll'l seffll" "lI! classe !;ee."l). " vali;;" tie M tilJl +1JlJ u // Alc+o.: eS+4 pl"épl'fetJt!tJe 11t:ll'le 9Sf:I.IS(~5ea,,>. 'l"ic ~" J1fttlt: ~yel' CCIl'lc fetilJ,jfJ 'ltllll'le=fersa"! tJes+tlI +1JlJ. 1Jip;.cfl"ietiIJ.tie ct.all'la- se 'lll"Xe Si'''''Plesil'le''rf-e fJ/?:I"Séll'/ tli ttleli'I'/i'tltl.. CC"X" 11 dllss/?: eal' CIJ,I./SllllJ,-Iél'lI'IiI. I você está to- 349
  • 377. <jsp:useBean> A <jsp:useJea.,> tatMbétM pode CRIAR UtMbea.,! Se <jsp:useBean> não puder encontrar um objeto atributo chamado "person", ele pode construir um! É parecido com a forma com que request.getSessionO (ou getSession(true)) funciona: ele primeiro procura por algo existente, mas caso não o encontre, ele cria um. Observe o código do servlet gerado e você verá o que está acontecendo - tem um teste iflá! Ele procura por um bean baseando-se nos valores de id e escopo na tag, e se não encontrar um, ele cria uma instância da classe especificada em class, atribui o objeto à variável id e a configura como um atributo no escopo que você definiu na tag. Esta tag <jsp:useBean id="person" class="foo.Person" scope="request" /> Transforma-se neste código no método -JspService() !JedlJ.t'tJ. (/#a VlJf'i~';I'el baSfltJ.i'1,;/ó-se '1ó vu.lifJl' de M, foo.Person person null; ~ i es+tJ. V4t'I{.vel 3ve pet'lOl-+e 3ve dó sev JSP<.tp/clvslve (w+NJ.$ +~s de synchronized (request) { N:flt'4# 4 eM.• person = (foo.Person) REQUEST _ SCOPE) ; jspx_page ç. 1é11+a e/;+et' r v 1I1J.1'1(;.vel context.getAttribute(nperson", AI <) il<)cê ,;/ef,),lllM. '11< 1J.+t'l!Jv+tJ P/li escilpiJ +~e o.+t'í"J,l/l e PageContext. JlA./tS; se AJ/ttJ I.,wllet' 11# if (person null) { ~ i1<)lOe esclJp<)", I1tJ _jspx~age_context.setAttribute(nperson", person, PageContext.REQUEST_SCOPE); ~ ç:,),lJ.lhle~; c<)p/fljf.lt'e IJ 11<)';1'<) lIfJe-I-fJ ctJlOfJ1110 • J '" lJ.+d!;v-rtJ '1ó esc"pfJ ave vlIce tlefi'J'llll. 350 capitulo 8
  • 378. JSP sem scripfs Isto pode ser uma coisa ruim - eu não QUERO ter um bean que não tenha seus valores de propriedade configurados! Se o Container cria um bean usando essa tag, o bean não terá valores de propriedade ... Você pode usar a <jsp:setProperty> Mas você já sabia que onde existe um get geralmente existe um set. A tag <jsp:setProperty> é a terceira e última ação-padrão bean. É simples de usá-Ia: <jsp:useBean id="person" class="foo.Person" scope="request" /> <jsp:setProperty name="person" property="name" value="Fred" /> você está aqui... 351
  • 379. <jsp:useBean> com um CO!PO Com o corpo de uma A <jsp:useJeat1> pode ter Uitcorpo! <jsP:UseBean>, você pode ter Se você puser seu código set (<jsp:setProperty» dentro do um CÓdigo que rode de forma Condicional. •• corpo de <jsp:useBean>, a configuração da propriedade torna-se condicional! Ou seja, os valores da propriedade SOMENTE se o atributo serão configurados apenas se um nov