287
.

uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

  • Upload
    others

  • View
    4

  • Download
    1

Embed Size (px)

Citation preview

Page 1: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

.

Page 2: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher
Page 3: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

EstaapostiladaCaelumvisaensinardeumamaneiraelegante,mostrandoapenasoqueénecessárioequandoénecessário,nomomentocerto,poupandoo leitordeassuntosquenãocostumamserdeseuinteresseemdeterminadasfasesdoaprendizado.

ACaelumesperaquevocêaproveiteessematerial.Todososcomentários,críticasesugestõesserãomuitobem-vindos.

Essa apostila é constantemente atualizada edisponibilizadano sitedaCaelum.Sempre consulteositeparanovasversõese,aoinvésdeanexaroPDFparaenviaraumamigo,indiqueositeparaqueelepossasemprebaixarasúltimasversões.Vocêpodeconferirocódigodeversãodaapostilalogono naldoíndice.

Baixesempreaversãomaisnovaem:www.caelum.com.br/apostilas

Esse material é parte integrante do treinamento Java para Desenvolvimento Web e distribuídogratuitamente exclusivamente pelo site da Caelum. Todos os direitos são reservados à Caelum. Adistribuição, cópia, revenda eutilizaçãoparaministrar treinamentos são absolutamente vedadas.Parausocomercialdestematerial,porfavor,consulteaCaelumpreviamente.

SOBREESTAAPOSTILA

Page 4: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

2

4

32

Sumário

1EnfrentandooJavanaWeb1.1OgrandemercadodoJavanaWeb 21.2Livrosesitesinteressantes 3

2BancosdedadoseJDBC2.1Porqueusarumbancodedados? 42.2PersistindoatravésdeSockets? 52.3AconexãoemJava 52.4FábricadeConexões 82.5DesignPatterns 102.6Exercícios:ConnectionFactory 112.7AtabelaContato 142.8Javabeans 152.9Inserindodadosnobanco 172.10DAO-DataAccessObject 202.11Exercícios:JavabeanseContatoDao 232.12Fazendopesquisasnobancodedados 262.13Exercícios:Listagem 272.14Umpoucomais... 292.15Exercíciosopcionais 292.16OutrosmétodosparaoseuDAO 292.17Exercíciosopcionais-Alterareremover 31

3OqueéJavaEE?3.1ComooJavaEEpodeteajudaraenfrentarproblemas 323.2AlgumasespecificaçõesdoJavaEE 333.3ServidordeAplicação 343.4ServletContainer 353.5Exercícios:PreparandooTomcat 363.6PreparandooTomcatemcasa 37

SumárioCaelum

Page 5: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

44

55

80

3.7Outraopção:Jetty 383.8IntegrandooTomcatnoEclipse 393.9OpluginWTP 393.10Exercícios:ConfigurandooTomcatnoEclipse 39

4NovoprojetoWebusandoEclipse4.1Novoprojeto 444.2Exercícios:Novoprojetoweb 444.3Análisedoresultadofinal 474.4CriandonossaspáginaseHTMLBásico 514.5Exercícios:primeirapágina 524.6Parasabermais:configurandooTomcatsemoplugin 524.7AlgumastagsHTML 53

5Servlets5.1Páginasdinâmicas 555.2Servlets 565.3Mapeandoumaservletnoweb.xml 585.4Aestruturadediretórios 595.5Exercícios:PrimeiraServlet 605.6Erroscomuns 625.7FacilidadesdasServlets3.0 645.8Parasabermais:WebServleteInitParamAnnotation 655.9Enviandoparâmetrosnarequisição 665.10Pegandoosparâmetrosdarequisição 675.11Exercícios:Criandofuncionalidadeparagravarcontatos 695.12GET,POSTemétodosHTTP 735.13TratandoexceçõesdentrodaServlet 735.14Exercício:TratandoexceçõesecódigosHTTP 755.15IniteDestroy 765.16UmaúnicainstânciadecadaServlet 775.17Exercíciosopcionais 795.18Discussão:Criandopáginasdentrodeumaservlet 79

6JavaServerPages6.1ColocandooHTMLnoseudevidolugar 806.2Exercícios:PrimeiroJSP 826.3ListandooscontatoscomScriptlet 836.4Exercíciosopcionais:Listadecontatoscomscriptlet 84

CaelumSumário

Page 6: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

88

105

114

6.5MisturandocódigoJavacomHTML 856.6EL:Expressionlanguage 866.7Exercícios:parâmetroscomaExpressionLanguage 866.8Parasabermais:CompilandoosarquivosJSP 87

7UsandoTaglibs7.1Taglibs 887.2InstanciandoPOJOs 897.3JSTL 907.4Instalação 907.5CabeçalhoparaaJSTLcore 917.6ForEach 917.7Exercícios:forEach 937.8Exercíciosopcionais 947.9Evoluindonossalistagem 957.10FazendoifscomaJSTL 957.11Exercícios:listadecontatoscomcondicionais 967.12Importandopáginas 987.13Exercícios:cabeçalhoserodapés 997.14Formataçãodedatas 1007.15Exercícios:Formatandoadatadenascimentodoscontatos 1017.16Parasabermais:linkscom<c:url> 1027.17Exercíciosopcionais:Caminhoabsoluto 1037.18Parasabermais:Outrastags 103

8TagscustomizadascomTagfiles8.1PorqueeuprecisariadeoutrastagsalémdaJSTL? 1058.2CalendárioscomjQuery 1068.3CriandominhasprópriastagscomTagfiles 1078.4Exercícios:criandonossaprópriatagparacalendário 1098.5Parasabermais:Outrastaglibsnomercado 1128.6Desafio:Colocandodisplaytagnoprojeto 112

9MVC-ModelViewController9.1ServletouJSP? 1149.2RequestDispatcher 1169.3Exercícios:RequestDispatcher 1169.4Melhorandooprocesso 1189.5RetomandoodesignpatternFactory 122

SumárioCaelum

Page 7: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

132

145

9.6Exercícios:Criandonossaslógicaseaservletdecontrole 1239.7Exercícios:Criandoumalógicapararemovercontatos 1249.8Fazendoalógicaparalistaroscontatos 1259.9Exercícios:Lógicaparalistarcontatos 1269.10Escondendonossaspáginas 1279.11Exercíciosopcionais 1289.12ModelViewController 1289.13Listadetecnologias:camadadecontrole 1299.14Listadetecnologias:camadadevisualização 1309.15Discussãoemaula:ospadrõesCommandeFrontController 130

10Recursosimportantes:Filtros10.1ReduzindooacoplamentocomFiltros 14010.2Exercíciosopcionais:Filtroparamedirotempodeexecução 13710.3Problemasnacriaçãodasconexões 13810.4Tentandooutrasestratégias 13910.5ReduzindooacoplamentocomFiltros 14010.6Exercícios:Filtros 142

11SpringMVC11.1PorqueprecisamosdeframeworksMVC? 14511.2Umpoucodehistória 14611.3ConfigurandooSpringMVC 14711.4Criandoaslógicas 14911.5AlógicaOláMundo! 14911.6Parasabermais:ConfigurandooSpringMVCemcasa 15011.7Exercícios:ConfigurandooSpringMVCetestandoaconfiguração 15111.8Adicionandotarefasepassandoparâmetros 15311.9Exercícios:Criandotarefas 15611.10Incluindovalidaçãonocadastrodetarefas 15811.11ValidaçãocomBeanValidation 15911.12Exercícios:Validandotarefas 16211.13Listandoastarefasedisponibilizandoobjetosparaaview 16311.14Exercícios:Listandotarefas 16511.15Redirecionandoarequisiçãoparaoutraação 16611.16Exercícios:Removendoealterandotarefas 16711.17Desafio-Calendário 16911.18Melhorandoausabilidadedanossaaplicação 17011.19UtilizandoAJAXparamarcartarefascomofinalizadas 171

CaelumSumário

Page 8: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

180

189

205

11.20ConfiguraroSpringMVCparaacessararquivoscomuns 17211.21Exercícios:Ajax 17311.22Parasabermais:AlterandovalordadatacomAJAX 17511.23ExercíciosOpcionais:MelhorandonossoAJAX 178

12SpringMVC:Autenticaçãoeautorização12.1Autenticandousuários:comofunciona? 18012.2Cookies 18012.3Sessão 18112.4Configurandootempolimite 18112.5Registrandoousuáriologadonasessão 18212.6Exercício:Fazendoologinnaaplicação 18212.7BloqueandoacessosdeusuáriosnãologadoscomInterceptadores 18412.8Exercícios:Interceptandoasrequisições 18612.9Exercíciosopcionais:Logout 187

13SpringIoCedeploydaaplicação13.1Menosacoplamentocominversãodecontroleeinjeçãodedependências 18913.2ContainerdeInjeçãodedependências 19213.3ContainerSpringIoC 19313.4Outrasformasdeinjeção 19513.5Exercícios:InversãodecontrolecomoSpringContainer 19613.6AprimorandoovisualatravésdeCSS 19813.7Exercíciosopcionais:AplicandoCSSnaspáginas 20013.8Deploydoprojetoemoutrosambientes 20113.9Exercícios:Deploycomwar 20213.10Discussãoemaula:lidandocomdiferentesnomesdecontexto 204

14UmaintroduçãopráticaaoJPAcomHibernate14.1MapeamentoObjetoRelacional 20514.2JavaPersistenceAPIeFrameworksORM 20614.3BibliotecasdoHibernateeJPA 20614.4MapeandoumaclasseTarefaparanossoBancodeDados 20714.5ConfigurandooJPAcomaspropriedadesdobanco 20814.6UsandooJPA 20914.7Parasabermais:ConfigurandooJPAcomHibernateemcasa 21014.8Exercícios:ConfigurandooJPAegerandooschemadobanco 21114.9Trabalhandocomosobjetos:oEntityManager 21414.10Exercícios:GravandoeCarregandoobjetos 215

SumárioCaelum

Page 9: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

220

224

234

14.11Removendoeatualizandoobjeto 21614.12Buscandocomumacláusulawhere 21714.13Exercícios:BuscandocomJPQL 218

15Eagora?15.1Osapêndicesdessaapostila 22015.2FrameworksWeb 22115.3Frameworksdepersistência 22215.4Ondeseguirseusestudos 222

16Apêndice-IntegraçãodoSpringcomJPA16.1GerenciandooEntityManager 22416.2ConfigurandooJPAnoSpring 22516.3InjetandooEntityManager 22616.4Baixoacoplamentopelousodeinterface 22716.5Gerenciandoatransação 22916.6Exercícios:IntegrandoJPAcomSpring 231

17Apêndice-VRaptor3eprodutividadenaWeb17.1Motivação:evitandoAPIscomplicadas 23417.2VantagensdeumcódigoindependentedeRequesteResponse 23717.3VRaptor3 23717.4Aclassedemodelo 23817.5Minhaprimeiralógicadenegócios 23917.6Redirecionandoapósainclusão 24017.7Criandooformulário 24117.8Alistadeprodutos 24217.9Exercícios 24417.10AprofundandoemInjeçãodeDependênciaseInversãodeControle 24717.11InjeçãodeDependênciascomoVRaptor 24817.12Escoposdoscomponentes 24817.13Exercícios:UsandoInjeçãodeDependênciasparaoDAO 24917.14Adicionandosegurançaemnossaaplicação 25017.15Interceptandorequisições 25217.16Exercícios:Construindoaautenticaçãoeaautorização 25317.17Melhorandoausabilidadedanossaaplicação 25617.18Parasabermais:Requisições:SíncronoxAssíncrono 25617.19Parasabermais:AJAX 25717.20AdicionandoAJAXnanossaaplicação 257

CaelumSumário

Page 10: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

262

270

17.21Exercíciosopcionais:AdicionandoAJAXnanossaaplicação 259

18Apêndice-JavaEE618.1JavaEE6easnovidades 26218.2Processamentoassíncrono 26318.3PlugabilidadeeWebfragments 26518.4RegistrodinâmicodeServlets 268

19Apêndice-TópicosdaServletAPI19.1Init-paramsecontext-params 27019.2welcome-file-list 27119.3PropriedadesdepáginasJSP 27119.4Inclusãoestáticadearquivos 27219.5TratamentodeerroemJSP 27319.6Descobrindotodososparâmetrosdorequest 27419.7Trabalhandocomlinkscomac:url 27419.8Contextlistener 27519.9OServletContexteoescopodeaplicação 27519.10Outroslisteners 277

Versão:22.8.23

SumárioCaelum

Page 11: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

.

Page 12: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO1

"Todohomemtemalgumaslembrançasqueelenãocontaatodomundo,masapenasaseusamigos.Eletemoutraslembrançasqueelenãorevelarianemmesmoparaseusamigos,masapenasparaelemesmo,efazissoemsegredo.Masaindaháoutraslembrançasqueohomemtemmedodecontaratéaelemesmo,etodo homem decente tem um considerável número dessas coisas guardadas bem no fundo. Alguém atépoderiadizerque,quantomaisdecenteéohomem,maioronúmerodessascoisasemsuamente."--FiodórDostoiévski,emMemóriasdoSubsolo

ComofazeraplataformaJavaeaWebtrabalharemjuntas?

CertamenteomercadocommaisoportunidadesemqueoJavaestápresenteéodeWeb.Nãoéporacasosuapopularidade:criarumprojetocomJavadámuitaliberdade,evitandocairnovendorlock-in.Em outras palavras, sua empresa fica independente do fabricante de vários softwares: do servletcontainer,dobancodedadoseatédaprópriafabricantedasuaVirtualMachine!Alémdisso,podemosfazertodoodesenvolvimentoemumsistemaoperacionalefazerodeploy(implantação)emoutro.

Apesar de tanta popularidade no ambiente Web, o desenvolvimento com Java não é trivial: énecessárioconhecercomcertaprofundidadeasAPIsdeservletsedeJSP,mesmoquesuaequipevenhautilizar frameworkscomoStruts,VRaptorou JSF.ConceitosdeHTTP, sessione cookies tambémsãomandatóriosparapoderenxergargargaloseproblemasquesuaaplicaçãoenfrentará.

Esse curso abordadesdeobancodedados, até ousode frameworksMVCparadesacoplar o seucódigo. Ao final do curso, ainda veremos o SpringMVC e o Hibernate, duas das ferramentas maispopularesentreosrequisitosnasmuitasvagasdeempregoparadesenvolvedorWeb.

Por fim, faltamencionar sobre a prática, que deve ser tratada seriamente: todos os exercícios sãomuito importantes e os desafios podem ser feitos quando o curso acabar. De qualquer maneira,recomendamosaosalunosestudaremcasa,principalmenteàquelesquefazemoscursosintensivos.

Como estudaremos várias tecnologias e ambientes, é comum esbarrarmos em algum erro que setorneumimpeditivoparaprosseguirnosexercícios,portantonãodesanime.

Lembre-se de usar o fórum do GUJ (http://www.guj.com.br/), onde sua dúvida será respondidaprontamente.Vocêtambémpodeentraremcontatocomseuinstrutorparatirardúvidasdurantetodoo

ENFRENTANDOOJAVANAWEB

1.1OGRANDEMERCADODOJAVANAWEB

.

Page 13: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

seucurso.

Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende

Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!

ConheçaaAluraCursosOnline.

É possível aprender muitos dos detalhes e pontos não cobertos no treinamento em tutoriais naInternetemportaiscomooGUJ,emblogseemmuitossitesespecializados.

http://www.guj.com.br/

A editoraCasa doCódigo possui livros de Java, comodeAndroid, JSF e JPA, e vende e-books apreçosbastantejustos:

http://www.CasaDoCodigo.com.br/

NãodeixedeconhecerosoutroscursosdaCaelum,inclusiveosnovoscursosonline,ondevocêpodecomeçaraestudaragoramesmo.

http://www.alura.com.br/

Agoraéamelhorhoradeaprenderalgonovo

1.2LIVROSESITESINTERESSANTES

.

Page 14: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO2

"Omedoéopaidamoralidade"--FriedrichWilhelmNietzsche

Aotérminodessecapítulo,vocêserácapazde:

conectar-seaumbancodedadosqualqueratravésdaAPIJDBC;criarumafábricadeconexõesusandoodesignpatternFactory;pesquisardadosatravésdequeries;encapsularsuasoperaçõescombancosdedadosatravésdeDAO-DataAccessObject.

Muitos sistemas precisam manter as informações com as quais eles trabalham para permitirconsultas futuras, geraçãode relatórios oupossíveis alteraçõesnas informações.Paraque essesdadossejammantidos para sempre, esses sistemas geralmente guardam essas informações emumbancodedados,queasmantémdeformaorganizadaeprontasparaconsultas.

A maioria dos bancos de dados comerciais são os chamados relacionais, que é uma forma detrabalharepensardiferenteaoparadigmaorientadoaobjetos.

OMySQLéobancodedadosqueusaremosduranteocurso.Éumdosmaisimportantesbancosdedados relacionais, e é gratuito, além de ter uma instalação fácil para todos os sistemas operacionais.Depoisdeinstalado,paraacessá-loviaterminal,fazemosdaseguinteforma:

mysql-uroot-p

Digitandoasenhaemseguida,casohaja.Seousuáriorootnãotiversenha,ocomandoacimanãoprecisado-p.

BANCODEDADOS

Para aqueles que não conhecem um banco de dados, é recomendado ler um pouco sobre oassuntoetambémterumabasedeSQLparacomeçarausaraAPIJDBC.

O processo de armazenamento de dados é também chamado de persistência. A biblioteca de

BANCOSDEDADOSEJDBC

2.1PORQUEUSARUMBANCODEDADOS?

.

Page 15: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

persistência embancodedados relacionais do Java é chamada JDBC (JavaDataBaseConnectivity), etambémexistemdiversasferramentasdotipoORM(ObjectRelationalMapping)quefacilitambastanteousodo JDBC.Nestemomento, focaremosnosconceitosenousodo JDBC.Veremosumpoucodaferramenta de ORMHibernate ao final destemesmo curso e, no curso FJ-25, commuitos detalhes,recursosetópicosavançados.

Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.

CasadoCódigo,ebookcompreçodeebook.

Paraconectar-seaumbancodedados,poderíamosabrirsocketsdiretamentecomoservidorqueohospeda,por exemplo,umOracleouMySQL, enos comunicarmos comele atravésde seuprotocoloproprietário.

Mas você conhece o protocolo proprietário de algum banco de dados? Conhecer um protocolocomplexoemprofundidadeédifícil,trabalharcomeleémuitotrabalhoso.

Uma segunda ideia seria utilizar umaAPI específica para cada banco de dados.Antigamente, noPHP,porexemplo,aúnicamaneiradeacessaroOracleeraatravésdefunçõescomooracle_connect,oracle_result,eassimpordiante.OMySQLtinhasuasfunçõesanálogas,comomysql_connect.Essaabordagemfacilitamuitonossotrabalhopornãoprecisarmosentenderoprotocolodecadabanco,mas fazcomque tenhamosdeconhecerumaAPIumpoucodiferenteparacada tipodebanco.Alémdisso,casoprecisemostrocardebancodedadosumdia,precisaremostrocartodoonossocódigopararefletirafunçãocorretadeacordocomonovobancodedadosqueestamosutilizando.

AconexãoaumbancodedadoséfeitademaneiraelegantecomJava.Paraevitarquecadabancotenhaa suaprópriaAPIeumconjuntodeclassesemétodos, temosumúnicoconjuntode interfaces

EditoraCasadoCódigocomlivrosdeumaformadiferente

2.2PERSISTINDOATRAVÉSDESOCKETS?

2.3ACONEXÃOEMJAVA

.

Page 16: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

muitobemdefinidasquedevemser implementadas.Esseconjuntode interfaces ficadentrodopacotejava.sqlenosreferiremosaelecomoJDBC.

Entreasdiversas interfacesdestepacote,existea interfaceConnection,quedefinemétodosparaexecutarumaquery(comouminserteselect),comitartransação,fecharaconexão,entreoutros.Caso queiramos trabalhar com o MySQL, precisamos de classes concretas que implementem essasinterfacesdopacotejava.sql.

EsseconjuntodeclassesconcretaséquemfaráaponteentreocódigoclientequeusaaAPIJDBCeobancodedados.Sãoessasclassesquesabemsecomunicaratravésdoprotocoloproprietáriodobancodedados. Esse conjunto de classes recebe o nome de driver. Todos os principais bancos de dados domercadopossuemdriversJDBCparaquevocêpossautilizá-loscomJava.Onomedriveréanálogoaoqueusamosparaimpressoras:comoéimpossívelqueumsistemaoperacionalsaibaconversarcomtodotipodeimpressoraexistente,precisamosdeumdriverquefaçaopapelde"tradutor"dessaconversa.

Para abriruma conexão comumbancodedados, precisamosutilizar sempreumdriver.A classeDriverManager éa responsávelpor secomunicarcomtodososdriversquevocêdeixoudisponível.Paraisso, invocamosométodoestáticogetConnectioncomumaString que indicaaqualbancodesejamosnosconectar.

EssaString-chamadadeStringdeconexãoJDBC-queutilizaremosparaacessaroMySQLtemsempreaseguinteforma:

jdbc:mysql://ip/nome_do_banco

DevemossubstituirippeloIPdamáquinadoservidorenome_do_bancopelonomedobancode

.

Page 17: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

dadosaserutilizado.

Seguindo o exemplo da linha acima e tudo que foi dito até agora, seria possível rodar o exemploabaixoereceberumaconexãoparaumbancoMySQL,casoeleestejarodandonamesmamáquina:

publicclassJDBCExemplo{publicstaticvoidmain(String[]args)throwsSQLException{Connectionconexao=DriverManager.getConnection("jdbc:mysql://localhost/fj21");System.out.println("Conectado!");conexao.close();}}

ReparequeestamosdeixandopassaraSQLException,queéumaexceptionchecked, lançadapormuitosdosmétodosdaAPIdeJDBC.Numaaplicaçãorealdevemosutilizartry/catch nos lugaresquejulgamoshaverpossibilidadederecuperardeumafalhacomobancodedados.Tambémprecisamostomarsemprecuidadoparafechartodasasconexõesqueforamabertas.

Aotestarocódigoacima,recebemosumaexception.Aconexãonãopôdeseraberta.Recebemosamensagem:

java.sql.SQLException:Nosuitabledriverfoundforjdbc:mysql://localhost/fj21

Porquê?

O sistemaaindanãoachouuma implementaçãodedriver JDBC quepode serusadapara abrir aconexãoindicadapelaURLjdbc:mysql://localhost/fj21.

OqueprecisamosfazeréadicionarodriverdoMySQLaoclasspath,ouseja,oarquivo.jarcontendoaimplementaçãoJDBCdoMySQL(mysqlconnector)precisasercolocadoemumlugarvisívelpeloseuprojeto ou adicionado à variável de ambiente CLASSPATH . Como usaremos o Eclipse, depois deadicionaro jardodriver JDBCdoMySQLnapastadoprojeto, faremos isso atravésdeumcliquedadireitaemnossoprojeto,BuildPatheemAddtoBuildPath.Veremosistopassoapassonosexercícios.

.

Page 18: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

EOCLASS.FORNAME?

Atéaversão3doJDBC,antesdechamaroDriverManager.getConnection()eranecessárioregistrar o driver JDBC que iria ser utilizado através do métodoClass.forName("com.mysql.jdbc.Driver"), no caso doMySQL, que carregava essa classe, eessasecomunicavacomoDriverManager.

ApartirdoJDBC4,queestápresentenoJava6,essepassonãoémaisnecessário.Maslembre-se:casovocêutilizeJDBCemumprojetocomJava5ouanterior,seráprecisofazeroregistrodoDriverJDBC,carregandoasuaclasse,quevaiseregistrarnoDriverManager.

Issotambémpodesernecessárioemalgunsservidoresdeaplicaçãoeweb,comonoTomcat7ouposterior,porproteçãoparapossíveisvazamentosdememória:

http://bit.ly/18BpDfG

Teoricamente,bastaalterarasduasStringsqueescrevemosparamudardeumbancoparaoutro.Porém,nãoétudotãosimplesassim!OcódigoSQLqueveremosaseguirpodefuncionaremumbancoenãoemoutros.DependedequãoaderenteaopadrãoANSISQLéseubancodedados.

Isso só causa dor de cabeça e existem projetos que resolvem isso, como é o caso do Hibernate(www.hibernate.org)edaespecificaçãoJPA(JavaPersistenceAPI).VeremosumpoucodoHibernateaofinaldessecursoebastantesobreelenoFJ-25.

Osdriverspodemserbaixadosnormalmentenositedofabricantedobancodedados.

Algunscasos,comonoMicrosoftSQLServer,existemoutrosgruposquedesenvolvemodriveremhttp://jtds.sourceforge.net . Enquanto isso, você pode achar o driver doMYSQL (chamado demysqlconnector)nositehttp://www.mysql.org.

Emdeterminadomomentodenossaaplicação,gostaríamosdeterocontrolesobreaconstruçãodosobjetosdanossaclasse.Muitopodeserfeitoatravésdoconstrutor,comosaberquantosobjetosforaminstanciadosoufazerologsobreessasinstanciações.

Àsvezes,tambémqueremoscontrolarumprocessomuitorepetitivoetrabalhoso,comoabriruma

Alterandoobancodedados

Driversdeoutrosbancosdedados

2.4FÁBRICADECONEXÕES

.

Page 19: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

conexãocomobancodedados.Tomemoscomoexemploaclassea seguir,que seria responsávelporabrirumaconexãocomobanco:

publicclassConnectionFactory{publicConnectiongetConnection(){try{returnDriverManager.getConnection("jdbc:mysql://localhost/fj21","root","<SENHADOBANCOAQUI>");}catch(SQLExceptione){thrownewRuntimeException(e);}}}

Assim, sempre que quisermos obter uma conexão com o banco no nosso código, usaremos ocomandoaseguir:

Connectioncon=newConnectionFactory().getConnection();

NotequeométodogetConnection()éumafábricadeconexões, istoé,elecrianovasconexõesparanós.Bastainvocarométodoerecebemosumaconexãoprontaparauso,nãoimportandodeondeelaveioeeventuaisdetalhesdecriação.Portanto,vamoschamaraclassedeConnectionFactoryeométododegetConnection.

Encapsulandodessaforma,podemosmaistardemudaraobtençãodeconexões,para,porexemplo,usarummecanismodepooling,queéfortementerecomendávelemumaaplicaçãoreal.

TRATAMENTODEEXCEÇÕES

Reparequeestamosfazendoumtry/catchemSQLException e relançando-a comoumaRuntimeException.FazemosissoparaqueoseucódigoquechamaráafábricadeconexõesnãofiqueacopladocomaAPIdeJDBC.Todavezquetivermosque lidarcomumaSQLException,vamosrelançá-lascomoRuntimeException.

Poderíamos ainda criar nossa própria exceção para indicar que ocorreu um erro dentro danossaFactory,algocomoumaConnectionFactoryException.

.

Page 20: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,

Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex-aluno daCaelumtem15%dedescontonestelink!

ConheçaoscursosonlineAlura.

Orientaçãoaobjetosresolveasgrandesdoresdecabeçaquetínhamosnaprogramaçãoprocedural,restringindoecentralizandoresponsabilidades.

Masalgunsproblemasnãopodemosresolversimplesmentecomorientaçãoaobjetos,poisnãoexistepalavrachaveparaumafuncionalidadetãoespecífica.

Algunsdessespequenosproblemasaparecemcomtantafrequênciaqueaspessoasdesenvolvemumasolução"padrão"paraele.Comisso,aonosdefrontarmoscomumdessesproblemasclássicos,podemosrapidamenteimplementaressasoluçãogenéricacomumaououtramodificação,deacordocomnossanecessidade.EssassoluçõespadrõestemonomedeDesignPatterns(PadrõesdeProjeto).

AmelhormaneiraparaaprenderoqueéumDesignPatternévendocomosurgiusuanecessidade.

AnossaConnectionFactoryimplementaodesignpatternFactory,quepregaoencapsulamentodaconstrução(fabricação)deobjetoscomplicados.

ABÍBLIADOSDESIGNPATTERNS

O livromais conhecidodeDesignPatterns foi escrito em1995 e tem trechosde código emC++eSmalltalk.Masoque realmente importa sãoos conceitos eosdiagramasque fazemdesselivroindependentedequalquerlinguagem.Alémdetudo,olivroédeleituraagradável.

DesignPatterns,ErichGammaetal.

JáconheceoscursosonlineAlura?

2.5DESIGNPATTERNS

.

Page 21: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

1. NoscomputadoresdaCaelum,cliquenoíconedoEclipsenoDesktop;

BAIXANDOOECLIPSEEMCASA

Estamos usando o Eclipse for Java EE Developers. Você pode obtê-lo direto no site doEclipseemwww.eclipse.org

FecheateladeWelcomecasoelaapareça

VamoscriarumprojetonoEclipsechamadofj21-jdbc.

VáemFile->New->Project:

SelecioneJavaProjectecliqueemNext:

2.6EXERCÍCIOS:CONNECTIONFACTORY

.

Page 22: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Coloqueonomedoprojetocomofj21-jdbcecliqueemFinish:

Aceiteamudançadeperspectiva:

2. CopieodriverdoMySQLparaoseuprojeto.

noseuDesktop,cliquenoatalhoAtalhoparaarquivosdocursos;copieapasta21paraoseuDesktop;

.

Page 23: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

entrenapasta21doDesktopecliquedadireitanodriverdoMySQLmaisnovo,escolhaCopy;váparasuapastaprincipal(home);entrenodiretórioworkspace,fj21-jdbc;cliquedadireitaeescolhaPaste:vocêacabadecolocaroarquivo".jar"noseuprojeto.

3. Vamoscriaraclassequefabricaconexões:

CliqueemFile->New->Class.

Crie-anopacotebr.com.caelum.jdbcenomeie-acomoConnectionFactory.

CliqueemFinish

Nocódigo,crieométodogetConnection,queretornaumanovaconexão.Quandoperguntado,importeasclassesdopacotejava.sql(cuidadoparanãoimportarNADAdecom.mysql).

publicConnectiongetConnection(){try{returnDriverManager.getConnection("jdbc:mysql://localhost/fj21","root","<SENHADOBANCOAQUI>");}catch(SQLExceptione){thrownewRuntimeException(e);}}

4. CrieumaclassechamadaTestaConexaonopacotebr.com.caelum.jdbc.teste.Todasasnossasclassesdetestedeverãoficarnessepacote.

Crieummétodomaindentrodaclasse.UseoatalhodoEclipseparaajudar.

Dentrodomain, fabriqueuma conexãousando aConnectionFactory que criamos.Vamosapenastestaraaberturadaconexãoedepoisfechá-lacomométodoclose:

Connectionconnection=newConnectionFactory().getConnection();System.out.println("Conexãoaberta!");connection.close();

Trateoserroscomthrows.(Use:Ctrl+1eescolha"addthrowsdeclaration").

.

Page 24: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

5. RodeasuaclasseTestaConexaopeloEclipse.

CliquedadireitanasuaclasseTestaConexao

Escolha Run as, Java Application (caso prefira, aprenda a tecla de atalho para agilizar naspróximasexecuções)

6. A aplicação não funciona pois o driver não foi encontrado? Esquecemos de colocar o JAR noclasspath!(BuildPathnoEclipse)

CliquenoseuprojetocomobotãodadireitaeescolhaRefresh(oupressioneF5).

SelecioneoseudriverdoMySQL,cliquedadireitaeescolhaBuildPath,AddtoBuildPath:

RodenovamentesuaaplicaçãoTestaConexaoagoraquecolocamosodrivernoclasspath.

Paracriarumatabelanova,primeirodevemosacessaroterminalefazerocomandoparalogarmosnomysql:

mysql-uroot-p

Digitandoemseguidaasenha,queoinstrutordiráqualésehouver.

Nospreparamosparausarobancodedadosfj21:

2.7ATABELACONTATO

.

Page 25: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

usefj21;

Aseguintetabelaseráusadanosexemplosdessecapítulo:

createtablecontatos(idBIGINTNOTNULLAUTO_INCREMENT,nomeVARCHAR(255),emailVARCHAR(255),enderecoVARCHAR(255),dataNascimentoDATE,primarykey(id));

No banco de dados relacional, é comum representar um contato (entidade) em uma tabela decontatos.

Querendoaprenderaindamaissobre?Esclarecerdúvidasdosexercícios?Ouvirexplicaçõesdetalhadascomuminstrutor?ACaelum oferece o cursoFJ-21 presencial nas cidades de São Paulo, Rio deJaneiroeBrasília,alémdeturmasincompany.

ConsulteasvantagensdocursoJavaparaDesenvolvimentoWeb

OquesãoJavabeans?AperguntaquenãoquersecalarpodeserrespondidamuitofacilmenteumavezqueumadasmaioresconfusõesfeitasaíforaéentreJavabeanseEnterpriseJavaBeans(EJB).

Javabeanssãoclassesquepossuemoconstrutorsemargumentosemétodosdeacessodotipogeteset!Maisnada!Simples,não?JáosEJBscostumamserjavabeanscomcaracterísticasmaisavançadasesãooassuntoprincipaldocursoFJ-31daCaelum.

Podemos usar beans em diversas situações, como em classes que representam nosso modelo dedados.

A seguir, você vê um exemplo de uma classe JavaBean que seria equivalente ao nossomodelo deentidadedobancodedados:

packagebr.com.caelum.jdbc.modelo;

publicclassContato{

VocêpodetambémfazerocursoFJ-21dessaapostilanaCaelum

2.8JAVABEANS

.

Page 26: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

privateLongid;privateStringnome;privateStringemail;privateStringendereco;privateCalendardataNascimento;

//métodosgetesetparaid,nome,email,endereçoedataNascimento

publicStringgetNome(){returnthis.nome;}publicvoidsetNome(Stringnovo){this.nome=novo;}

publicStringgetEmail(){returnthis.email;}publicvoidsetEmail(Stringnovo){this.email=novo;}

publicStringgetEndereco(){returnthis.endereco;}publicvoidsetEndereco(Stringnovo){this.endereco=novo;}

publicLonggetId(){returnthis.id;}publicvoidsetId(Longnovo){this.id=novo;}

publicCalendargetDataNascimento(){returnthis.dataNascimento;}publicvoidsetDataNascimento(CalendardataNascimento){this.dataNascimento=dataNascimento;}}

AespecificaçãoJavaBeansémuitograndeemaisinformaçõessobreessavastaáreaqueéabasedoscomponentesescritosemJavapodeserencontradaem:

http://docs.oracle.com/javase/tutorial/javabeans/

.

Page 27: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

MÉTODOSGETTERSESETTERS

UmerromuitocomumcometidopelosdesenvolvedoresJavaéacriaçãodosmétodosgettersesettersindiscriminadamente,semterarealnecessidadedaexistênciadetaismétodos.

Existe um artigo no blog da Caelum que trata desse assunto:http://blog.caelum.com.br/2006/09/14/nao-aprender-oo-getters-e-setters/

Os cursos FJ-11 e FJ-22 tambémmostram isso claramente, quando criam algumas entidadesquenãopossuemapenasgettersesetters.

SevocêquersabermaissobreEnterpriseJavaBeans(EJB),aCaelumofereceocursoFJ-31.NãoosconfundacomJavaBeans!

Para inserirdadosemumatabeladeumbancodedadosentidade-relacional,bastausaracláusulaINSERT.Precisamosespecificarquaisoscamposquedesejamosatualizareosvalores.

PrimeiroocódigoSQL:

Stringsql="insertintocontatos"+"(nome,email,endereco,dataNascimento)"+"values('"+nome+"','"+email+"','"+endereco+"','"+dataNascimento+"')";

O exemplo acima possui três pontos negativos que são importantíssimos. O primeiro é que oprogramadorquenãoescreveuocódigooriginalnãoconseguebateroolhoeentenderoqueestáescrito.O que o código acima faz? Lendo rapidamente fica difícil. Mais difícil ainda é saber se faltou umavírgula,umfechaparêntesestalvez?Eaindaassim,esseéumcasosimples.Existemtabelascom10,20,30 e até mais campos, tornando inviável entender o que está escrito no SQL misturado com asconcatenações.

Outro problema é o clássico "preconceito contra Joana D'arc", formalmente chamado de SQLInjection.Oqueacontecequandoo contato a ser adicionadopossuinonomeumaaspas simples?Ocódigo SQL se quebra todo eparade funcionarou, pior ainda, ousuário final é capazde alterar seucódigoSQLparaexecutaraquiloqueeledeseja (SQL injection)... tudo issoporqueescolhemosaquelalinhadecódigoenãofizemosoescapedecaracteresespeciais.

Maisumproblemaqueenxergamosaíénadata.ElaprecisaserpassadacomoumaString e noformatoqueobancodedadosentenda,portanto,sevocêpossuiumobjetojava.util.Calendar,queéonossocaso,vocêprecisaráfazeraconversãodesseobjetoparaaString.

2.9INSERINDODADOSNOBANCO

.

Page 28: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Poresses trêsmotivosnãousaremoscódigoSQLcomomostradoanteriormente.Vamos imaginaralgomaisgenéricoeumpoucomaisinteressante:

Stringsql="insertintocontatos"+"(nome,email,endereco,dataNascimento)"+"values(?,?,?,?)";

ExisteumamaneiraemJavadeescreverocódigoSQLcomonoprimeiroexemplodessaseção(comconcatenaçõesdeString).Essamaneiranãoseráensinadaduranteocursopoiséumapéssimapráticaquedificultaamanutençãodoseuprojeto.

Percebaquenãocolocamosospontosdeinterrogaçãodebrincadeira,massimporquerealmentenãosabemos o que desejamos inserir. Estamos interessados em executar aquele códigomas não sabemosainda quais são os parâmetros que utilizaremos nesse código SQL que será executado, chamado destatement.

AscláusulassãoexecutadasemumbancodedadosatravésdainterfacePreparedStatement.ParareceberumPreparedStatement relativo à conexão, basta chamar ométodo prepareStatement,passandocomoargumentoocomandoSQLcomosvaloresvindosdevariáveispreenchidoscomumainterrogação.

Stringsql="insertintocontatos"+"(nome,email,endereco,dataNascimento)"+"values(?,?,?,?)";PreparedStatementstmt=connection.prepareStatement(sql);

Logoemseguida, chamamosométodosetString doPreparedStatement parapreencherosvaloresquesãodo tipoString, passandoaposição (começandoem1)da interrogaçãonoSQLeovalorquedevesercolocado:

//preencheosvaloresstmt.setString(1,"Caelum");stmt.setString(2,"[email protected]");stmt.setString(3,"R.Vergueiro3185cj57");

Precisamosdefinirtambémadatadenascimentodonossocontato,paraisso,precisaremosdeumobjetodo tipojava.sql.Date parapassarmosparaonossoPreparedStatement.Nesse exemplo,vamospassaradataatual.Paraisso,vamospassarumlongquerepresentaosmilissegundosdadataatual paradentrodeumjava.sql.Date, que é o tipo suportado pelaAPI JDBC.Vamos utilizar aclasseCalendarparaconseguirmosessesmilissegundos:

java.sql.DatedataParaGravar=newjava.sql.Date(Calendar.getInstance().getTimeInMillis());stmt.setDate(4,dataParaGravar);

Porfim,umachamadaaexecute()executaocomandoSQL:

stmt.execute();

Imagine todo esse processo sendo escrito toda vez que desejar inserir algo no banco?Ainda não

.

Page 29: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

conseguevisualizaroquãodestrutivoissopodeser?

Vejaoexemploabaixo,queabreumaconexãoeinsereumcontatonobanco:

publicclassJDBCInsere{

publicstaticvoidmain(String[]args)throwsSQLException{

//conectandoConnectioncon=newConnectionFactory().getConnection();

//criaumpreparedStatementStringsql="insertintocontatos"+"(nome,email,endereco,dataNascimento)"+"values(?,?,?,?)";PreparedStatementstmt=con.prepareStatement(sql);

//preencheosvaloresstmt.setString(1,"Caelum");stmt.setString(2,"[email protected]");stmt.setString(3,"R.Vergueiro3185cj57");stmt.setDate(4,newjava.sql.Date(Calendar.getInstance().getTimeInMillis()));

//executastmt.execute();stmt.close();

System.out.println("Gravado!");

con.close();}}

NãoécomumutilizarJDBCdiretamentehojeemdia.OmaispraticadoéousodealgumaAPIdeORMcomoaJPAouoHibernate.TantonaJDBCquantoembibliotecasORMdeve-seprestaratençãonomomentodefecharaconexão.

O exemplo dado acima não a fecha caso algum erro ocorra nomomento de inserir um dado nobancodedados.Ocomuméfecharaconexãoemumblocofinally:

publicclassJDBCInsere{publicstaticvoidmain(String[]args)throwsSQLException{Connectioncon=null;try{con=newConnectionFactory().getConnection();

//fazummontedeoperações.//quepodemlançarexceptionsruntimeeSQLException}catch(SQLExceptione){System.out.println(e);}finally{con.close();}}}

Parasabermais:Fechandoaconexãopropriamente

.

Page 30: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Dessaforma,mesmoqueocódigodentrodotrylanceexception,ocon.close()seráexecutado.Garantimosquenãodeixaremosumaconexãopenduradasemuso.Essecódigopodeficarmuitomaiorse quisermos ir além. Pois o que acontece no caso de con.close lançar uma exception? Quem atratará?

Trabalharcomrecursoscaros, comoconexões, sessões, threadsearquivos, sempredeve sermuitobem pensado. Deve-se tomar cuidado para não deixar nenhum desses recursos abertos, pois poderávazar algopreciosodanossa aplicação.Comoveremosduranteo curso, é importante centralizar essetipodecódigoemalgumlugar,paranãorepetirumatarefacomplicadacomoessa.

Além disso, há a estrutura do Java 7 conhecida como try-with-resources. Ela permite declarar einicializar,dentrodotry,objetosque implementamAutoCloseable.Dessa forma, ao términodotry, o próprio compilador inserirá instruções para invocar o close desses recursos, além de seprecaveremrelaçãoaexceçõesquepodemsurgirporcausadessainvocação.Nossocódigoficariamaisreduzidoeorganizado,alémdoescopodeconsóvalerdentrodotry:

try(Connectioncon=newConnectionFactory().getConnection()){//fazummontedeoperações.//quepodemlançarexceptionsruntimeeSQLException}catch(SQLExceptione){System.out.println(e);}

Em vez de usar o PreparedStatement, você pode usar uma interface mais simples chamadaStatement,quesimplesmenteexecutaumacláusulaSQLnométodoexecute:

Statementstmt=con.createStatement();stmt.execute("INSERTINTO...");stmt.close();

MasprefiraaclassePreparedStatementqueémais rápidaqueStatement e deixa seu códigomuitomaislimpo.

Geralmente, seus comandos SQL conterão valores vindos de variáveis do programa Java; usandoStatements,vocêteráquefazermuitasconcatenações,masusandoPreparedStatements, isso ficamaislimpoefácil.

AAPIdedatasdoJava,mesmoconsiderandoalgumasmelhoriasdaCalendaremrelaçãoaDate,aindaémuitopobre.Naversão8doJavatemosumaAPInova,ajava.time,quefacilitabastanteotrabalho.ElaébaseadanaexcelentebibliotecadedataschamadaJodaTime.

Parasabermais:AmápráticaStatement

Parasabermais:JodaTime

2.10DAO-DATAACCESSOBJECT

.

Page 31: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

JáfoipossívelsentirquecolocarcódigoSQLdentrodesuasclassesdelógicaéalgonemumpoucoeleganteemuitomenosviávelquandovocêprecisamanteroseucódigo.

Quantasvezesvocênãoficoubravocomoprogramadorresponsávelporaquelecódigoilegível?

Aideiaaseguiréremoverocódigodeacessoaobancodedadosdesuasclassesdelógicaecolocá-loemumaclasseresponsávelpeloacessoaosdados.Assimocódigodeacessoaobancodedadosficaemumlugarsó,tornandomaisfácilamanutenção.

QuetalsepudéssemoschamarummétodoadicionaqueadicionaumContatoaobanco?

Emoutraspalavrasqueroqueocódigoaseguirfuncione:

//adicionaosdadosnobancoMisteriobd=newMisterio();bd.adiciona("meunome","meuemail","meuendereço",meuCalendar);

Tem algo estranho nesse código. Repare que todos os parâmetros que estamos passando são asinformaçõesdocontato.Secontatotivesse20atributos,passaríamos20parâmetros?JavaéorientadoaStrings?Vamostentarnovamente:emoutraspalavrasqueroqueocódigoaseguirfuncione:

//adicionaumcontatonobancoMisteriobd=newMisterio();

//métodomuitomaiselegantebd.adiciona(contato);

Tentaremoschegaraocódigoanterior:seriamuitomelhoremaiselegantepoderchamarumúnicométodoresponsávelpelainclusão,certo?

publicclassTestaInsere{

publicstaticvoidmain(String[]args){

//prontoparagravarContatocontato=newContato();contato.setNome("Caelum");contato.setEmail("[email protected]");contato.setEndereco("R.Vergueiro3185cj87");contato.setDataNascimento(Calendar.getInstance());

//gravenessaconexão!!!Misteriobd=newMisterio();

//métodoelegantebd.adiciona(contato);

System.out.println("Gravado!");}}

Ocódigoanteriorjámostraopoderquealcançaremos:atravésdeumaúnicaclasseseremoscapazesdeacessarobancodedadose,maisainda,somenteatravésdessaclasseserápossívelacessarosdados.

Estaideia,inocenteàprimeiravista,écapazdeisolartodooacessoabancoemclassesbemsimples,

.

Page 32: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

cujainstânciaéumobjetoresponsávelporacessarosdados.DaresponsabilidadedesteobjetosurgiuonomedeDataAccessObjectousimplesmenteDAO,umdosmaisfamosospadrõesdeprojeto(designpattern).

Oque faltaparao códigoacima funcionar éumaclasse chamadaContatoDao comummétodochamadoadiciona.Vamoscriarumaqueseconectaaobancoaoconstruirmosumainstânciadela:

publicclassContatoDao{

//aconexãocomobancodedadosprivateConnectionconnection;

publicContatoDao(){this.connection=newConnectionFactory().getConnection();}}

Agora que todo ContatoDao possui uma conexão com o banco, podemos focar no métodoadiciona, que recebe um Contato como argumento e é responsável por adicioná-lo através decódigoSQL:

publicvoidadiciona(Contatocontato){Stringsql="insertintocontatos"+"(nome,email,endereco,dataNascimento)"+"values(?,?,?,?)";

try{//preparedstatementparainserçãoPreparedStatementstmt=con.prepareStatement(sql);

//setaosvalores

stmt.setString(1,contato.getNome());stmt.setString(2,contato.getEmail());stmt.setString(3,contato.getEndereco());stmt.setDate(4,newDate(contato.getDataNascimento().getTimeInMillis()));

//executastmt.execute();stmt.close();}catch(SQLExceptione){thrownewRuntimeException(e);}}

Encapsulamos a SQLException em uma RuntimeException mantendo a ideia anterior daConnectionFactorydedesacoplarocódigodeAPIdeJDBC.

.

Page 33: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.

CasadoCódigo,LivrosdeTecnologia.

1. CrieaclassedeContatonopacotebr.com.caelum.jdbc.modelo.ElaseránossoJavaBeanpararepresentaraentidadedobanco.Deveráterid,nome,email,endereçoeumadatadenascimento.

Coloqueosatributosnaclasseegereosgettersesettersparacadaatributo:

publicclassContato{privateLongid;privateStringnome;privateStringemail;privateStringendereco;privateCalendardataNascimento;}

Dica:useoatalhodoEclipseparagerarosgettersesetters.AperteCtrl+3,digiteggasqueéaabreviaçãodeGenerategettersandsetterseselecionetodososgettersesetters.

Seuslivrosdetecnologiaparecemdoséculopassado?

2.11EXERCÍCIOS:JAVABEANSECONTATODAO

.

Page 34: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

2. Vamos desenvolver nossa classe de DAO. Crie a classe ContatoDao no pacotebr.com.caelum.jdbc.dao. Seu papel será gerenciar a conexão e inserir Contatos no banco dedados.

Paraaconexão,vamoscriá-lanoconstrutoresalvaremumatributo:

publicclassContatoDao{

//aconexãocomobancodedadosprivateConnectionconnection;

publicContatoDao(){this.connection=newConnectionFactory().getConnection();}

}

UseoEclipseparaajudarcomosimports!(atalhoCtrl+Shift+O)

O próximo passo é criar o método de adição de contatos. Ele deve receber um objeto do tipo

.

Page 35: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Contato como argumento e encapsular totalmente o trabalho com o banco de dados.Internamente,useumPreparedStatementcomovimosnaaulaparaexecutaroSQL:

publicvoidadiciona(Contatocontato){Stringsql="insertintocontatos"+"(nome,email,endereco,dataNascimento)"+"values(?,?,?,?)";

try{//preparedstatementparainserçãoPreparedStatementstmt=connection.prepareStatement(sql);

//setaosvaloresstmt.setString(1,contato.getNome());stmt.setString(2,contato.getEmail());stmt.setString(3,contato.getEndereco());stmt.setDate(4,newDate(contato.getDataNascimento().getTimeInMillis()));

//executastmt.execute();stmt.close();}catch(SQLExceptione){thrownewRuntimeException(e);}}

ATENÇÃO:Lembre-sede importar as classesdeSQLdopacotejava.sql, inclusive a classeDate!

3. ParatestarnossoDAO,desenvolvaumaclassedetestescomométodomain. Por exemplo, umachamadaTestaInserenopacotebr.com.caelum.jdbc.teste.GereomainpeloEclipse.

Onossoprogramadetestesdeve,dentrodomain,criarumnovoobjetoContatocomdadosdetesteechamaranovaclasseContatoDaoparaadicioná-loaobancodedados:

//prontoparagravarContatocontato=newContato();contato.setNome("Caelum");contato.setEmail("[email protected]");contato.setEndereco("R.Vergueiro3185cj57");contato.setDataNascimento(Calendar.getInstance());

//gravenessaconexão!!!ContatoDaodao=newContatoDao();

//métodoelegantedao.adiciona(contato);

System.out.println("Gravado!");

Executeseuprogramaevejasetudocorreubem.

4. Verifiqueseocontatofoiadicionado.Abraoterminaledigite:

mysql-uroot-pusefj21;select*fromcontatos;

.

Page 36: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Lembrando de colocar a senha do usuário root informada pelo instrutor. exit para sair doconsoledoMySQL.

Parapesquisar tambémutilizamosa interfacePreparedStatement paramontarnosso comandoSQL. Mas como uma pesquisa possui um retorno (diferente de uma simples inserção), usaremos ométodoexecuteQueryqueretornatodososregistrosdeumadeterminadaquery.

OobjetoretornadoédotipoResultSetdoJDBC,oquenospermitenavegarporseusregistrosatravésdométodonext.Essemétodoretornaráfalsequandochegaraofimdapesquisa,portantoeleénormalmenteutilizadoparafazerumlaçonosregistros:

//pegaaconexãoeoStatementConnectioncon=newConnectionFactory().getConnection();PreparedStatementstmt=con.prepareStatement("select*fromcontatos");

//executaumselectResultSetrs=stmt.executeQuery();

//iteranoResultSetwhile(rs.next()){}

rs.close();stmt.close();con.close();

Pararetornarovalordeumacolunanobancodedados,bastachamarumdosmétodosget doResultSet,dentreosquais,omaiscomum:getString.

//pegaaconexãoeoStatementConnectioncon=newConnectionFactory().getConnection();PreparedStatementstmt=con.prepareStatement("select*fromcontatos");

//executaumselectResultSetrs=stmt.executeQuery();

//iteranoResultSetwhile(rs.next()){Stringnome=rs.getString("nome");Stringemail=rs.getString("email")

System.out.println(nome+"_"+email);}

stmt.close();con.close();

2.12FAZENDOPESQUISASNOBANCODEDADOS

.

Page 37: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

RECURSOAVANÇADO:OCURSOR

Assimcomoo cursordobancodedados, só é possívelmoverparaopróximo registro.ParapermitirumprocessodeleituraparatrásénecessárioespecificarnaaberturadoResultSetquetalcursordeveserutilizado.

Mas, novamente, podemos aplicar as ideias deDAO e criar ummétodogetLista() no nossoContatoDao . Mas o que esse método retornaria? Um ResultSet ? E teríamos o código demanipulaçãodeResultSetespalhadoportodoocódigo?VamosfazernossogetLista() devolveralgomaisinteressante,umalistadeContato:

PreparedStatementstmt=this.connection.prepareStatement("select*fromcontatos");ResultSetrs=stmt.executeQuery();

List<Contato>contatos=newArrayList<Contato>();

while(rs.next()){

//criandooobjetoContatoContatocontato=newContato();contato.setNome(rs.getString("nome"));contato.setEmail(rs.getString("email"));contato.setEndereco(rs.getString("endereco"));

//montandoadataatravésdoCalendarCalendardata=Calendar.getInstance();data.setTime(rs.getDate("dataNascimento"));contato.setDataNascimento(data);

//adicionandooobjetoàlistacontatos.add(contato);}

rs.close();stmt.close();

returncontatos;

1. CrieométodogetListanaclasseContatoDao.ImporteListdejava.util:

publicList<Contato>getLista(){try{List<Contato>contatos=newArrayList<Contato>();PreparedStatementstmt=this.connection.prepareStatement("select*fromcontatos");ResultSetrs=stmt.executeQuery();

while(rs.next()){//criandooobjetoContato

2.13EXERCÍCIOS:LISTAGEM

.

Page 38: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Contatocontato=newContato();contato.setId(rs.getLong("id"));contato.setNome(rs.getString("nome"));contato.setEmail(rs.getString("email"));contato.setEndereco(rs.getString("endereco"));

//montandoadataatravésdoCalendarCalendardata=Calendar.getInstance();data.setTime(rs.getDate("dataNascimento"));contato.setDataNascimento(data);

//adicionandooobjetoàlistacontatos.add(contato);}rs.close();stmt.close();returncontatos;}catch(SQLExceptione){thrownewRuntimeException(e);}}

2. VamosusarométodogetListaparalistartodososcontatosdonossobancodedados.

CrieumaclassechamadaTestaListacomummétodomain:

CrieumContatoDao:

ContatoDaodao=newContatoDao();

ListeoscontatoscomoDAO:

List<Contato>contatos=dao.getLista();

Iterenessalistaeimprimaasinformaçõesdoscontatos:

for(Contatocontato:contatos){System.out.println("Nome:"+contato.getNome());System.out.println("Email:"+contato.getEmail());System.out.println("Endereço:"+contato.getEndereco());System.out.println("DatadeNascimento:"+contato.getDataNascimento().getTime()+"\n");}

3. RodeoprogramaanteriorclicandoemRun>Runas>JavaApplication(aproveiteparaaprenderatecladeatalhoparaexecutaraaplicação).

.

Page 39: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende

Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!

ConheçaaAluraCursosOnline.

Assim como o MySQL existem outros bancos de dados gratuitos e opensource na internet. OHSQLDBéumbancodesenvolvidoemJavaquepodeseracopladoaqualqueraplicaçãoeliberaoclientedanecessidadedebaixarqualquerbancodedadosantesdainstalaçãodeumprodutoJava!

OHibernate tomoucontadomercado e virou febremundialpoisnão se faznecessário escreverumalinhadecódigoSQL!

SeumprojetonãousanenhumadastecnologiasdeORM(ObjectRelationalMapping)disponíveis,omínimoaserfeitoéseguiroDAO.

1. A impressão da data de nascimento ficou um pouco estranha. Para formatá-la, pesquise sobre aclasseSimpleDateFormat.

2. Crie uma classe chamadaDAOException que estenda de RuntimeException e utilize-a no seuContatoDao.

3. Usecláusulaswherepararefinarsuapesquisanobancodedados.Porexemplo:wherenomelike'C%'

4. Crieométodopesquisarquerecebeumid(int)eretornaumobjetodotipoContato.

1. Façaconexõesparaoutrostiposdebancodedadosdisponíveis.

Agoraquevocê jásabeusaroPreparedStatementparaexecutarqualquertipodecódigoSQLe

Agoraéamelhorhoradeaprenderalgonovo

2.14UMPOUCOMAIS...

2.15EXERCÍCIOSOPCIONAIS

Desafios

2.16OUTROSMÉTODOSPARAOSEUDAO

.

Page 40: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

ResultSetparareceberosdadosretornadosdasuapesquisaficasimples,porémmaçante,escreverocódigodediferentesmétodosdeumaclassetípicadeDAO.

Vejaprimeiroométodoaltera,querecebeumcontatocujosvaloresdevemseralterados:

publicvoidaltera(Contatocontato){Stringsql="updatecontatossetnome=?,email=?,endereco=?,"+"dataNascimento=?whereid=?";try{PreparedStatementstmt=connection.prepareStatement(sql);stmt.setString(1,contato.getNome());stmt.setString(2,contato.getEmail());stmt.setString(3,contato.getEndereco());stmt.setDate(4,newDate(contato.getDataNascimento().getTimeInMillis()));stmt.setLong(5,contato.getId());stmt.execute();stmt.close();}catch(SQLExceptione){thrownewRuntimeException(e);}}

Nãoexistenadadenovonaslinhasacima.Umaexecuçãodequery!Simples,não?

Ocódigopararemoção:começacomumaquerybaseadaemumcontato,masusasomenteoiddeleparaexecutaraquerydotipodelete:

publicvoidremove(Contatocontato){try{PreparedStatementstmt=connection.prepareStatement("delete"+"fromcontatoswhereid=?");stmt.setLong(1,contato.getId());stmt.execute();stmt.close();}catch(SQLExceptione){thrownewRuntimeException(e);}}

Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.

CasadoCódigo,ebookcompreçodeebook.

EditoraCasadoCódigocomlivrosdeumaformadiferente

.

Page 41: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

1. AdicioneométodoparaalterarcontatonoseuContatoDao.

publicvoidaltera(Contatocontato){Stringsql="updatecontatossetnome=?,email=?,"+"endereco=?,dataNascimento=?whereid=?";

try{PreparedStatementstmt=connection.prepareStatement(sql);stmt.setString(1,contato.getNome());stmt.setString(2,contato.getEmail());stmt.setString(3,contato.getEndereco());stmt.setDate(4,newDate(contato.getDataNascimento().getTimeInMillis()));stmt.setLong(5,contato.getId());stmt.execute();stmt.close();}catch(SQLExceptione){thrownewRuntimeException(e);}}

2. AdicioneométodopararemovercontatonoseuContatoDao

publicvoidremove(Contatocontato){try{PreparedStatementstmt=connection.prepareStatement("deletefromcontatoswhereid=?");stmt.setLong(1,contato.getId());stmt.execute();stmt.close();}catch(SQLExceptione){thrownewRuntimeException(e);}}

3. Useosmétodoscriadosanteriormenteparafazertestescomoseubancodedados:atualizeeremovaumcontato.

4. CrieumaclassechamadaFuncionariocomoscamposid(Long),nome,usuarioesenha(String).5. Crieumatabelanobancodedadoschamadafuncionarios.6. CrieumaclasseDAOparaFuncionario.7. Use-aparainstanciarnovosfuncionáriosecolocá-losnoseubanco.

2.17EXERCÍCIOSOPCIONAIS-ALTERAREREMOVER

.

Page 42: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO3

"Ensinaréaprenderduasvezes."--JosephJoubert

Aotérminodessecapítulo,vocêserácapazde:

EntenderoqueéoJavaEnterpriseEdition;DiferenciarumServidordeAplicaçãodeumServletContainer;InstalarumServletContainercomooApacheTomcat;ConfigurarumServletContainerdentrodoEclipse.

As aplicaçõesWeb de hoje em dia já possuem regras de negócio bastante complicadas. Codificaressasmuitasregrasjárepresentamumgrandetrabalho.Alémdessasregras,conhecidascomorequisitosfuncionais de uma aplicação, existem outros requisitos que precisam ser atingidos através da nossainfraestrutura:persistênciaembancodedados, transação,acessoremoto,webservices,gerenciamentode threads, gerenciamento de conexões HTTP, cache de objetos, gerenciamento da sessão web,balanceamentodecarga,entreoutros.Sãochamadosderequisitosnão-funcionais.

Seformostambémosresponsáveisporescrevercódigoquetratedessesoutrosrequisitos,teríamosmuitomaistrabalhoafazer.Tendoissoemvista,aSuncriouumasériedeespecificaçõesque,quandoimplementadas, podem ser usadas por desenvolvedores para tirar proveito e reutilizar toda essainfraestruturajápronta.

OJavaEE(JavaEnterpriseEdition)consistedeumasériedeespecificaçõesbemdetalhadas,dandouma receita de como deve ser implementado um software que faz cada um desses serviços deinfraestrutura.

Veremosnodecorrerdessecursováriosdessesserviçosecomoutilizá-los,focandonoambientededesenvolvimentowebatravésdo JavaEE.Veremos tambémconceitosmuito importantes,paradepoisconceituartermosfundamentaiscomoservidordeaplicaçãoecontainers.

PorqueaSunfazisso?Aideiaéquevocêpossacriarumaaplicaçãoqueutilizeessesserviços.Comoesses serviços são bem complicados, você não perderá tempo implementando essa parte do sistema.Existemimplementaçõestantoopensourcequantopagas,ambasdeboaqualidade.

OQUEÉJAVAEE?

3.1COMOOJAVAEEPODETEAJUDARAENFRENTARPROBLEMAS

.

Page 43: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Algum dia, você pode querer trocar essa implementação atual por uma que é mais rápida emdeterminadospontos,queusemenosmemória,etc.Fazendoessamudançadeimplementaçãovocênãoprecisará alterar seu software, já que o Java EE é uma especificaçãomuito bem determinada. O quemuda é a implementação da especificação: você tem essa liberdade, não está preso a um código e aespecificaçãogarantequesuaaplicaçãofuncionarácomaimplementaçãodeoutrofabricante.Esseéumatrativomuitograndeparagrandesempresasegovernos,quequeremsempreevitarovendorlock-in:expressãousadaquandovocêestápresosemprenasmãosdeumúnicofabricante.

ONDEENCONTRARASESPECIFICAÇÕES

O grupo responsável por gerir as especificações usa o site do Java Community Process:http://www.jcp.org/

Lá você pode encontrar tudo sobre as Java Specification Requests (JSR), isto é, os novospedidosdebibliotecaseespecificaçõesparaoJava,tantoparaJavaSE,quantoEEeoutros.

SobreoJavaEE,vocêpodeencontrarem:http://java.sun.com/javaee/

J2EE

OnomeJ2EEerausadonasversõesmaisantigas,atéa1.4.Hoje,onomecorretoéJavaEE,porumaquestãodemarketing,masvocêaindavaiencontrarmuitasreferênciasaoantigotermoJ2EE.

Querendoaprenderaindamaissobre?Esclarecerdúvidasdosexercícios?Ouvirexplicaçõesdetalhadascomuminstrutor?ACaelum oferece o cursoFJ-21 presencial nas cidades de São Paulo, Rio deJaneiroeBrasília,alémdeturmasincompany.

ConsulteasvantagensdocursoJavaparaDesenvolvimentoWeb

VocêpodetambémfazerocursoFJ-21dessaapostilanaCaelum

3.2ALGUMASESPECIFICAÇÕESDOJAVAEE

.

Page 44: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

AsAPIsaseguirsãoasprincipaisdentreasdisponibilizadaspeloJavaEnterprise:

JavaServerPages(JSP),JavaServlets,JavaServerFaces(JSF)(trabalharparaaWeb,ondeéfocadoestecurso)

Enterprise Javabeans Components (EJB) e Java Persistence API (JPA). (objetos distribuídos,clusters,acessoremotoaobjetosetc)

JavaAPI forXMLWeb Services (JAX-WS), JavaAPI forXMLBinding (JAX-B) (trabalhar comarquivosxmlewebservices)

JavaAutenthicationandAuthorizationService(JAAS)(APIpadrãodoJavaparasegurança)

JavaTransactionAPI(JTA)(controledetransaçãonocontêiner)

JavaMessageService(JMS)(trocademensagensassíncronas)

JavaNamingandDirectoryInterface(JNDI)(espaçodenomeseobjetos)

JavaManagementExtensions(JMX)(administraçãodasuaaplicaçãoeestatísticassobreamesma)

AúltimaversãodisponíveldaespecificaçãodoJavaEEéaversão7,lançadaem12dejunhode2013.É uma versão aindamuito recente, com poucas ferramentas e servidores disponíveis. A versãomaisusadanomercadoéaversão6,de2009.Estecursoéfocadonaversão6quevocêencontraránomercadoe jáapresentandoasnovidadesdonovoJavaEE7quedeveganharespaçonomercadonospróximosanos.

Neste curso FJ-21, atacamos especialmente JSP e Servlets. No curso FJ-26, estuda-se comprofundidadeJSFcomCDIeJBossSeam.NoFJ-25éapresentadoemdetalheJPAcomHibernateeoEJB.NoFJ-36,estuda-seasespecificaçõesmaisrelacionadasasistemasdealtodesempenho:EJB,JNDI,JMS,JAX-BalémdeWebServices(JAX-WSeJAX-RS).

JSPeServletssãosemdúvidaasespecificaçõesessenciaisquetododesenvolvedorJavavaiprecisarparadesenvolvercomaWeb.MesmousandoframeworksebibliotecasquefacilitamotrabalhoparaaWeb, conhecer bem essas especificações é certamente um diferencial, e fará com que você entendamotivaçõesedificuldades,auxiliandonatomadadedecisõesarquiteturaisededesign.

Como vimos, o Java EE é um grande conjunto de especificações. Essas especificações, quandoimplementadas, vão auxiliar bastante o desenvolvimento da sua aplicação, pois você não precisará sepreocuparcomgrandepartedecódigodeinfraestrutura,quedemandariamuitotrabalho.

Como fazer o "download do Java EE"? O Java EE é apenas um grande PDF, uma especificação,detalhando quais especificações fazem parte deste. Para usarmos o software, é necessário fazer o

3.3SERVIDORDEAPLICAÇÃO

.

Page 45: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

downloaddeumaimplementaçãodessasespecificações.

Existemdiversasdessasimplementações.Jáqueessesoftwaretempapeldeservirsuaaplicaçãoparaauxiliá-la com serviços de infraestrutura, esse software ganha o nome de servidor de aplicação. AprópriaSun/Oracledesenvolveumadessas implementações,oGlassfishqueéopensourceegratuito,porémnãoéolíderdemercadoapesardeganharforçanosúltimostempos.

ExistemdiversosservidoresdeaplicaçãofamososcompatíveiscomaespecificaçãodoJ2EE1.4,JavaEE5ealgunsjádoJavaEE6.OJBosséumdoslíderesdomercadoetemavantagemdesergratuitoeopensource.AlgunssoftwaresimplementamapenasumapartedessasespecificaçõesdoJavaEE,comooApacheTomcat,quesóimplementaJSPeServlets(comodissemos,duasdasprincipaisespecificações),portantonão é totalmente correto chamá-lode servidor de aplicação.Apartir do JavaEE 6, existe otermo"applicationserverwebprofile",parapodersereferenciaraservidoresquenãooferecemtudo,masumgrupomenordeespecificações,consideradasessenciaisparaodesenvolvimentoweb.

Você pode ver uma lista de servidores Java EE 5 aqui:http://java.sun.com/javaee/overview/compatibility-javaee5.jsp

E Java EE 6 aqui, onde a lista ainda está crescendo:http://java.sun.com/javaee/overview/compatibility.jsp

Algunsdosservidoresdeaplicaçãomaisconhecidosdomercado:

Oracle/Sun,GlassFishServerOpenSourceEdition4.0,gratuito,JavaEE7;RedHat,JBossApplicationServer7.x,gratuito,JavaEE6;Apache,ApacheGeronimo,gratuito,JavaEE6(nãocertificado);Oracle/BEA,OracleWebLogicServer8.x,JavaEE6;IBM,IBMWebSphereApplicationServer,JavaEE6;SAP,SAPNetWeaverApplicationServerouSAPWebApplicationServer,JavaEE6WebProfile;

Nos cursos da Caelum utilizamos o Apache Tomcat e o RedHat JBoss, mas todo conhecimentoadquiridoaquipodeseraplicadocomfacilidadeparaosoutrosservidorescompatíveis,mudandoapenasaformadeconfigurá-los.

NocursoFJ-36,estuda-seprofundamentealgumasdasoutrastecnologiasenvolvidasnoJavaEE:oEJB,oJMS,oJAX-WSparaWebServiceseoJNDI.

O Java EE possui várias especificações, entre elas, algumas específicas para lidar com odesenvolvimentodeumaaplicaçãoWeb:

Servlet

3.4SERVLETCONTAINER

.

Page 46: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

JSPJSTLJSF

UmServletContaineréumservidorquesuportaessasfuncionalidades,masnãonecessariamenteoJavaEEWebProfilenemoJavaEEcompleto.ÉindicadoaquemnãoprecisadetudodoJavaEEeestáinteressadoapenasnaparteweb(boapartedasaplicaçõesdemédioporteencaixam-senessacategoria).

Háalgunsservletcontainersfamososnomercado.OmaisfamosoéoApacheTomcat,masháoutroscomooJetty,quenósdaCaelumusamosmuitoemprojetoseoGoogleusaemseucloudGoogleAppEngine.

Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.

CasadoCódigo,LivrosdeTecnologia.

ParaprepararoTomcatnaCaelum,sigaosseguintespassos:

1. Entrenapasta21doDesktopeselecioneoarquivodoapache-tomcat-7.x;

2. DêdoiscliquesparaabriroArchiveManagerdoLinux;

Seuslivrosdetecnologiaparecemdoséculopassado?

3.5EXERCÍCIOS:PREPARANDOOTOMCAT

.

Page 47: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

3. CliqueemExtract;4. EscolhaoseuDesktopecliqueemextract;

5. Oresultadoéumapastachamadaapache-tomcat-7.x.Pronto,otomcatjáestáinstalado.

3.6PREPARANDOOTOMCATEMCASA

.

Page 48: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Baixe o Tomcat 7 em http://tomcat.apache.org/ na página de downloads da versão queescolher,vocêprecisadeuma"BinaryDistribution".Mesmonowindows,dêpreferênciaaversão .zip,para você entendermelhor o processo de inicialização do servidor.A versão executável é apenas umwrapperparaexecutaraJVM,jáqueoTomcaté100%Java.

OTomcatfoipormuitotempoconsideradoimplementaçãopadrãoereferênciadasnovasversõesdaAPIdeservlets.EletambéméoservletcontainerpadrãoutilizadopeloJBoss.Elecontinuaemprimeiraposiçãonomercado,mashojetemesselugardisputadopeloJettyepeloGrizzly(esseúltimoéoservletcontainerquefazpartedoservidordeaplicaçãodaOracle/Sun,oGlassfish).

Entrenodiretóriodeinstalaçãoeexecuteoscriptstartup.sh:

cdapache-tomcat<TAB>/bin./startup.sh

Entrenodiretóriodeinstalaçãodotomcaterodeoprogramashutdown.sh:

cdapache-tomcat<TAB>/bin./shutdown.sh

AprenderemosfuturamentecomoiniciarocontainerdedentrodopróprioEclipse,porcomodidadeeparafacilitarousododebug.

ParainstalaroTomcatnoWindowsbastaexecutaroarquivo.exequepodeserbaixadonositedoTomcat(comofalamos,dêpreferênciaaozip).Depoisdisso,vocêpodeusarosscriptsstartup.bateshutdown.bat,analogamenteaosscriptsdoLinux.

TudooquevamosdesenvolvernestecursofuncionaemqualquerambientecompatívelcomoJavaEnterpriseEdition,sejaoLinux,WindowsouMacOS.

O Jetty é uma outra implementação criada pela MortBay (http://jetty.mortbay.org) de ServletContainereHTTPServer.

Pequeno e eficiente, ele é uma opção ao Tomcat bastante utilizada devido a algumas de suascaracterísticas.Especialmente:

facilmenteembarcável;escalável;"plugabilidade":éfáciltrocarasimplementaçõesdosprincipaiscomponentesdaAPI.

O Jetty tambémcostuma implementar, antesdoTomcat, ideiasdiferentesqueaindanãoestãonaAPIdeservletsdoJavaEE.Umadessasimplementaçõespioneirasfoidousodoschamadosconectores

TomcatnoWindows

3.7OUTRAOPÇÃO:JETTY

.

Page 49: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

NIO,porexemplo,quepermitiramumaperformancemelhorparaousodeAJAX.

O GUJ.com.br roda com o Jetty, em uma instalação customizada que pode ser lida aqui:http://blog.caelum.com.br/2008/06/27/melhorando-o-guj-jetty-nio-e-load-balancing/

Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende

Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!

ConheçaaAluraCursosOnline.

Sempre que estamos trabalhando como desenvolvimento de uma aplicação queremos ser omaisprodutivos possível, e não é diferente com uma aplicação web. Uma das formas de aumentar aprodutividade do desenvolvedor é utilizar uma ferramenta que auxilie no desenvolvimento e o tornemaiságil,nonossocaso,umaIDE.

OWTP,WebToolsPlatform,éumconjuntodepluginsparaoEclipsequeauxiliaodesenvolvimentode aplicações Java EE, em particular, de aplicaçõesWeb. Contém desde editores para JSP, CSS, JS eHTMLatéperspectivasejeitosderodarservidoresdedentrodoEclipse.

Estepluginvainosajudarbastantecomcontent-assistseatalhosparatornarodesenvolvimentoWebmaiseficiente.

AversãodedownloadEclipseIDEforJavaEEDevelopersjávemporpadrãocomoplugin.Sendoassim,bastairnositedoEclipsee:

Abraapáginawww.eclipse.org/downloads;BaixeoEclipseIDEforJavaEEDevelopers;Descompacteoarquivoepronto.

Agoraéamelhorhoradeaprenderalgonovo

3.8INTEGRANDOOTOMCATNOECLIPSE

3.9OPLUGINWTP

3.10EXERCÍCIOS:CONFIGURANDOOTOMCATNOECLIPSE

.

Page 50: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

VamosprimeiroconfigurarnoWTPoservidorTomcatqueacabamosdedescompactar.

1. MudeaperspectivadoEclipseparaJava(enãoJavaEE,porenquanto).Paraisso,vánocantodireitosuperiorecliquenobotão:

DepoisselecioneJava:

2. AbraaViewdeServersnaperspectivaatual.AperteCtrl+3edigiteServers:

.

Page 51: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

3. CliquecomobotãodireitodentrodaabaServerseváemNew>Server:

4. SelecioneoApacheTomcat7.0ecliqueemNext:

5. Napróximatela,selecioneodiretórioondevocêdescompactouoTomcatecliqueemFinish:

.

Page 52: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

6. Porpadrão,oWTPgerenciatodooTomcatparanósenãopermitequeconfiguraçõessejamfeitasporforadoEclipse.Parasimplificar,vamosdesabilitarissoedeixaroTomcatnomodopadrãodopróprioTomcat.NaabaServers,dêdoiscliquesnoservidorTomcatqueumateladeconfiguraçãoseabrirá.LocalizeaseçãoServerLocations.Reparequeaopçãouseworkspacemetadataestámarcada.MarqueaopçãoUseTomcatinstallation:Salveefecheessatela.

7. SelecioneoservidorqueacabamosdeadicionarecliqueemStart(íconeplayverdenaviewservers):

.

Page 53: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

8. AbraonavegadoreacesseaURLhttp://localhost:8080/DeveaparecerumatelademensagemdoTomcat.Pronto!OWTPestáconfiguradopararodarcomoTomcat!

Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.

CasadoCódigo,ebookcompreçodeebook.

EditoraCasadoCódigocomlivrosdeumaformadiferente

.

Page 54: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO4

"Sãomuitososqueusamarégua,maspoucososinspirados."--Platão

Aotérminodessecapítulo,vocêserácapazde:

criarumnovoprojetoWebnoEclipse;compreenderquaissãoosdiretóriosimportantesdeumaaplicaçãoWeb;compreenderquaissãoosarquivosimportantesdeumaaplicaçãoWeb;entenderondecolocarsuaspáginasearquivosestáticos.

Nesse capítulo veremos como, passo a passo, criar um novo projetoWeb no Eclipse usando osrecursosdoEclipse JavaEE.Dessa formanãoprecisarmos iniciaro servlet containernamão, alémdepermitiraconfiguraçãodeumprojeto,desuasbibliotecas,edeseudebug,deumamaneirabemmaissimplesdoquesemele

AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,

Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex-aluno daCaelumtem15%dedescontonestelink!

ConheçaoscursosonlineAlura.

1. VáemNew>ProjecteselecioneDynamicWebProjectecliqueNext:

NOVOPROJETOWEBUSANDOECLIPSE

4.1NOVOPROJETO

JáconheceoscursosonlineAlura?

4.2EXERCÍCIOS:NOVOPROJETOWEB

.

Page 55: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

2. Coloqueonomedoprojetocomofj21-agenda,verifiqueseoTargetruntimeestáapontandoparaaversãodoTomcatqueacabamosdeconfigurareseoDynamicwebmoduleversionestáconfiguradopara3.0.DepoiscliqueNext.ATENÇÃO:NÃOCLIQUEEMFinishAINDA!!!

3. CliqueemNextnaconfiguraçãodaspastas:

.

Page 56: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

4. NaconfiguraçãoWebmodulemarqueoboxGenerateweb.xmldeploymentdescriptorecliqueemFinish:

5. SeforperguntadosobreamudançaparaaperspectivaJavaEE,selecioneNão.

.

Page 57: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

6. O último passo é configurar o projeto para rodar noTomcat que configuramos.Na abaServers,cliquecomobotãodireitonoTomcateváemAddandRemove...:

7. Bastaselecionaronossoprojetofj21-agendaeclicaremAdd:

8. Dêumaolhadanaspastasqueforamcriadasenaestruturadonossoprojetonesseinstante.Vamosanalisá-laemdetalhes.

Olhebemaestruturadepastaseveráalgoparecidocomoquesegue:

4.3ANÁLISEDORESULTADOFINAL

.

Page 58: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

O diretório src já é velho conhecido. É onde vamos colocar nosso código fonte Java. Em umprojetonormaldoEclipse,essasclassesseriamcompiladasparaapastabin,masnoEclipseécostumeseusarapastabuildquevemosemnossoprojeto.

Nosso projeto será composto demuitas páginasWeb e vamos querer acessá-lo no navegador. Jásabemosqueo servidor é acessadopelohttp://localhost:8080,mas como seráquedizemosquequeremosacessaronossoprojetoenãooutrosprojetos?

No Java EE, trabalhamos com o conceito de contextosWeb para diferenciar sites ou projetosdistintosemummesmoservidor.Naprática,écomoumapastavirtualque,quandoacessada,remeteaalgumprojetoemquestão.

Porpadrão, oEclipse geraocontextname comomesmonomedoprojeto; nonosso caso, fj21-agenda.PodemosmudarissonahoradecriaroprojetoouposteriormenteindoemProject>Properties>WebProjectSettingsemudandoaopçãoContextRoot.Reparequenãoénecessárioqueonomedocontextosejaomesmonomedoprojeto.

Assim,paraacessaroprojeto,usaremosaURL:http://localhost:8080/fj21-agenda/

MasoqueseráquevaiaparecerquandoabrirmosessaURL?Seráqueveremostodooconteúdodoprojeto?Porexemplo, serápossívelacessarapastasrcqueestádentrodonossoprojeto?Tomaraquenão,afinaltodonossocódigofonteestálá.

Para solucionar isso, uma outra configuração é importante no Eclipse: oContentDirectory. Aoinvésdeabriracessoatudo,criamosumapastadentrodoprojetoedizemosqueelaéaraiz(root)doconteúdoaserexibidononavegador.NoEclipse,porpadrão,écriadaapastaWebContent,maspoderiaserqualqueroutrapastaconfiguradanacriaçãodoprojeto(outronomecomumdeseusaréweb).

Tudo que colocarmos na pasta WebContent será acessível na URL do projeto. Por exemplo, se

.

Page 59: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

queremosumapáginadeboasvindas:

http://localhost:8080/fj21-agenda/bemvindo.html

entãocriamosoarquivo:

fj21-agenda/WebContent/bemvindo.html

Repare também que dentro da WebContent há uma pasta chamada WEB-INF . Essa pasta éextremamente importante para qualquer projeto web Java EE. Ela contém configurações e recursosnecessáriosparanossoprojetorodarnoservidor.

Oweb.xmléoarquivoondeficaráarmazenadaasconfiguraçõesrelativasasuaaplicação,usaremosessearquivoembreve.

Porenquanto,abra-oevejasuaestrutura,atéentãobemsimples:

<?xmlversion="1.0"encoding="UTF-8"?><web-appxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee"xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"id="WebApp_ID"version="2.5">

<display-name>fj21-agenda</display-name>

<welcome-file-list><welcome-file>index.html</welcome-file><welcome-file>index.htm</welcome-file><welcome-file>index.jsp</welcome-file><welcome-file>default.html</welcome-file><welcome-file>default.htm</welcome-file><welcome-file>default.jsp</welcome-file></welcome-file-list></web-app>

ÉobásicogeradopelopróprioEclipse.Tudooqueelefazédefinironomedaaplicaçãoealistadearquivosacessadosquevãoserprocuradosporpadrão.Todasessasconfiguraçõessãoopcionais.

Repare ainda que há uma pasta chamada lib dentro daWEB-INF.Quase todos os projetosWebexistentes precisam usar bibliotecas externas, como por exemplo o driver doMySQL no nosso caso.Copiaremostodaselasparaessapasta lib.Comoessediretóriosóaceitabibliotecas,apenascolocamosnele arquivos .jar ou arquivos zip com classes dentro. Caso um arquivo com outra extensão sejacolocadonolib,eleseráignorado.

WEB-INF

.

Page 60: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

WEB-INF/LIB

O diretório lib dentro do WEB-INF pode conter todas as bibliotecas necessárias para aaplicação Web, evitando assim que o classpath da máquina que roda a aplicação precise seralterado.

Além do mais, cada aplicaçãoWeb poderá usar suas próprias bibliotecas com suas versõesespecíficas!Vocêvaiencontrarprojetosopensourcequesomentefornecemsuporteerespondemperguntas aqueles usuários que utilizam tal diretório para suas bibliotecas, portanto evite aomáximoousodoclasspathglobal.

Parasabermaissobreousodeclassloaderseclasspathglobal,vocêpodeprocurarnocapítulo2dolivroIntroduçãoàArquiteturaeDesigndeSoftware,publicadopelaEditoraCasadoCódigoepelaElsevier.

Há aindaumúltimodiretório, ocultonoEclipse, o importanteWEB-INF/classes. Para rodarmosnossaaplicaçãonoservidor,precisamosteracessoasclassescompiladas(nãonecessariamenteaocódigofonte).Por isso,nossos.class sãocolocadosnessapastadentrodoprojeto.EssepadrãoédefinidopelaespecificaçãodeServletsdoJavaEE.ReparequeoEclipsecompilanossasclassesnapastabuildedepoisautomaticamenteascopiaparaoWEB-INF/classes.

NotequeapastaWEB-INFémuitoimportanteecontémrecursosvitaisparaofuncionamentodoprojeto.Imagineseousuáriotiveracessoaessapasta!Códigoscompilados(facilmentedescompiláveis),bibliotecaspotencialmentesigilosas,arquivosdeconfiguraçãointernoscontendosenhas,etc.

Para que isso não aconteça, a pastaWEB-INF com esse nome especial é umapasta invisível aousuário final. Isso quer dizer que se alguém acessar a URL http://localhost:8080/fj21-agenda/WEB-INFveráapenasumapáginadeerro(404).

src-códigofonteJava(.java)build-ondeoEclipsecompilaasclasses(.class)WebContent-contentdirectory(páginas,imagens,cssetcvãoaqui)WebContent/WEB-INF/-pastaocultacomconfiguraçõeserecursosdoprojetoWebContent/WEB-INF/lib/-bibliotecas.jarWebContent/WEB-INF/classes/-arquivoscompiladossãocopiadosparacá

Resumofinaldaspastas

.

Page 61: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

META-INF

ApastaMETA-INFéopcionalmaségeradapeloEclipse.Éondeficaoarquivodemanifestocomousadoemarquivos.jar.

Para criarmos as nossas páginas, precisamos utilizar uma linguagemque consiga ser interpretadapelosnavegadores.EssalinguageméaHTML(HypertextMarkupLanguage).

Comoopróprionomediz,elaéumalinguagemdemarcação,oquesignificaqueelaécompostaportagsquedefinemocomportamentodapáginaqueseestácriando.Essastagsdizemcomoapáginaserávisualizada, através da definição dos componentes visuais que aparecerão na tela. É possível exibirtabelas,parágrafos,blocosdetexto,imagenseassimpordiante.

TodoarquivoHTMLdeveconteraextensão.html,eseuconteúdodeveestardentrodatag<html>.EmumHTMLbemformado,todasastagsquesãoabertastambémsãofechadas,dessaforma,todooseucódigonumarquivo .html ficarádentrode<html> e</html>.Alémdisso, podemos tambémdefiniralgunsdadosdecabeçalhosparanossapágina,comoporexemplo,otítuloqueserácolocadonajaneladonavegador,atravésdastags<head>e<title>:

<html><head><title>Títuloquevaiaparecernonavegador</title></head></html>

Para escrevermos algo que seja exibido dentro do navegador, no corpo da nossa página, bastacolocarmosatag<body>dentrode<html>,comoaseguir:

<html><body>Textoquevaiaparecernocorpodapágina</body></html>

4.4CRIANDONOSSASPÁGINASEHTMLBÁSICO

.

Page 62: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Querendoaprenderaindamaissobre?Esclarecerdúvidasdosexercícios?Ouvirexplicaçõesdetalhadascomuminstrutor?ACaelum oferece o cursoFJ-21 presencial nas cidades de São Paulo, Rio deJaneiroeBrasília,alémdeturmasincompany.

ConsulteasvantagensdocursoJavaparaDesenvolvimentoWeb

VamostestarnossasconfiguraçõescriandoumarquivoHTMLdeteste.

1. CrieoarquivoWebContent/index.htmlcomoseguinteconteúdo:

<html><head><title>Projetofj21-agenda</title></head><body><h1>Primeirapáginadoprojetofj21-agenda</h1></body></html>

2. Inicie(oureinicie)oTomcatclicandonobotãodeplaynaabaServers.

3. Acesse pelo navegador (nas máquinas da caelum existe um Firefox instalado):http://localhost:8080/fj21-agenda/index.html

Testetambémaconfiguraçãodowelcome-filenoweb.xml:http://localhost:8080/fj21-agenda/

SefosseocasodecriarumaaplicaçãowebsemutilizaroplugindoTomcat,precisaríamoscolocarnossaaplicaçãodentrodoTomcatmanualmente.

Dentro do diretório do Tomcat, há um diretório chamado webapps. Podemos colocar nossasaplicaçõesdentrodessediretório,cadaumadentrodeumdiretórioespecífico.Onomedodiretórioseráonomedocontextodaaplicação.

Por exemplo, para colocar nossa aplicação fj21-agenda no Tomcat manualmente, basta copiar oconteúdododiretórioWebContentparaumdiretóriochamado,porexemplo,agendadentrodesse

VocêpodetambémfazerocursoFJ-21dessaapostilanaCaelum

4.5EXERCÍCIOS:PRIMEIRAPÁGINA

4.6PARASABERMAIS:CONFIGURANDOOTOMCATSEMOPLUGIN

.

Page 63: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

diretóriowebappsdoTomcat.Pronto,oTomcatserviráanossaaplicaçãocomocontextoagenda.ParaqueoTomcatsirvanossaaplicaçãonocontexto/,bastacolocarnossaaplicaçãodentrodeumdiretóriochamadoROOT.

DevidoaofocodocursonãosernoHTML,nãomostraremosafundoastagsdoHTML.Noentanto,abaixoestáumalistacomalgumasdastagsmaiscomunsdoHTML:

h1 -h6:definecabeçalhos,doh1 aoh6, ondemenoronúmero,maior a importânciadocabeçalho;a:criaumlinkparaoutrapágina,ouparaalgumpontodamesmapágina;p:definequeotextodentrodelaestaráemumparágrafo;ul:criaumalistadeelementos;li:criaumnovoitemnumalistadeelementos;input:colocaumcontroledeformulárionatela(caixadetexto,botão,radiobuttonetc.)table:defineumatabela;tr:colocadadentrodeumtableparadefinirumalinhadatabela;td:colocadadentrodeumtrparadefinirumacélula;

TUTORIALDEHTML

Para um tutorial completo sobre HTML, recomendamos uma visita ao site da MozillaDeveloper Network, que possui referências das tags e exemplos de uso:https://developer.mozilla.org/pt-BR/docs/Web/HTML

Você também pode visitar o tutorial de HTML da W3schools.com:http://www.w3schools.com/html/

4.7ALGUMASTAGSHTML

.

Page 64: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.

CasadoCódigo,LivrosdeTecnologia.

Seuslivrosdetecnologiaparecemdoséculopassado?

.

Page 65: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO5

"Vivemostodossobomesmocéu,masnemtodostemosomesmohorizonte."--KonradAdenauer

Aotérminodessecapítulo,vocêserácapazde:

fazercomqueumaclassesejaacessívelvianavegador;criarpáginascontendoformulários;recebereconverterparâmetrosenviadosporumapágina;distinguirosmétodosHTTP;executarsuaslógicaseregrasdenegócio.

Quando aWeb surgiu, seu objetivo era a troca de conteúdos através, principalmente, de páginasHTMLestáticas.EramarquivosescritosnoformatoHTMLedisponibilizadosemservidoresparaseremacessadosnosnavegadores.Imagens,animaçõeseoutrosconteúdostambémeramdisponibilizados.

MaslogoseviuqueaWebtinhaumenormepotencialdecomunicaçãoeinteraçãoalémdaexibiçãodesimplesconteúdos.Paraatingiressenovoobjetivo,porém,páginasestáticasnãoseriamsuficientes.EraprecisoservirpáginasHTMLgeradasdinamicamentebaseadasnasrequisiçõesdosusuários.

Hoje,boapartedoqueseacessanaWeb(portais,blogs,homebankingsetc)ébaseadoemconteúdodinâmico.Ousuáriorequisitaalgoaoservidorque,porsuavez,processaessarequisiçãoedevolveumarespostanovaparaousuário.

Umadasprimeiras ideiaspara esses "geradoresdinâmicos"depáginasHTML foi fazero servidorWeb invocar umoutroprograma externo em cada requisiçãopara gerar oHTMLde resposta. Era ofamosoCGIquepermitiaescreverpequenosprogramasparaapresentarpáginasdinâmicasusando,porexemplo,Perl,PHP,ASPeatéCouC++.

Na plataforma Java, a primeira e principal tecnologia capaz de gerar páginas dinâmicas são asServlets, que surgiram no ano de 1997. Hoje, a versão mais encontrada no mercado é baseada nasversões2.x,maisespecificamentea2.4(partedoJ2EE1.4)ea2.5(partedoJavaEE5).Aúltimaversãodisponível é a versão 3.0 lançada em Dezembro de 2009 com o Java EE 6, e que vem sendogradativamenteadotadanomercado.

SERVLETS

5.1PÁGINASDINÂMICAS

.

Page 66: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende

Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!

ConheçaaAluraCursosOnline.

AsServlets são a primeira forma que veremos de criar páginas dinâmicas com Java.Usaremos apróprialinguagemJavaparaisso,criandoumaclassequeterácapacidadedegerarconteúdoHTML.Onome"servlet"vemdaideiadeumpequenoservidor(servidorzinho,eminglês)cujoobjetivoéreceberchamadasHTTP,processá-lasedevolverumarespostaaocliente.

Umaprimeiraideiadaservletseriaquecadaumadelaséresponsávelporumapágina,sendoqueelalêdadosdarequisiçãodoclienteerespondecomoutrosdados(umapáginaHTML,umaimagemGIFetc).ComonoJavatentamossemprequepossíveltrabalharorientadoaobjetos,nadamaisnaturalqueumaservletsejarepresentadacomoumobjetoapartirdeumaclasseJava.

Cada servlet é, portanto, um objeto Java que recebe tais requisições (request) e produz algo(response),comoumapáginaHTMLdinamicamentegerada.

OdiagramaabaixomostratrêsclientesacessandoomesmoservidoratravésdoprotocoloHTTP:

Agoraéamelhorhoradeaprenderalgonovo

5.2SERVLETS

.

Page 67: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

OcomportamentodasservletsquevamosvernestecapítulofoidefinidonaclasseHttpServletdopacotejavax.servlet.

AinterfaceServletéaquedefineexatamentecomoumaservletfunciona,masnãoéoquevamosutilizar,umavezqueelapossibilitaousodequalquerprotocolobaseadoemrequisiçõeserespostas,enãoespecificamenteoHTTP.

Paraescrevermosumaservlet,criamosumaclasseJavaqueestendaHttpServletesobrescrevaummétodochamadoservice.Essemétodoseráoresponsávelporatenderrequisiçõesegerarasrespostasadequadas.Suaassinatura:

protectedvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{...}

Reparequeométodorecebedoisobjetosquerepresentam,respectivamente,arequisiçãofeitapelousuário e a resposta que será exibida no final. Veremos que podemos usar esses objetos para obterinformaçõessobrearequisiçãoeparaconstruirarespostafinalparaousuário.

Nosso primeiro exemplo de implementação dométodo service não executa nada de lógica eapenasmostraumamensagemestáticadebemvindoparaousuário.Paraisso,precisamosconstruirarespostaqueaservletenviaráparaocliente.

É possível obter um objeto que represente a saída a ser enviada ao usuário através do métodogetWriterdavariávelresponse.E,apartirdisso,utilizarumPrintWriterparaimprimiralgonarespostadocliente:

publicclassOiMundoextendsHttpServlet{protectedvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{PrintWriterout=response.getWriter();

//escreveotextoout.println("<html>");out.println("<body>");out.println("Primeiraservlet");out.println("</body>");out.println("</html>");}}

Oúnicoobjetivoda servlet acima é exibir umamensagemHTML simplesparaosusuários que arequisitarem.MasnotecomoseriamuitofácilescreveroutroscódigosJavamaispoderososparagerarasStringsdoHTMLbaseadaseminformaçõesdinâmicasvindas,porexemplo,deumbancodedados.

.

Page 68: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

SERVLETXCGI

Diversasrequisiçõespodemserfeitasàmesmaservletaomesmotempoemumúnicoservidor.Porisso,elaémaisrápidaqueumprogramaCGIcomumquenãopermitiaisso.AespecificaçãodeservletscitaalgumasvantagensemrelaçãoaoCGI.

Ficanamemóriaentrerequisições,nãoprecisaserreinstanciada;OníveldesegurançaepermissãodeacessopodesercontroladoemJava;emCGI,cadaclienteérepresentadoporumprocesso,enquantoquecomServlets,cadaclienteérepresentadoporumalinhadeexecução.

Esse capítulo está focado na HttpServlet, um tipo que gera aplicaçõesWeb baseadas noprotocoloHTTP,masvalelembrarqueaAPInãofoicriadasomenteparaesteprotocolo,podendoserestendidaparaoutrosprotocolostambémbaseadosemrequisiçõeserespostas.

Acabamos de definir uma Servlet, mas como vamos acessá-la pelo navegador? Qual o endereçopodemos acessar para fazermos com que ela execute? O container não tem como saber essasinformações,anãoserquedigamosissoparaele.Paraisso,vamosfazerummapeamentodeumaURLespecíficaparaumaservletatravésdoarquivoweb.xml,queficadentrodoWEB-INF.

Uma vez que chamar a servlet pelo pacote e nome da classe acabaria criando URLs estranhas ecomplexas,écomummapear,porexemplo,umaservletcomonoexemplo,chamadaOiMundoparaonomeprimeiraServlet.

Começamoscomadefiniçãodaservletemsi,dentrodatag<servlet>:

<servlet><servlet-name>primeiraServlet</servlet-name><servlet-class>br.com.caelum.servlet.OiMundo</servlet-class></servlet>

Em seguida, mapeie nossa servlet para a URL /oi. Perceba que isso acontece dentro da tag<servlet-mapping> (mapeamentodeservlets)equevocê temque indicarqueestá falandodaquelaservletquedefinimoslogoacima:passamosomesmoservlet-nameparaomapeamento.

<servlet-mapping><servlet-name>primeiraServlet</servlet-name><url-pattern>/oi</url-pattern></servlet-mapping>

Portanto,sãonecessáriosdoispassosparamapearumaservletparaumaURL:

5.3MAPEANDOUMASERVLETNOWEB.XML

.

Page 69: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Definironomeeclassedaservlet;Usandoonomedaservlet,definiraURL.

AservletpodeseracessadaatravésdaseguinteURL:

http://localhost:8080/fj21-agenda/oi

Assim que o arquivoweb.xml e a classe da servlet de exemplo forem colocados nos diretórioscorretos,bastaconfiguraroTomcatparautilizarodiretóriodebasecomopadrãoparaumaaplicaçãoWeb.

Atag<url-pattern>tambémtedáaflexibilidadededisponibilizarumaservletatravésdeváriasURLsdeumcaminho,porexemploocódigoabaixofarácomquequalquerendereçoacessadodentrode/oisejainterpretadopelasuaservlet:

<servlet-mapping><servlet-name>primeiraServlet</servlet-name><url-pattern>/oi/*</url-pattern></servlet-mapping>

Você aindapode configurar "extensões"para as suas servlets, por exemplo, omapeamento abaixofarácomquesuaservletsejachamadaporqualquerrequisiçãoqueterminecom.php:

<servlet-mapping><servlet-name>primeiraServlet</servlet-name><url-pattern>*.php</url-pattern></servlet-mapping>

Reparequenãocriamosdiretórionenhumnanossaaplicação(excetoopacoteparaanossaclasseServlet).Ouseja,omapeamentodaservletnãotemrelaçãoalgumacomumdiretóriofísiconaaplicação.Essemapeamentoéapenasumnomeatribuído,virtual,queéutilizadoparaacessarmosaaplicação.

Maissobreourl-pattern

5.4AESTRUTURADEDIRETÓRIOS

.

Page 70: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.

CasadoCódigo,ebookcompreçodeebook.

1. Crie a servletOiMundo nopacotebr.com.caelum.servlet. Escolha omenuFile,New,Class(maisumavez,aproveiteparaaprenderteclasdeatalho).

EstendaHttpServlet:

publicclassOiMundoextendsHttpServlet{}

UtilizeoCTRL+SHIFT+OparaimportarHttpServlet.

Para escrever a estrutura dométodo service, dentro da classe, escreva apenas service e dêCtrl+espaço:oEclipsegerapravocêométodo.

EditoraCasadoCódigocomlivrosdeumaformadiferente

5.5EXERCÍCIOS:PRIMEIRASERVLET

.

Page 71: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

ATENÇÃO: Cuidado para escolher corretamente a versão de service que recebeHttpServletRequest/Response.

Aanotação@Overrideserveparanotificarocompiladorqueestamossobrescrevendoométodoservicedaclassemãe.Se,poracaso,errarmosonomedométodooutrocarmosaordemdosparâmetros,ocompiladorvaireclamarevocêvaiperceberoerroaindaemtempodecompilação.

Ométodogeradodeveseresse.Troqueosnomesdosparâmetrosarg0earg1comoabaixo:

@Overrideprotectedvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{

}

Escrevadentrodométodoservice sua implementação.Por enquanto, queremos apenasquenossaServletmonteumapáginaHTMLsimplesparatestarmos.

Cuidadoemtirarachamadaaosuper.serviceantesereparequeadeclaraçãodométodojáfoifeitanopassoanterior.

protectedvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{

PrintWriterout=response.getWriter();

out.println("<html>");out.println("<head>");out.println("<title>PrimeiraServlet</title>");out.println("</head>");out.println("<body>");out.println("<h1>OimundoServlet!</h1>");out.println("</body>");out.println("</html>");}

2. Abraoarquivoweb.xmlecliquenaabaSourcenaparteinferiordoeditordecódigo.Dentrodatag<web-app>,mapeieaURL /oiparaa servletOiMundo.Aproveite o autocompletardoEclipse ecuidadoaoescreveronomedaclasseedopacote.

.

Page 72: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

<servlet><servlet-name>servletOiMundo</servlet-name><servlet-class>br.com.caelum.servlet.OiMundo</servlet-class></servlet>

<servlet-mapping><servlet-name>servletOiMundo</servlet-name><url-pattern>/oi</url-pattern></servlet-mapping>

3. ReinicieoTomcatclicandonobotãoverdenaabaServers.

4. Testeaurlhttp://localhost:8080/fj21-agenda/oi

Existemdiversoserroscomunsnosexercíciosanteriores.Aquivãoalgunsdeles:

EsquecerdabarrainicialnoURLpattern:

<url-pattern>oi</url-pattern>

5.6ERROSCOMUNS

.

Page 73: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Nessecaso,umaexceçãoaconteceránomomentoemqueotomcatforinicializado:

Digitarerradoonomedopacotedasuaservlet:

<servlet-class>br.caelum.servlet.OiMundo</servlet-class>

.

Page 74: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Esquecerdecolocaronomedaclassenomapeamentodaservlet:

<servlet-class>br.com.caelum.servlet</servlet-class>

Como foi visto no exercício anterior, criar Servlets usando o Java EE 5 é um processo muitotrabalhoso. Um dos grandes problemas é que temos que configurar cada um de nossas Servlets noweb.xmlesequisermosacessaressaservletdemaneirasdiferentes,temosquecriarváriosmapeamentosparaamesmaservlet,oquepodecomotempotornar-seumproblemadevidoadifícilmanutenção.

NanovaespecificaçãoServlets3.0,quefazpartedoJavaEE6,podemosconfiguraramaneiracomovamosacessaranossaServletdemaneiraprogramática,utilizandoanotaçõessimples.

Demodogeral,nãoémaisprecisoconfigurarasnossasServletsnoweb.xml,sendosuficienteusaraanotação@WebServletapenas:

@WebServlet("/oi")publicclassOiServlet3extendsHttpServlet{...}

IssoéequivalenteaconfiguraraServletacimacomaurl-patternconfiguradacomo/oi.

Naanotação@WebServlet,podemoscolocaraindaumparâmetroopcionalchamadoname quedefineumnomeparaaServlet(equivalenteaoservlet-name).Senãodefinirmosesseatributo,porpadrão,onomedaServletéonomecompletodaclassedasuaServlet,tambémconhecidocomoFullyQualifiedName.

SequisermosquenossaServlet seja acessadoatravésde apenasumaURL, recomenda-sedefinir aURLdiretamentenoatributovaluecomonoexemploacima.MasseprecisarmosdefinirmaisdeumaURLparaacessaraServlet,podemosutilizaroatributourlPatternsepassarumvetordeURLs:

@WebServlet(name="MinhaServlet3",urlPatterns={"/oi","/ola"})publicclassOiServlet3extendsHttpServlet{...}

É bom reforçar que, mesmo a Servlet estando anotado com @WebServlet() , ele deveobrigatoriamenterealizarumextendsaclassejavax.servlet.http.HttpServlet.

5.7FACILIDADESDASSERVLETS3.0

.

Page 75: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

ARQUIVOWEB.XML

Dentro da tag <web-app> no web.xml, existe um novo atributo chamado metadata-complete.Nesseatributopodemosconfigurarsenossasclassesanotadascom@WebServletserãoprocuradas pelo servidor de aplicação. Se definirmos como true as classes anotadas serãoignoradas.

SenãodefinirmosoudefinirmoscomofalseasclassesqueestiveremnoWEB-INF/classesouemalgum.jardentroWEB-INF/libserãoexaminadaspeloservidordeaplicação.

AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,

Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex-aluno daCaelumtem15%dedescontonestelink!

ConheçaoscursosonlineAlura.

Mesmo sendo uma prática questionada por alguns desenvolvedores, podemos passar parâmetrosprogramaticamenteparaasServletsnasuainicializaçãoesemprecisardoarquivoweb.xml.Bastausaraanotação@WebInitParam(), paradeclarar cadaparâmetronopadrão chave/valor e depois passá-losdentrodeumvetorparaapropriedadeinitParamsdaanotação@WebServlet():

@WebServlet(name="OiServlet3",urlPatterns={"/oi"},initParams={@WebInitParam(name="param1",value="value1"),@WebInitParam(name="param2",value="value2")})publicclassOiServlet3{...}

Pararecuperá-losdentrodaServlettemostrêsestratégias:

JáconheceoscursosonlineAlura?

5.8PARASABERMAIS:WEBSERVLETEINITPARAMANNOTATION

.

Page 76: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Usandoasobrecargadométodoinit()dasServlets:

//códigoomitidoprivateStringparametro1;privateStringparametro2;

@Overridepublicvoidinit(ServletConfigconfig)throwsServletException{super.init(config);this.parametro1=config.getInitParameter("param1");this.parametro2=config.getInitParameter("param2");}

EmqualqueroutrométododaServletpormeiodeumobjetodaclasseServletConfig:

publicvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{

response.setContentType("text/html");PrintWriterout=response.getWriter();

out.println("<h2>ExemplocomInitParamServlet</h2>");

ServletConfigconfig=getServletConfig();

Stringparametro1=config.getInitParameter("param1");out.println("Valordoparâmetro1:"+parametro1);

Stringparametro2=config.getInitParameter("param2");out.println("<br>Valordoparâmetro1:"+parametro2);

out.close();}

OuusandoométodogetServletConfig()comgetInitParameter()diretonaopçãodesaída:

out.println("Valordoparâmetro1:"+getServletConfig().getInitParameter("param1"));

AodesenvolverumaaplicaçãoWeb,sempreprecisamosrealizaroperaçõesnoladodoservidor,comdadosinformadospelousuário,sejaatravésdeformuláriosousejaatravésdaURL.

Porexemplo,paragravarmosumcontatonobancodedados,precisamosdonome,e-mail,endereçoeadatadenascimentodele.Temosumapáginacomumformulárioqueousuáriopossapreenchereaoclicaremumbotãoessesdadosdevem,dealgumaforma,serpassadosparaumServlet.JásabemosqueaServlet responde por uma determinada URL (através do url-pattern/v2.5 ou do urlPatterns/v3.0),portanto,sóprecisamosindicarqueaoclicarnobotãodevemosenviarumarequisiçãoparaessaServlet.

Para isso, vamos criar uma página HTML, chamada adiciona-contato.html , contendo umformulárioparapreenchermososdadosdoscontatos:

<html><body>

5.9ENVIANDOPARÂMETROSNAREQUISIÇÃO

.

Page 77: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

<formaction="adicionaContato">Nome:<inputtype="text"name="nome"/><br/>E-mail:<inputtype="text"name="email"/><br/>Endereço:<inputtype="text"name="endereco"/><br/>DataNascimento:<inputtype="text"name="dataNascimento"/><br/>

<inputtype="submit"value="Gravar"/></form></body></html>

Essecódigopossuiumformulário,determinadopelatag<form>.Oatributoactionindicaqualendereçodeveserchamadoaosubmeteroformulário,aoclicarnobotãoGravar.Nessecaso,estamosapontandooactionparaumendereçoqueseráumaServletquejávamoscriar.

Aoacessarapáginaadiciona-contato.html,oresultadodeverásersimilaràfiguraabaixo:

Pararecebermososvaloresqueforampreenchidosnatelaesubmetidos,criaremosumaServlet,cujafunçãoseráreceberdealgumamaneiraessesdadoseconvertê-los,senecessário.

DentrodométodoservicedanossaServletparaadiçãodecontatos,vamosbuscarosdadosqueforamenviadosnarequisição.Parabuscarmosessesdados,precisamosutilizaroparâmetrorequestdométodoservice chamandoométodogetParameter("nomeDoParametro"), ondeonomedoparâmetroéomesmonomedoinputquevocêquerbuscarovalor.IssovairetornarumaStringcomovalordoparâmetro.Casonãoexistaoparâmetro,seráretornadonull:

StringvalorDoParametro=request.getParameter("nomeDoParametro");

OfatodeserdevolvidaumaStringnostrazumproblema,pois,adatadenascimentodocontatoestácriadacomoumobjetodotipoCalendar.Então,oqueprecisamosfazeréconverteressaStringem um objetoCalendar.Mas a API do Java para trabalhar com datas não nos permite fazer issodiretamente.Teremosque converter antes aString emumobjetodo tipojava.util.Date comauxíliodaclasseSimpleDateFormat,utilizandoométodoparse,daseguinteforma:

StringdataEmTexto=request.getParameter("dataNascimento");Datedate=newSimpleDateFormat("dd/MM/yyyy").parse(dataEmTexto);

5.10PEGANDOOSPARÂMETROSDAREQUISIÇÃO

.

Page 78: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Repare que indicamos também o pattern (formato) com que essa data deveria chegar para nós,atravésdoparâmetropassadonoconstrutordeSimpleDateFormatcomovalordd/MM/yyyy.TemosquetomarcuidadopoisométodoparselançaumaexceçãodotipoParseException.Essaexceçãoindicaqueoquefoipassadonadatanãopôdeserconvertidoaopatternespecificado.Comoobjetodotipojava.util.Date que foi devolvido, queremos criar um Calendar. Para isso vamos usar ométodosetTimedaclasseCalendar,querecebeumDate.

dataNascimento=Calendar.getInstance();dataNascimento.setTime(date);

VamosutilizartambémonossoDAOparagravaroscontatosnobancodedados.Nofinal,anossaServletficarádaseguinteforma:

@WebServlet("/adicionaContato")publicclassAdicionaContatoServletextendsHttpServlet{protectedvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException,ServletException{

PrintWriterout=response.getWriter();

//pegandoosparâmetrosdorequestStringnome=request.getParameter("nome");Stringendereco=request.getParameter("endereco");Stringemail=request.getParameter("email");StringdataEmTexto=request.getParameter("dataNascimento");CalendardataNascimento=null;

//fazendoaconversãodadatatry{Datedate=newSimpleDateFormat("dd/MM/yyyy").parse(dataEmTexto);dataNascimento=Calendar.getInstance();dataNascimento.setTime(date);}catch(ParseExceptione){out.println("Errodeconversãodadata");return;//paraaexecuçãodométodo}

//montaumobjetocontatoContatocontato=newContato();contato.setNome(nome);contato.setEndereco(endereco);contato.setEmail(email);contato.setDataNascimento(dataNascimento);

//salvaocontatoContatoDaodao=newContatoDao();dao.adiciona(contato);

//imprimeonomedocontatoquefoiadicionadoout.println("<html>");out.println("<body>");out.println("Contato"+contato.getNome()+"adicionadocomsucesso");out.println("</body>");out.println("</html>");}

.

Page 79: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

}

Querendoaprenderaindamaissobre?Esclarecerdúvidasdosexercícios?Ouvirexplicaçõesdetalhadascomuminstrutor?ACaelum oferece o cursoFJ-21 presencial nas cidades de São Paulo, Rio deJaneiroeBrasília,alémdeturmasincompany.

ConsulteasvantagensdocursoJavaparaDesenvolvimentoWeb

1. Comovamosprecisargravarcontatos,precisaremosdasclassesparatrabalharcombancodedadosquecriamosnocapítulodeJDBC.Paraisso,deixamosdisponívelumarquivozipcontendoasclassesnecessáriasquecriamosanteriormente.

NoEclipse,selecioneoprojetofj21-agendaevánomenuFile->Import

DentrodajaneladeImport,escolhaGeneral->ArchiveFileecliqueemNext:

NocampoFromarchivefilecliqueemBrowse,selecioneoarquivoDesktop/21/dao-modelo.zipecliqueemFinish

EMCASA

Casovocêestejafazendoemcasa,vocêpodeusarexatamenteasmesmasclassescriadasdurante os exercícios do capítulo de JDBC, mas terá que fazer uma mudança na classeConnectionFactory (volte ao capítulo 2, no box sobre o Class.forName. Não esqueça decopiartambémoDriverdoMySQL.

2. Temosquecriarapáginaquepermitiráaosusuárioscadastraroscontatos

VánomenuFile->New->Other.

EscolhaWeb->HTMLPageouHTMLFileecliqueNext:

VocêpodetambémfazerocursoFJ-21dessaapostilanaCaelum

5.11 EXERCÍCIOS: CRIANDO FUNCIONALIDADE PARA GRAVARCONTATOS

.

Page 80: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Chame o arquivo de adiciona-contato.html e clique em Finish (garanta que o arquivo estejadentrododiretórioWebContent):

EssearquivoHTMLdeveráteroseguinteconteúdo(cuidadocomonomedosinputs):

<html><body><h1>AdicionaContatos</h1><hr/><formaction="adicionaContato">Nome:<inputtype="text"name="nome"/><br/>E-mail:<inputtype="text"name="email"/><br/>Endereço:<inputtype="text"name="endereco"/><br/>DataNascimento:<inputtype="text"name="dataNascimento"/><br/>

<inputtype="submit"value="Gravar"/></form></body></html>

.

Page 81: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Acessenonavegadoroendereço:

http://localhost:8080/fj21-agenda/adiciona-contato.html

3. PrecisamoscriaraServletquegravaráocontatonobancodedados:

Crie uma nova Servlet no pacote br.com.caelum.agenda.servlet chamadoAdicionaContatoServletcomoseguintecódigo.

Cuidadoaoimplementaressaclasse,queégrandeecomplicada.

UseoCtrl+Shift+Oparaajudarnosimports.AclasseDatedeveserdejava.utileaclasseParseException,dejava.text.

@WebServlet("/adicionaContato")publicclassAdicionaContatoServletextendsHttpServlet{protectedvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException,ServletException{//buscaowriterPrintWriterout=response.getWriter();

//buscandoosparâmetrosnorequestStringnome=request.getParameter("nome");Stringendereco=request.getParameter("endereco");Stringemail=request.getParameter("email");StringdataEmTexto=request.getParameter("dataNascimento");CalendardataNascimento=null;

//fazendoaconversãodadatatry{Datedate=newSimpleDateFormat("dd/MM/yyyy").parse(dataEmTexto);dataNascimento=Calendar.getInstance();dataNascimento.setTime(date);}catch(ParseExceptione){out.println("Errodeconversãodadata");return;//paraaexecuçãodométodo}

//montaumobjetocontatoContatocontato=newContato();contato.setNome(nome);

.

Page 82: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

contato.setEndereco(endereco);contato.setEmail(email);contato.setDataNascimento(dataNascimento);

//salvaocontatoContatoDaodao=newContatoDao();dao.adiciona(contato);

//imprimeonomedocontatoquefoiadicionadoout.println("<html>");out.println("<body>");out.println("Contato"+contato.getNome()+"adicionadocomsucesso");out.println("</body>");out.println("</html>");}}

UTILIZANDOASERVLETV2.5

Se ainda estivéssemosutilizandoa versão2.5daServlet, precisaríamos fazero seguintemapeamentonoweb.xml:

<servlet><servlet-name>AdicionaContato</servlet-name><servlet-class>br.com.caelum.agenda.servlet.AdicionaContatoServlet</servlet-class></servlet>

<servlet-mapping><servlet-name>AdicionaContato</servlet-name><url-pattern>/adicionaContato</url-pattern></servlet-mapping>

Reinicieoservidor,paraqueanovaServletsejareconhecido

Acesse novamente no navegador a URL http://localhost:8080/fj21-agenda/adiciona-contato.html

PreenchaoformulárioecliqueemGravar.Oresultadodevesersemelhanteàimagemaseguir:

Verifiquenobancodedadosseodadorealmentefoiadicionadocomsucesso.

.

Page 83: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Repare que no exercício anterior, ao clicarmosno botão salvar, todos os dados que digitamosnoformulário aparecem na URL da página de sucesso. Isso acontece porque não definimos no nossoformulárioaformacomqueosdadossãoenviadosparaoservidor,atravésdoatributomethodparao<form>daseguinteforma:

<formaction="adicionaContato"method="POST">

Comonãotínhamosdefinido,porpadrãoentãoéusadoométodoGET,queindicaqueosvaloresdosparâmetrossãopassadosatravésdaURLjuntodosnomesdosmesmos,separadospor&,comoem:nome=Adriano&[email protected]

Podemos tambémdefinirométodoparaPOST e, dessa forma, osdados sãopassadosdentrodocorpodoprotocoloHTTP,semaparecernaURLqueémostradanonavegador.

Podemos, além de definir no formulário como os dados serão passados, também definir quaismétodosHTTPnossaservletaceitará.

OmétodoserviceaceitatodososmétodosHTTP,portanto,tantoométodoGETquantooPOST.Para especificarmos como trataremos cada método, temos que escrever os métodos doGet e/oudoPostnanossaservlet:

voiddoGet(HttpServletRequestreq,HttpServletResponseres);

voiddoPost(HttpServletRequestreq,HttpServletResponseres);

OUTROSMÉTODOSHTTP

AlémdoGET e doPOST, o protocoloHTTPpossui aindamais 7métodos: PUT,DELETE,HEAD,TRACE,CONNECT,OPTIONSePATCH.

MuitaspessoasconhecemapenasoGETePOST,pois,sãoosúnicosqueHTML4suporta.

OqueseráquevaiacontecersealgumSQLdonossoDAOcontivererrodesintaxeeocomandonãopuderserexecutado?Seráquevaiaparecerumamensagemagradávelparaousuário?

Naverdade,casoaconteçaumerrodentrodanossaServletastacktracedaexceçãoocorridaserámostradaemumatelapadrãodocontainer.Oproblemaéqueparaousuáriocomum,amensagemdeerrodoJavanãofaráomenorsentido.Oidealseriamostrarmosumapáginadeerrodizendo:"Umerroocorreu"ecominformaçõesdecomonotificaroadministrador.

5.12GET,POSTEMÉTODOSHTTP

5.13TRATANDOEXCEÇÕESDENTRODASERVLET

.

Page 84: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Parafazermosisso,bastaconfigurarmosnossaaplicaçãodizendoque,casoaconteçaumaException,umapáginadeerrodeveráserexibida.Essaconfiguraçãoéfeitanoweb.xml,comaseguintedeclaração:

<error-page><exception-type>java.lang.Exception</exception-type><location>/erro.html</location></error-page>

Alémdetratarmosasexceçõesquepodemacontecernanossaaplicação,podemostambémtrataroscódigos de erro HTTP, como por exemplo, 404, que é o erro dado quando se acessa uma páginainexistente.Paraissobastafazermosadeclaraçãonoweb.xml:

<error-page><error-code>404</error-code><location>/404.html</location></error-page>

WRAPPINGEMSERVLETEXCEPTION

Caso aconteça uma exceção que seja do tipo checada (não filha de RuntimeException),tambémteríamosquerepassá-laparacontainer.Noentanto,ométodoservice sónospermitelançarServletExceptioneIOException.

Para podermos lançar outra exceção checked, precisamos escondê-la em umaServletException,comoaseguir:

try{//códigoquepodelançarSQLException}catch(SQLExceptione){thrownewServletException(e);}

Essa técnica é conhecida como wrapping de exceptions. O container, ao receber aServletException,vaidesembrulharaexceptioninternaetratá-la.

.

Page 85: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.

CasadoCódigo,LivrosdeTecnologia.

1. Vamoscriarumapáginaparamostraramensagemgenéricadetratamento:

CrieumnovoHTMLchamadoerro.htmlcomoseguinteconteúdo:

<html><body>Umerroocorreu!</body></html>

Adicioneadeclaraçãodapáginadeerronoweb.xml:

<error-page><exception-type>java.lang.Exception</exception-type><location>/erro.html</location></error-page>

AltereousuáriodeacessoaobanconaclasseConnectionFactoryderootparaalgumoutrousuárioquenãoexista,porexemplo,toor.

Reinicieoservidor,paraqueasalteraçõestenhamefeito

AcessenonavegadoraURLhttp://localhost:8080/fj21-agenda/adiciona-contato.html

PreenchaoformulárioecliqueemGravar,oresultadodevesersemelhanteàimagemaseguir:

Seuslivrosdetecnologiaparecemdoséculopassado?

5.14EXERCÍCIO:TRATANDOEXCEÇÕESECÓDIGOSHTTP

.

Page 86: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

AlterenovamenteousuáriodeacessoaobanconaclasseConnectionFactorypararoot.

2. Vamoscriarumapáginaparaserexibidaquandoousuárioacessaralgoinexistente:

CrieumnovoHTMLchamado404.htmlcomoseguinteconteúdo:

<html><body>Apáginaacessadanãoexiste.</body></html>

Adicioneadeclaraçãodapáginanoweb.xml:

<error-page><error-code>404</error-code><location>/404.html</location></error-page>

Reinicienovamenteoservidor;

Acesse no navegador umaURL inexistente no projeto, por exemplo, http://localhost:8080/fj21-agenda/naoexiste.html:

TodaServletdevepossuirumconstrutorsemargumentosparaqueocontainerpossacriá-lo.Apósacriação,oservletcontainer inicializaaServletcomométodoinit(ServletConfigconfig) e ousadurante todoo seuperíodoativo, atéquevaidesativá-lo atravésdométododestroy(), para entãoliberaroobjeto.

ÉimportanteperceberqueasuaServletseráinstanciadoumaúnicavezpelocontainereesseúnicoobjetoseráusadoparaatenderatodasasrequisiçõesdetodososclientesemthreadsseparadas.Aliás,éjustoissoquetrazumamelhoriaemrelaçãoaosCGIcomunsquedisparavamdiversosprocessos.

NainicializaçãodeumaServlet,quandoparâmetrospodemserlidosevariáveiscomunsatodasasrequisiçõesdevemserinicializadas,éumbommomento,porexemplo,paracarregararquivosdiversosdeconfiguraçõesdaaplicação:

voidinit(ServletConfigconfig);

5.15INITEDESTROY

.

Page 87: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Nafinalização,devemosliberarpossíveisrecursosqueestejamossegurando:

voiddestroy();

Osmétodosinit edestroy, quando reescritos, sãoobrigados a chamarosuper.init() esuper.destroy() respectivamente. Isso acontece pois um método é diferente de um construtor.Quando estendemos uma classe e criamos o nosso próprio construtor da classe filha, ela chama oconstrutor da classe pai sem argumentos, preservando a garantia da chamada de um construtor. Omesmonãoacontececomosmétodos.

Supondoqueométodoinit(oudestroy)executaalgumatarefafundamentalemsuaclassepai,sevocêesquecerdechamarosuper,teráproblemas.

OexemploaseguirmostraumaServletimplementandoosmétodosdeinicializaçãoefinalização.Osmétodosinitedestroypodemserbemsimples(lembre-sequesãoopcionais):

@WebServlet("/minhaServlet")publicclassMinhaServletextendsHttpServlet{

publicvoidinit(ServletConfigconfig)throwsServletException{super.init(config);log("Iniciandoaservlet");}

publicvoiddestroy(){super.destroy();log("Destruindoaservlet");}

protectedvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException,ServletException{//códigodoseumétodoservice}}

DeacordocomaespecificaçãodeServlets,porpadrão, existeumaúnica instânciadecadaServletdeclarada.AochegarumarequisiçãoparaaServlet,umanovaThreadéabertasobreaquelainstânciaquejáexiste.

Isso significa que, se colocássemos em nossa Servlet uma variável de instância, ela seriacompartilhadaentretodasasthreadsqueacessamessaServlet!Emoutraspalavras,seriacompartilhadoentre todasas requisiçõese todososclientesenxergariamomesmovalor.Provavelmentenãoéoquequeremosfazer.

UmexemplosimplesparanosauxiliarenxergarissoéumaServletcomumavariávelparacontaraquantidadederequisições:

@WebServlet("/contador")

5.16UMAÚNICAINSTÂNCIADECADASERVLET

.

Page 88: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

publicclassContadorextendsHttpServlet{privateintcontador=0;//variaveldeinstância

protectedvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{contador++;//acadarequisiçãoamesmavariáveléincrementada

//recebeowriterPrintWriterout=response.getWriter();

//escreveotextoout.println("<html>");out.println("<body>");out.println("Contadoragoraé:"+contador);out.println("</body>");out.println("</html>");}}

Quando a Servlet for inicializada, o valor do contador é definidopara 0 (zero).Após isso, a cadarequisição que é feita para essa Servlet, devido ao fato da instância ser sempre a mesma, a variávelutilizadaparaincrementarserásempreamesma,eporconsequênciaimprimiráonúmeroatualparaocontador.

Sabemosquecompartilharvariáveis entremúltiplasThreadspodenos trazerproblemasgravesdeconcorrência. Se duas threads (no caso, duas requisições)modificarem amesma variável ao "mesmotempo",podemosterperdadeinformaçõesmesmoemcasossimplescomoodocontadoracima.

Háduassoluçõesparaesseproblema.Aprimeiraseriaimpedirqueduasthreadsacessemaomesmotempoomesmoobjetocrítico;paraisso,podemossincronizarométodoservice.Masissotrariamuitosproblemas de escalabilidade (apenas uma pessoa por vez poderia requisitar minha página). A outrasolução,maissimples,éapenasnãocompartilharobjetosentrethreads.

QuandosefaladeServlets,aboapráticadizparaevitarusaratributoscompartilhados.

Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende

Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!

ConheçaaAluraCursosOnline.

Agoraéamelhorhoradeaprenderalgonovo

.

Page 89: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

1. ImplementeoscódigosdasseçõesanterioressobreciclodevidaeconcorrênciaemServlets.FaçaaclasseContador e use tambémosmétodosinit edestroy.O objetivo é ver na prática osconceitosdiscutidos.

Imaginesequiséssemoslistarosnossoscontatos,comopoderíamosfazer?Comoatéomomentosóconhecemos Servlet, provavelmente nossa sugestão seria criarmos uma Servlet que faça toda alistagematravésdeout.println().Mas, seráqueamanutençãodisso seriaagradável?E seumdiaprecisarmos adicionar uma coluna nova na tabela? Teríamos que recompilar classes, e colocarmos aatualizaçãonoar.

Com o decorrer do curso aprenderemos que essa não é a melhor forma de fazermos essafuncionalidade.

5.17EXERCÍCIOSOPCIONAIS

5.18DISCUSSÃO:CRIANDOPÁGINASDENTRODEUMASERVLET

.

Page 90: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO6

"Omaiorprazeréesperarpeloprazer."--GottholdLessing

Nessecapítulo,vocêaprenderá:

OqueéJSP;Suasvantagensedesvantagens;EscreverarquivosJSPcomscriptlets;UsarExpressionLanguage.

Atéagora,vimosquepodemosescreverconteúdodinâmicoatravésdeServlets.Noentanto, setodahoracriarmosServletsparafazermosessetrabalho,teremosmuitosproblemasnamanutençãodas nossas páginas e também na legibilidade do nosso código, pois sempre aparece código JavamisturadocomcódigoHTML.ImaginetodoumsistemacriadocomServletsfazendoageraçãodoHTML.

Para não termos que criar todos os nossos conteúdos dinâmicos dentro de classes, misturandofortementeHTML com código Java, precisamos usar uma tecnologia que podemos usar oHTMLdeformadireta,equetambémvápossibilitarautilizaçãodoJava.AlgosimilaraoASPePHP.

Essa tecnologia é o JavaServerPages (JSP). O primeiro arquivo JSP que vamos criar é chamadobemvindo.jsp.EssearquivopoderiacontersimplesmentecódigoHTML,comoocódigoaseguir:

<html><body>Bemvindo</body></html>

Assim, fica claro que uma página JSP nada mais é que um arquivo baseado em HTML, com aextensão.jsp.

Dentro de um arquivo JSP podemos escrever também código Java, para que possamos adicionarcomportamentodinâmicoemnossaspáginas,comodeclaraçãodevariáveis,condicionais(if), loops(for,while)entreoutros.

JAVASERVERPAGES

6.1COLOCANDOOHTMLNOSEUDEVIDOLUGAR

.

Page 91: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Portanto,vamosescreverumpoucodecódigoJavananossaprimeirapágina.VamosdeclararumavariáveldotipoStringeinicializá-lacomalgumvalor.

<%Stringmensagem="Bemvindo!";%>

ParaescrevercódigoJavanasuapágina,bastaescrevê-loentreastags<%e%>.Essetipodecódigoéchamadodescriptlet.

SCRIPTLET

Scriptletéocódigoescritoentre<%e%>.Essenomeécompostodapalavrascript(pedaçodecódigoemlinguagemdescript)comosufixolet,queindicaalgopequeno.

Comovocêjápercebeu,aSunpossuiessamaniadecolocarosufixoletemseusprodutoscomoosscriptlets,servlets,portlets,midlets,appletsetc...

PodemosavançarmaisumpoucoeutilizarumadasvariáveisjáimplícitasnoJSP:todoarquivoJSPjápossuiumavariávelchamadaout(dotipoJspWriter)quepermiteimprimirparaoresponseatravésdométodoprintln:

<%out.println(nome);%>

A variável out é um objeto implícito na nossa página JSP e existem outras de acordo com aespecificação. Repare também que sua funcionalidade é semelhante ao out que utilizávamos nasServletsmassemprecisarmosdeclará-loantes.

Existemaindaoutraspossibilidadespara imprimiroconteúdodanossavariável:podemosutilizarumatalho(muitoparecido,ouigual,aoutraslinguagensdescriptparaaWeb):

<%=nome%><br/>

IssojáéosuficienteparaquepossamosescreveronossoprimeiroJSP.

COMENTÁRIOS

OscomentáriosemumapáginaJSPdevemserfeitoscomooexemploaseguir:

<%--comentárioemjsp--%>

.

Page 92: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.

CasadoCódigo,ebookcompreçodeebook.

1. CrieoarquivoWebContent/bemvindo.jspcomoseguinteconteúdo:

<html><body><%--comentárioemJSPaqui:nossaprimeirapáginaJSP--%>

<%Stringmensagem="BemvindoaosistemadeagendadoFJ-21!";%><%out.println(mensagem);%>

<br/>

<%Stringdesenvolvido="Desenvolvidopor(SEUNOMEAQUI)";%><%=desenvolvido%>

<br/>

<%System.out.println("Tudofoiexecutado!");%></body></html>

2. AcesseaURLhttp://localhost:8080/fj21-agenda/bemvindo.jspnonavegador

EditoraCasadoCódigocomlivrosdeumaformadiferente

6.2EXERCÍCIOS:PRIMEIROJSP

.

Page 93: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

3. Ondeapareceuamensagem"Tudofoiexecutado!"?

É muito importante você se lembrar que o código Java é interpretado no servidor, portantoapareceunoconsoledoseuTomcat.

VerifiqueoconsoledoseuTomcat.

Uma vez que podemos escrever qualquer código Java como scriptlet, não fica difícil criar umalistagemdetodososcontatosdobancodedados.

Temos todas as ferramentas necessárias para fazer essa listagem uma vez que já fizemos isso nocapítulodeJDBC.

Basicamente,ocódigoutilizaráoContatoDaoquecriamosanteriormenteparaimprimiralistadeContato:

<%ContatoDaodao=newContatoDao();List<Contato>contatos=dao.getLista();

for(Contatocontato:contatos){%><li><%=contato.getNome()%>,<%=contato.getEmail()%>:<%=contato.getEndereco()%></li>

<%}%>

Nessecódigoaindafalta,assimcomonoJavapuro,importarasclassesdospacotescorretos.

Parafazermosoimportdasclasses,precisamosdeclararqueaquelapáginaprecisadeacessoàoutrasclassesJava.Paraisso,utilizamosdiretivas,quepossuemaseguintesintaxe:<%@...%>.

Reparequeelaseparecemuitocomscriptlet,comadiferençaquepossuiuma@ logonaabertura.Essadiretivaéumadiretivadepágina,ouseja,umaconfiguraçãoespecíficadeumapágina.

Paraisso,utilizamos<%@page%>.Bastadizermosqualconfiguraçãoqueremosfazernessapágina,

6.3LISTANDOOSCONTATOSCOMSCRIPTLET

.

Page 94: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

quenonossocasoéimportarumaclasseparautilizá-la:

<%@pageimport="br.com.caelum.agenda.dao.ContatoDao"%>

Oatributoimport permite que seja especificado qual o pacote a ser importado. Para importardiversospacotes,podemossepará-losporvírgulas(videoexercício).

1. CrieoarquivoWebContent/lista-contatos-scriptlet.jspesiga:

Importeospacotesnecessários.UseoCtrl+EspaçodoEclipseparaajudaraescreverospacotes.

<%@pageimport="java.util.*,br.com.caelum.agenda.dao.*,br.com.caelum.agenda.modelo.*"%>

Coloqueocódigoparafazeralistagem.UsebastanteoCtrl+EspaçodoEclipse.

<html><body><table><%ContatoDaodao=newContatoDao();List<Contato>contatos=dao.getLista();

for(Contatocontato:contatos){%><tr><td><%=contato.getNome()%></td><td><%=contato.getEmail()%></td><td><%=contato.getEndereco()%></td><td><%=contato.getDataNascimento().getTime()%></td></tr><%}%></table></body></html>

Testeaurlhttp://localhost:8080/fj21-agenda/lista-contatos-scriptlet.jsp

2. Reparequeadataapareceudeumaformacomplicadadeler.Tentemostrá-laformatadautilizandoaclasseSimpleDateFormat.

3. Coloquecabeçalhosparaascolunasdatabela,descrevendooquecadacolunasignifica.4. Tenteutilizaroquadroaseguirparadefinirapáginapadrãodeseusite.

6.4EXERCÍCIOSOPCIONAIS:LISTADECONTATOSCOMSCRIPTLET

.

Page 95: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

WELCOME-FILE-LIST

Oarquivoweb.xmlabaixodizqueosarquivoschamados"bemvindo.jsp"devemserchamadosquandoumclientetentaacessarumdiretóriowebqualquer.

Ovalordessecampocostumaser"index.html"emoutraslinguagensdeprogramação.

ComovocêpodeverpeloarquivogeradoautomaticamentepeloWTP,épossívelindicarmaisdeumarquivoparaseroseuwelcome-file!Mude-opara:

<welcome-file-list><welcome-file>bemvindo.jsp</welcome-file></welcome-file-list>

ReinicieotomcateacesseaURL:http://localhost:8080/fj21-agenda/

AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,

Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex-aluno daCaelumtem15%dedescontonestelink!

ConheçaoscursosonlineAlura.

AbrimosocapítulodizendoquenãoqueríamosmisturarcódigoJavacomcódigoHTMLnasnossasServlets,pois,prejudicavaalegibilidadedonossocódigoeafetavaamanutenção.

Maséjustamenteissoqueestamosfazendoagora,sóquenoJSP,atravésdeScriptlets.

ÉcomplicadoficarescrevendoJavaemseuarquivoJSP,nãoé?

Primeiro,ficatudomalescritoedifícildeler.OJavapassaaatrapalharocódigoHTMLemvezdeajudar.Depois,quandooresponsávelpelodesigngráficodapáginaquiseralteraralgo,teráqueconhecerJavaparaentenderoqueestáescritoládentro.Hmm...nãopareceumaboasolução.

JáconheceoscursosonlineAlura?

6.5MISTURANDOCÓDIGOJAVACOMHTML

.

Page 96: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

E existe hoje em dia no mercado muitas aplicações feitas inteiramente utilizando scriptlets eescrevendocódigoJavanomeiodosHTMLs.

Comodecorrerdocurso,vamosevoluirnossocódigoatéumpontoemquenãofaremosmaisessamistura.

PararemoverumpoucodocódigoJavaqueficanapáginaJSP,aSundesenvolveuumalinguagemchamadaExpressionLanguagequeéinterpretadapeloservletcontainer.

Nossoprimeiroexemplocomessalinguageméutilizá-laparamostrarparâmetrosqueoclienteenviaatravésdesuarequisição.

Porexemplo,seoclientechamaapáginatestaparam.jsp?idade=24,oprogramadevemostraramensagemqueoclientetem24anos.

Como fazer isso? Simples, existe uma variável chamada param que, na expression language, éresponsável pelos parâmetros enviados pelo cliente. Para ler o parâmetro chamado idade basta usar${param.idade}.Paraleroparâmetrochamadodiadevemosusar${param.dia}.

A expression language ainda vai ser utilizada para muitos outros casos, não apenas para pegarparâmetrosquevieramdorequest.ElaéaformamaiselegantehojeemdiaparatrabalharnoJSPeseráexploradanovamenteduranteoscapítulosposteriores.

1. CrieumapáginachamadaWebContent/digita-idade.jspcomoconteúdo:

<html><body>Digitesuaidadeepressioneobotão:<br/>

<formaction="mostra-idade.jsp">Idade:<inputtype="text"name="idade"/><inputtype="submit"/></form></body></html>

2. Crie um arquivo chamado WebContent/mostra-idade.jsp e coloque o código de expressionlanguagequemostraaidadequefoienviadacomoparâmetroparaessapágina:

<html><body>Testandoseusparâmetros:<br/>Aidadeé${param.idade}.</body></html>

6.6EL:EXPRESSIONLANGUAGE

6.7EXERCÍCIOS:PARÂMETROSCOMAEXPRESSIONLANGUAGE

.

Page 97: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

3. Testeosistemaacessandoapáginahttp://localhost:8080/fj21-agenda/digita-idade.jsp.

Querendoaprenderaindamaissobre?Esclarecerdúvidasdosexercícios?Ouvirexplicaçõesdetalhadascomuminstrutor?ACaelum oferece o cursoFJ-21 presencial nas cidades de São Paulo, Rio deJaneiroeBrasília,alémdeturmasincompany.

ConsulteasvantagensdocursoJavaparaDesenvolvimentoWeb

Os arquivos JSPs não são compilados dentro do Eclipse, por esse motivo na hora que estamosescrevendooJSPnoEclipsenãoprecisamosdasclassesdodriver.

Os JSPs são transformados emumaServlet, que vimos anteriormente, porumcompilador JSP (oTomcatcontémumcompiladorembutido).EssecompiladorJSPpodegerarumcódigoJavaqueéentãocompiladoparagerarbytecodediretamenteparaaservlet.

Então,somenteduranteaexecuçãodeumapáginaJSP,quandoeleétransformadoemumaservlet,queseucódigoJavaécompiladoenecessitamosdasclassesdodriverquesãoprocuradasnodiretóriolib.

VocêpodetambémfazerocursoFJ-21dessaapostilanaCaelum

6.8PARASABERMAIS:COMPILANDOOSARQUIVOSJSP

.

Page 98: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO7

"Saberécompreendermosascoisasquemaisnosconvém."--FriedrichNietzsche

Nessecapítulo,vocêaprenderáoquesãoTaglibseJSTL.Etambémteráachancedeutilizaralgumasdasprincipaistagsdogrupocoreefmt.

Nocapítuloanterior,começamosamelhorarnossosproblemascomrelaçãoàmisturadecódigoJavacomHTMLatravésdaExpressionLanguage.Noentanto, ela sozinhanãopodenos ajudarmuito,poiselanãonospermite,porexemplo, instanciarobjetos, fazerverificaçõescondicionais(ifelse),iteraçõescomoemumforeassimpordiante.

Paraquepossamosteressecomportamentosemimpactarnalegibilidadedonossocódigo,teremosque escrever esse código nos nossos JSPs numa forma parecida com o que já escrevemos lá, que éHTML,logo,teremosqueescrevercódigobaseadoemTags.

Issomesmo,umatag!ASunpercebeuqueosprogramadoresestavamabusandodocódigoJavanoJSP e tentou criar algomais "natural" (um ponto um tanto quanto questionável damaneira que foiapresentadanoinício),sugerindoousodetagsparasubstituirtrechosdecódigo.

Oresultadofinaléumconjuntodetags(umataglibrary,outaglib)padrão,quepossui,entreoutrastags,afuncionalidadedeinstanciarobjetosatravésdoconstrutorsemargumentos.

USANDOTAGLIBS

7.1TAGLIBS

.

Page 99: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.

CasadoCódigo,ebookcompreçodeebook.

Como já foi comentado anteriormente, os Javabeans devem possuir o construtor público semargumentos(umtípicoPlainOldJavaObject:POJO),gettersesetters.

Instanciá-losnanossapáginaJSPnãoécomplicado.Bastautilizarmosatagcorrespondenteparaessafunção,quenonossocasoéa<jsp:useBean>.

Parautilizá-la,bastaindicarmosqualaclassequeremosinstanciarecomosechamaráavariávelqueseráatribuídaessanovainstância.

<jsp:useBeanid="contato"class="br.com.caelum.agenda.modelo.Contato"/>

Podemosimprimironomedocontato(queestáembranco,claro...):

${contato.nome}

Mas,ondeestáogetNome()?Aexpressionlanguageécapazdepercebersozinhaanecessidadedechamarummétododotipogetter,porissoopadrãogetter/setterdoPOJOétãoimportantehojeemdia.

Desta maneira, classes como Contato são ferramentas poderosas por seguir esse padrão poisdiversasbibliotecasimportantesestãobaseadasnele:Hibernate,Struts,VRaptor,JSF,EJBetc.

ATENÇÃO

NaExpressionLanguage${contato.nome} chamaráométodogetNome porpadrão.Paraque isso sempre funcione, devemos colocar o parâmetro em letra minúscula. Ou seja,${contato.Nome}nãofunciona.

EditoraCasadoCódigocomlivrosdeumaformadiferente

7.2INSTANCIANDOPOJOS

.

Page 100: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Seguindo a ideia demelhorar o código Java que precisa de umamaneira ou outra ser escrito napáginaJSP,aSunsugeriuousodaJavaServerPagesStandardTagLibrary,aJSTL.

OBSERVAÇÃO

Antesde2005,JSTLsignificavaJavaServerPagesStandardTemplateLibrary.

AJSTL é aAPIque encapsulou em tags simples toda a funcionalidadequediversaspáginasWebprecisam,comocontroledelaços(fors),controledefluxodotipoifelse,manipulaçãodedadosXMLeainternacionalizaçãodesuaaplicação.

Antigamente,diversasbibliotecasforamcriadasporváriosgruposcomfuncionalidadessimilaresaoJSTL (principalmente aoCore), culminando com a aparição damesma, emuma tentativa da Sun depadronizaralgoqueomercadovêcomoútil.

Existem ainda outras partes da JSTL, por exemplo aquela que acessa banco de dados e permiteescrevercódigosSQLnanossapágina,masseodesignernãocompreendeJavaoquediremosdeSQL?OusodetalpartedaJSTLédesencorajado.

AJSTLfoiaformaencontradadepadronizarotrabalhodemilharesdeprogramadoresdepáginasJSP.

Antesdisso,muitagenteprogramavacomonosexemplosquevimosanteriormente, somentecomJSPseJavabeans,ochamadoModelo1,quenaépocafaziapartedosBlueprintsdeJ2EEdaSun(boaspráticas)enósvamosdiscutirmaisparafrentenocurso.

MuitaspáginasJSPnoBrasilaindapossuemgrandespedaçosdescriptletsespalhadosdentrodelas.

RecomendamosatodososnossosalunosqueoptarempeloJSPcomocamadadevisualização,queutilizemaJSTLeoutrasbibliotecasdetagparaevitarocódigoincompreensívelquepodesergeradocomscriptlets.

Ocódigodasscriptletsmaisconfundedoqueajuda,tornandoamanutençãodapáginaJSPcadavezmaiscustosaparaoprogramadoreparaaempresa.

Para instalar a implementação mais famosa da JSTL basta baixar a mesma no site

7.3JSTL

Asempresashojeemdia

7.4INSTALAÇÃO

.

Page 101: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

http://jstl.java.net/.

Aousaro JSTLemalgumapáginaprecisamosprimeirodefinir o cabeçalho.ExistemquatroAPIsbásicasevamosaprenderprimeiroautilizarabibliotecachamadadecore.

AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,

Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex-aluno daCaelumtem15%dedescontonestelink!

ConheçaoscursosonlineAlura.

SemprequevamosutilizarumataglibdevemosprimeiroescreverumcabeçalhoatravésdeumatagJSPquedefinequaltaglibvamosutilizareumnome,chamadoprefixo.

EsseprefixopodeterqualquervalormasnocasodataglibcoredaJSTLopadrãodaSunéaletrac.JáaURI(quenãodeveserdecorada)émostradaaseguirenãoimplicaemumarequisiçãopeloprotocolohttpesimumabuscaentreosarquivos.jarnodiretóriolib.

<%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%>

UsandoaJSTLcore,vamosreescreveroarquivoquelistatodoscontatos.

Ocabeçalhojáéconhecidodaseçãoanterior:

<%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%>

Depois, precisamos instanciar e declarar nosso DAO. Ao revisar o exemplo da lista através descriptlets,queremosexecutaroseguinte:

classe:br.com.caelum.jdbc.dao.ContatoDao;construtor:semargumentos;variável:DAO.

JáconheceoscursosonlineAlura?

7.5CABEÇALHOPARAAJSTLCORE

7.6FOREACH

.

Page 102: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Já vimos a tag jsp:useBean, capaz de instanciar determinada classe através do construtor semargumentosedarumnome(id)paraessavariável.

PortantovamosutilizarataguseBeanparainstanciarnossoContatoDao:

<jsp:useBeanid="dao"class="br.com.caelum.agenda.dao.ContatoDao"/>

Comotemosavariáveldao,desejamoschamarométodogetListaepodemosfazerissoatravésdaEL:

${dao.lista}

Desejamosexecutarumloopparacadacontatodentrodacoleçãoretornadaporessemétodo:

arrayoucoleção:dao.lista;variáveltemporária:contato.

Nonossoexemplocomscriptlets,oquefaltaéachamadadométodogetListaeaiteração:

<%//...List<Contato>contatos=dao.getLista();

for(Contatocontato:contatos){%><%=contato.getNome()%>,<%=contato.getEmail()%>,<%=contato.getEndereco()%>,<%=contato.getDataNascimento()%><%}%>

A JSTL core disponibiliza uma tag chamada c:forEach capaz de iterar por uma coleção,exatamente o que precisamos. No c:forEach, precisamos indicar a coleção na qual vamos iterar,atravésdoatributoitemsetambémcomochamaráoobjetoqueseráatribuídoparacadaiteraçãonoatributovar.Oexemplo a seguirmostraousodeexpression language deumamaneiramuitomaiselegante:

<c:forEachvar="contato"items="${dao.lista}">${contato.nome},${contato.email},${contato.endereco},${contato.dataNascimento}</c:forEach>

Maiselegantequeocódigoquefoiapresentadousandoscriptlets,não?

.

Page 103: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

FOREACHEVARSTATUS

ÉpossívelcriarumcontadordotipointdentrodoseulaçoforEach.Paraisso,bastadefiniroatributochamadovarStatus para a variável desejada eutilizar a propriedadecount dessavariável.

<tableborder="1"><c:forEachvar="contato"items="${dao.lista}"varStatus="id"><trbgcolor="#${id.count%2==0?'aaee88':'ffffff'}"><td>${id.count}</td><td>${contato.nome}</td></tr></c:forEach></table>

1. PrecisamosprimeirocolocarosJARsdaJSTLemnossaaplicação.

Primeiro,váaoDesktop,eentrenodiretório21/jars-jstlHaverádoisjars,javax.servlet.jsp.jstl-x.x.x.jarejavax.servlet.jsp.jstl-api-x.x.x.jarCopie-os(CTRL+C)ecole-os(CTRL+V)dentrodeworkspace/fj21-agenda/WebContent/WEB-INF/lib

NoEclipse,dêumF5noseuprojetooucliquecomobotãodireitodomousesobreonomedoprojetoeescolhaaopçãoRefresh.

EMCASA

Casovocêestejaemcasa,podefazerodownloaddaJSTLAPIeda implementaçãoem:https://jstl.java.net/download.html

2. ListeoscontatosdeContatoDaousandojsp:useBeaneJSTL.

Crieoarquivolista-contatos.jsp,dentrodapastaWebContent/usandooatalhodenovoJSPnoEclipse;

Antesdeescrevermosnossocódigo,precisamos importara taglib JSTLCore. Issoé feitocomadiretiva<%@taglib%> no topodo arquivo.Usandoo recurso de autocompletar doEclipse(inclusivenaURL),declareataglibnotopodoarquivo:

<%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%>

7.7EXERCÍCIOS:FOREACH

.

Page 104: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Localizea tag<body>noarquivoe implementeo conteúdodanossapáginadentrodobody.VamosusarumatabelaHTMLeastags<jsp:useBean/>e<c:forEach/>quevimosantes:

<!--criaoDAO--><jsp:useBeanid="dao"class="br.com.caelum.agenda.dao.ContatoDao"/>

<table><!--percorrecontatosmontandoaslinhasdatabela--><c:forEachvar="contato"items="${dao.lista}"><tr><td>${contato.nome}</td><td>${contato.email}</td><td>${contato.endereco}</td><td>${contato.dataNascimento.time}</td></tr></c:forEach></table>

Acessehttp://localhost:8080/fj21-agenda/lista-contatos.jsp

ReparequeapóscriarumanovapáginaJSPnãoprecisamosreiniciaronossocontainer!

3. ScriptletsouJSTL?Qualdosdoisémaisfácilentender?

Querendoaprenderaindamaissobre?Esclarecerdúvidasdosexercícios?Ouvirexplicaçõesdetalhadascomuminstrutor?ACaelum oferece o cursoFJ-21 presencial nas cidades de São Paulo, Rio deJaneiroeBrasília,alémdeturmasincompany.

ConsulteasvantagensdocursoJavaparaDesenvolvimentoWeb

VocêpodetambémfazerocursoFJ-21dessaapostilanaCaelum

7.8EXERCÍCIOSOPCIONAIS

.

Page 105: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

1. Coloqueumcabeçalhonascolunasdatabelacomumtítulodizendoàqueserefereacoluna.2. Utilizeumavariáveldestatusnoseuc:forEachparacolocarduascoresdiferentesemlinhaspares

eímpares.(UtilizecomoauxíliooboximediatamenteantesdoexercíciosobreforEach)

Alistagemdosnossoscontatosfuncionaperfeitamente,masonossoclienteaindanãoestásatisfeito.Elequerumpoucomaisdefacilidadenessatela,esugerequecasoousuáriotenhae-mailcadastrado,coloquemosumlinknoe-mailquequandoclicadoabraosoftwaredee-maildocomputadordousuárioparaenviarumnovoe-mailparaesseusuário.Comopodemosfazeressafuncionalidade?

Vamosanalisaroproblemacomcalma.Primeiro,percebemosquevamosprecisarcriarumlinkparaenvio de e-mail. Isso é facilmente conseguido através da tag do HTML <a> com o parâmetrohref="mailto:[email protected]".Primeiroproblemaresolvidofacilmente,masagoratemosoutro.Comofaremosaverificaçãoseoe-mailestáounãopreenchido?

Paraquepossamosfazeressaverificaçãoprecisaremosfazerumifparasabermosseoe-mailestápreenchido ou não. Mas, novamente, não queremos colocar código Java na nossa página e jáaprendemosqueestamosmudando issoparautilizar tags.Paraessa finalidade,existea tagc:if, naqualpodemosindicarqualotestelógicodeveserfeitoatravésdoatributotest.EssetesteéinformadoatravésdeExpressionLanguage.

Paraverificarmosseoe-mailestápreenchidoounão,podemosfazeroseguinte:

<c:iftest="${notemptycontato.email}"><ahref="mailto:${contato.email}">${contato.email}</a></c:if>

Podemos também, caso o e-mail não tenha sido preenchido, colocar a mensagem "e-mail nãoinformado",ao invésdenossa tabela ficarcomumespaçoembranco.Reparequeesseé justamenteocasocontrárioquefizemosnonossoif,logo,éequivalenteaoelse.

OproblemaéquenãotemosatagelsenaJSTL,porquestõesestruturaisdeXML.Umaprimeiraalternativa seria fazermosoutro<c:if> com a lógica invertida.Mas issonão é uma soluçãomuitoelegante. No Java, temos outra estrutura condicional que consegue simular um if/else, que é oswitch/case.

Parasimularmosswitch/casecomJSTL,utilizamosatagc:chooseeparacadacasodoswitchfazemosc:when.Odefaultdoswitchpodeserrepresentadoatravésdatagc:otherwise,comonoexemploaseguir:

<c:choose><c:whentest="${notemptycontato.email}">

7.9EVOLUINDONOSSALISTAGEM

7.10FAZENDOIFSCOMAJSTL

.

Page 106: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

<ahref="mailto:${contato.email}">${contato.email}</a></c:when><c:otherwise>E-mailnãoinformado</c:otherwise></c:choose>

Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.

CasadoCódigo,LivrosdeTecnologia.

1. Vamoscolocaremnossalistagemumlinkparaenviodee-mailcasoomesmotenhasidoinformado.

Abraoarquivolista-contatos.jspnoEclipse;

Nomomentode imprimiroe-maildocontato,adicioneumaverificaçãopara saber seoe-mailestápreenchidoe,casoesteja,adicioneumlinkparaenviodee-mail:

<c:forEachvar="contato"items="${dao.lista}"><tr><td>${contato.nome}</td><td><c:iftest="${notemptycontato.email}"><ahref="mailto:${contato.email}">${contato.email}</a></c:if></td><td>${contato.endereco}</td><td>${contato.dataNascimento.time}</td></tr></c:forEach>

Acesseapáginanonavegadorpeloendereçohttp://localhost:8080/fj21-agenda/lista-contatos.jsp

Seuslivrosdetecnologiaparecemdoséculopassado?

7.11EXERCÍCIOS:LISTADECONTATOSCOMCONDICIONAIS

.

Page 107: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

2. Vamoscolocaramensagem"E-mailnãoinformado"casooe-mailnãotenhasidoinformado

Abaixodonovoifque fizemosno itemanterior,vamoscolocarmaisum if,dessavezcomaverificaçãocontrária,ouseja,queremossaberseestávazio:

<c:forEachvar="contato"items="${dao.lista}"><tr><td>${contato.nome}</td><td><c:iftest="${notemptycontato.email}"><ahref="mailto:${contato.email}">${contato.email}</a></c:if>

<c:iftest="${emptycontato.email}">E-mailnãoinformado</c:if></td><td>${contato.endereco}</td><td>${contato.dataNascimento.time}</td></tr></c:forEach>

Casovocênãopossuanenhumcontatoseme-mail,cadastrealgum.

Acessealista-contatos.jsppelonavegadorevejaoresultadofinal.

3. (Opcional)Aoinvésdeutilizardoisifs,useatagc:choose

.

Page 108: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

UmrequisitocomumquetemosnasaplicaçõesWebhojeemdiaécolocarcabeçalhoserodapénaspáginasdonossosistema.Essescabeçalhoserodapéspodemterinformaçõesdaempresa,dosistemaeassimpordiante.Oproblemaéque,nagrandemaioriadasvezes,todasaspáginasdanossaaplicaçãoprecisamteressemesmocabeçalhoerodapé.Comopoderíamosresolverisso?

Uma primeira alternativa e talvez a mais inocente é colocarmos essas informações em todas aspáginasdanossaaplicação,copiandoecolandotodoocabeçalhováriasvezes.

Masoqueaconteceriaseprecisássemosmudarologotipodaempresa?Teríamosquemudartodasaspáginas,oquenãoéumtrabalhoagradável.

Umaalternativamelhorseriaisolarmosessecódigoqueserepeteemtodasaspáginasemumaoutrapágina, por exemplo, cabecalho.jsp e todas as páginas da nossa aplicação, apenas dizem queprecisamdessaoutrapáginanela,atravésdeumatagnova,ac:import.

Para utilizá-la, podemos criar uma pagina com o cabeçalho do sistema, por exemplo, acabecalho.jsp:

<imgsrc="imagens/logomarca.jpg"/>Nomedaempresa

Eumapáginaparaorodapé,porexemplo,rodape.jsp:

Copyright2010-Todososdireitosreservados

Bastaria que, em todas as nossas páginas, por exemplo, nalista-contatos.jsp, colocássemosambasaspáginas,atravésdac:importcomoabaixo:

<%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%><html><body>

<c:importurl="cabecalho.jsp"/>

<jsp:useBeanid="dao"class="br.com.caelum.agenda.dao.ContatoDao"/><table><!--for--><c:forEachvar="contato"items="${dao.lista}"><tr><td>${contato.nome}</td><td>${contato.email}</td><td>${contato.endereco}</td><td>${contato.dataNascimento.time}</td></tr></c:forEach></table>

<c:importurl="rodape.jsp"/>

</body></html>

7.12IMPORTANDOPÁGINAS

.

Page 109: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

1. Vamosprimeirocriaronossocabeçalho,utilizandoologotipodaCaelum.

Vá no Desktop, entre na pasta 21 e copie o diretório imagens para dentro do diretórioWebContentdoseuprojeto.EssediretóriopossuiologotipodaCaelum.

Ou você pode usar o que se encontra em: http://www.caelum.com.br/imagens/base/caelum-ensino-inovacao.png

CriedentrodeWebContentumarquivochamadocabecalho.jspcomologotipodosistema:

<imgsrc="imagens/caelum.png"/><h2>AgendadeContatosdo(a)(Seunomeaqui)</h2><hr/>

Crietambémapáginarodape.jsp:

<hr/>Copyright2010-Todososdireitosreservados

Podemosimportarasduaspáginas(cabecalho.jsperodape.jsp),dentrodanossalista-contatos.jspusandoatagc:importquevimos:

<html><body><%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%>

<c:importurl="cabecalho.jsp"/>

<!--criaalista--><jsp:useBeanid="dao"class="br.com.caelum.agenda.dao.ContatoDao"/><table><!--for--><c:forEachvar="contato"items="${dao.lista}"><tr><td>${contato.nome}</td>

<td><c:iftest="${notemptycontato.email}"><ahref="mailto:${contato.email}">${contato.email}</a></c:if><c:iftest="${emptycontato.email}">E-mailnãoinformado</c:if></td>

<td>${contato.endereco}</td><td>${contato.dataNascimento.time}</td></tr></c:forEach></table>

<c:importurl="rodape.jsp"/></body></html>

7.13EXERCÍCIOS:CABEÇALHOSERODAPÉS

.

Page 110: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Visualize o resultado final acessando no navegador http://localhost:8080/fj21-

agenda/lista-contatos.jsp

Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende

Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!

ConheçaaAluraCursosOnline.

Apesar da nossa listagem de contatos estar bonita e funcional, ela ainda possui problemas, porexemplo, a visualização da data de nascimento. Muitas informações aparecem na data, como horas,minutosesegundos,coisasquenãoprecisamos.

Jáaprendemosanteriormentequeumadas formasquepodemos fazeressa formataçãoemcódigoJava é através da classe SimpleDateFormat, mas não queremos utilizá-la aqui, pois não queremoscódigoJavanonossoJSP.

Paraisso,vamosutilizaroutraTaglibdaJSTLqueéataglibdeformatação,afmt.

Para utilizarmos a taglib fmt, precisamos importá-la, da mesma forma que fizemos com a tagcore,atravésdadiretivadetaglib,comoabaixo:

Agoraéamelhorhoradeaprenderalgonovo

7.14FORMATAÇÃODEDATAS

.

Page 111: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

<%@tagliburi="http://java.sun.com/jsp/jstl/fmt"prefix="fmt"%>

Dentro da taglib fmt, uma das tags que ela possui é a formatDate, que faz com que umdeterminadoobjetodotipojava.util.Datesejaformatadoparaumdadopattern.Então,podemosutilizaratagfmt:formatDatedaseguinteforma:

<fmt:formatDatevalue="${contato.dataNascimento.time}"pattern="dd/MM/yyyy"/>

Repareque,naExpressionLanguagequecolocamosnovalue,hánofinalum.time.Issoporqueo atributo value só aceita objetos do tipo java.util.Date, e nossa data de nascimento é umjava.util.Calendar que possui um método getTime() para chegarmos ao seu respectivojava.util.Date.

COMOFAZERPATTERNSMAISCOMPLICADOS?

Podemos no atributo pattern colocar outras informações com relação ao objetojava.util.Datequequeremosmostrar,porexemplo:

m-Minutoss-SegundosH-Horas(0-23)D-Dianoano,porexemplo,230

Sugerimosquequandoprecisardeformataçõesmaiscomplexas,leiaadocumentaçãodaclasseSimpleDateFormat,aondeseencontraadescriçãodealgunscaracteresdeformatação.

1. Vamosfazeraformataçãodadatadenascimentodosnossoscontatos.

Nalista-contatos.jsp, importeataglibfmtno topodoarquivo.UseoautocompletardoEclipseparateajudaraescrever:

<%@tagliburi="http://java.sun.com/jsp/jstl/fmt"prefix="fmt"%>

Troque a Expression Language que mostra a data de nascimento para passar pela tagformatDateabaixo:

<fmt:formatDatevalue="${contato.dataNascimento.time}"pattern="dd/MM/yyyy"/>

Acesseapáginapelonavegadorevejaoresultadofinal:

7.15 EXERCÍCIOS: FORMATANDO A DATA DE NASCIMENTO DOSCONTATOS

.

Page 112: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Muitas vezes trabalhar com links em nossa aplicação é complicado. Por exemplo, no arquivocabecalho.jspincluímosumaimagemchamadacaelum.pngqueestánapastaimagens.

IncluímosestaimagemcomatagHTML<img>utilizandoocaminhoimagens/caelum.pngqueéumcaminhorelativo,ouseja,seocabecalho.jspestivernaraizdoprojeto,oarquivocaelum.pngdeveráestaremumapastachamadaimagenstambémnaraizdoprojeto.

Utilizar caminhos relativos muitas vezes é perigoso. Por exemplo, se colocarmos o arquivocabecalho.jspemumdiretóriochamadoarquivos_comuns, a imagemque tínhamosadicionadoserá procurada em um diretório imagens dentro do diretório arquivos_comuns . Resultado, aimagemnãoseráexibida.

Poderíamos resolver isso utilizando um caminho absoluto. Ao invés de adicionarmos a imagemutilizando o caminho imagens/caelum.png , poderíamos usar /imagens/caelum.png . Só queutilizandoa/elenãovaiparaaraizdaminhaaplicaçãoesimparaaraizdotomcat,ouseja,eleiriaprocuraraimagemcaelum.pngemumdiretórioimagensnaraizdotomcat,quandonaverdadeodiretórionemmesmoexiste.

Poderíamos resolver isso utilizando o caminho /fj21-tarefas/imagens/caelum.png . Nossoproblemaseriaresolvido,entretanto,sealgumdiamudássemosocontextodaaplicaçãoparatarefasaimagemnãoseriaencontrada,poisdeixamosfixononossojspqualeraocontextodaaplicação.

Pararesolveresteproblema,podemosutilizaratag<c:url>daJSTL.Ousodelaéextremamentesimples.Paraadicionarmosologotipodacaelumnocabecalho.jsp,faríamosdaseguintemaneira:

<c:urlvalue="/imagens/caelum.png"var="imagem"/><imgsrc="${imagem}"/>

Oudeumaformaaindamaissimples:

7.16PARASABERMAIS:LINKSCOM<C:URL>

.

Page 113: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

<imgsrc="<c:urlvalue="/imagens/caelum.png"/>"/>

OHTMLgeradopeloexemploseria:<imgsrc="fj21-tarefas/imagens/caelum.png"/>.

Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.

CasadoCódigo,ebookcompreçodeebook.

1.

Abraoarquivocabecalho.jspealtere-oadicionandoatag<c:url>:

<imgsrc="<c:urlvalue="/imagens/caelum.png"/>"/>

Como vamos usar a JSTL também nesse novo arquivo de cabeçalho, não deixe de incluir adeclaraçãodataglibnoiníciodoarquivo.(ocomando<%@taglib...%>semelhanteaousadonalistagem)

Visualize o resultado acessando no navegador http://localhost:8080/fj21-agenda/lista-contatos.jsp

Aimagemcaelum.pngcontinuaaparecendonormalmente

Se,algumdia,alterarmosocontextodanossaaplicação,ocabeçalhocontinuariaexibindoaimagemdamaneiracorreta.Usandoatag<c:url>ficamoslivresparautilizarcaminhosabsolutos.

AJSTLpossuialémdastagsquevimosaqui,muitasoutras,eparadiversasfinalidades.AbaixoestáumresumocomalgumasdasoutrastagsdaJSTL:

c:catch-blocodotipotry/catchc:forTokens-foremtokens(ex:"a,b,c"separadosporvírgula)

EditoraCasadoCódigocomlivrosdeumaformadiferente

7.17EXERCÍCIOSOPCIONAIS:CAMINHOABSOLUTO

7.18PARASABERMAIS:OUTRASTAGS

.

Page 114: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

c:out-saídac:param-parâmetroc:redirect-redirecionamentoc:remove-remoçãodevariávelc:set-criaçãodevariável

Leia detalhes sobre as taglibs da JSTL (JavaDoc das tags e classes) em:http://java.sun.com/products/jsp/jstl/reference/api/index.html

.

Page 115: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO8

"Euapenasinventoeesperoqueoutrosapareçamprecisandodoqueinventei"--R.BuckminsterFuller

Aotérminodessecapítulo,vocêserácapazde:

criarsuaprópriataglibatravésdetagfiles;encapsularcódigosrepetitivosemtags;conheceroutrastaglibsexistentesnomercado.

Émuitocomum,nomomentoemqueestamosdesenvolvendonossosJSPs,cairmosemsituaçõesemquefazemosmuitarepetiçãodecódigo.Porexemplo,semprequecriamosumacaixadetexto,podemosassociá-lacomumlabel,atravésdoseguintecódigo:

<labelfor="nomeContato">Nome</label><inputtype="text"id="nomeContato"name="nome"/>

Essecódigofazcomque,sevocêclicarnapalavraNome,passeofocoparaocampodetexto.Masreparequetemosalgoqueserepetenessetrecho,queéoiddoinputeoatributofordolabel.Semudarmosoiddoinputteremosquerefletiressaalteraçãonofordolabel.Alémdisso,temosquesempreescrevertodoessecódigo.

Não seria mais simples escrevermos <campoTexto id="nomeContato" name="nome"

label="Nome:"/>etodoaquelecódigosergeradoparanós?

UmoutroexemplopoderiaserquandoutilizamoscomponentesquedependemdeJavascript,comoumcampoque,aoganharofoco,mostraumcalendário.Todavezquetemosqueusaressecomponente,precisamosescreverumpedaçodecódigoJavaScript.Porquenãoencapsulartudoissoemnovastags

TAGSCUSTOMIZADASCOMTAGFILES

8.1PORQUEEUPRECISARIADEOUTRASTAGSALÉMDAJSTL?

.

Page 116: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

customizadas?

Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.

CasadoCódigo,LivrosdeTecnologia.

VamospegarumexemplopráticodepossívelusodeJavaScriptnonossosistema.Temosnocadastrodecontatos,umcampoparadatadenascimento.Masatéomomento,ousuárioprecisadigitaradatanamãoseguindooformatoqueespecificamos.

EsemostrássemosumcalendárioemJavaScriptparaousuárioescolheradataapenasclicandoemumcomponentejápronto?

Paraconseguirmosessecomportamento,podemosutilizarporexemplooscomponentesvisuaisdojQuery,queéumabibliotecacomalgunscomponentesJavaScript.

Entreosdiversoscomponentesqueo jQuerypossui,umdeleséocampocomcalendário,tambémconhecidopordatepicker. Parautilizarmosodatepicker do jQuery, precisamos criar uminput detextosimpleseassociá-locomumafunçãoJavaScript,comonocódigoseguinte:

<inputid="dataNascimento"type="text">

<script>$("#dataNascimento").datepicker();</script>

AfunçãoJavaScriptfazcomqueoinputcujoidédataNascimentosejaumcalendário.

Imagine se toda hora que fossemos criar um campo de data tivéssemos que escrever esse códigoJavaScript?Aschancesde errarmosesse códigoé razoável,masaindaassim,opiorpontoainda seriaperdertempoescrevendoumcódigorepetitivo,sendoquepoderíamosobteromesmoresultadoapenasescrevendo:

<campoDataid="dataNascimento"/>

Seuslivrosdetecnologiaparecemdoséculopassado?

8.2CALENDÁRIOSCOMJQUERY

.

Page 117: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Qualabordagemémaissimples?

Paraquepossamosteratag<campoData>precisaremoscriá-la.UmadasformasquetemosdecriarnossasprópriastaglibsécriandoumarquivocontendoocódigoquenossaTaglibgerará.Essesarquivoscontendoocódigodastagssãoconhecidoscomotagfiles.

Tagfiles nada mais são do que pedaços de JSP, com a extensão .tag, contendo o código quequeremosqueanossataggere.

VamoscriarumarquivochamadocampoData.tagcomocódigoquequeremosgerar.

<inputid="dataNascimento"name="dataNascimento">

<script>$("#dataNascimento").datepicker();</script>

Mas essa nossa tag está totalmente inflexível, pois o id e o nome do campo estão escritosdiretamente dentro da tag. O que aconteceria se tivéssemos dois calendários dentro do mesmoformulário?Ambosteriamomesmoname.

Precisamosfazercomqueanossatagrecebaparâmetros.Podemosfazerissoadicionandoadiretiva<%@attribute%>nanossa tag, comosparâmetrosname representandoonomedo atributo e oparâmetrorequiredcomosvalorestrueoufalse,indicandoseoparâmetroéobrigatórioounão.

<%@attributename="id"required="true"%>

Reparecomoésimples.Bastadeclararessadiretivadeatributonocomeçodonossotagfileetemosacapacidade de receber um valor quando formos usar a tag. Imagine usar essa tag nova no nossoformulário:

<campoDataid="dataNascimento"/>

Já que nossa tag sabe receber parâmetros, basta usarmos esse parâmetro nos lugares adequadosatravésdeexpressionlanguage,comonocódigoabaixo:

<%@attributename="id"required="true"%>

<inputid="${id}"name="${id}"type="text"><script>$("#${id}").datepicker();</script>

Parausarnossatag,assimcomonasoutrastaglibs,precisamosimportarnossostagfiles.Comonãoestamos falando de taglibs complexas como a JSTL,mas simde pequenos arquivos de tags do nossopróprioprojeto,vamosreferenciardiretamenteapastaondenossosarquivos.tagestãosalvos.

Nossos tagfilesdevemficarnapastaWEB-INF/tags/dentrodoprojetoe,nomomentodeusaras

8.3CRIANDOMINHASPRÓPRIASTAGSCOMTAGFILES

.

Page 118: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

tags,vamosimportarcomamesmadiretiva<%@taglib%>queusamosantes.Adiferençaéque,alémdereceberoprefixodanovataglib,indicamosapastaWEB-INF/tags/comolocalizaçãodastags:

<%@taglibtagdir="/WEB-INF/tags"prefix="caelum"%>

Aquidecidimosimportaranovataglibsoboprefixocaelum,maspoderiaserqualquernome.Assim,podemosusaratagcomo:

<caelum:campoDataid="dataNascimento"/>

Repare que o nome da nossa nova Tag, é o mesmo nome do arquivo que criamos, ou seja,campoData.tagseráutilizandocomo<caelum:campoData>.

UTILIZANDOBIBLIOTECASJAVASCRIPT

ParapodermosutilizarbibliotecasJavascriptemnossaaplicaçãoprecisamosimportaroarquivo.jsquecontémabiblioteca.

Para fazermos essa importação, basta que no cabeçalho da página que queremos utilizar oJavascript,ouseja,naTaghead,declaremososeguinte:

<head><scriptsrc="js/arquivo.js"></script></head>

ParasabermaissobreJavaScript,temososcursosdeWebdaCaelum:

http://www.caelum.com.br/cursos-web-front-end/

.

Page 119: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

UTILIZANDOESTILOSEMCSS

Para que possamos construir uma interface agradável para o usuário, na maioria das vezessomenteHTMLnãoésuficiente.

Podemos também utilizar CSS (Cascading Stylesheet), que nada mais é que um arquivocontendo as definições visuais para sua página. Esses arquivos são distribuídos com a extensão.csseparaquepossamosusá-los,precisamostambémimportá-losdentrodatagheaddanossapáginaquevaiutilizaressesestilos.Comoabaixo:

<head><linkhref="css/meuArquivo.css"rel="stylesheet"></head>

A Caelum oferece os treinamentosWD-43 eWD-47 para quem quer dominar as melhorestécnicas de desenvolvimento Web com semântica perfeita, estilos CSS poderosos e JavaScriptscorretosefuncionais.

http://www.caelum.com.br/cursos-web-front-end/

1. Vamos criar nossa tag para o campo de calendário com datepicker. Para isso vamos utilizar abibliotecajavascriptjQuery.

VáaoDesktop,eentrenapasta21;

Copieosdiretóriosjsecssecole-osdentrodeWebContentnoseuprojeto;

EMCASA

Sevocêestiver fazendodecasa,podeacharessesdoisarquivosnopacotedo JQueryUIem:http://jqueryui.com/download

2. QueremosusarJSTLnapáginadeadicionarcontatos,aadiciona-contato.html.Mastemosumproblema. Não podemos utilizar as tags ou expression language em uma página HTML . Pararesolvermosisso,vamostrocarsuaextensãopara.jsp

Clique com o botão direito em cima do arquivoadiciona-contato.html e escolha a opçãoRenameetroqueaextensãodehtmlparajsp,dessaformaoarquivosechamaráadiciona-

8.4EXERCÍCIOS:CRIANDONOSSAPRÓPRIATAGPARACALENDÁRIO

.

Page 120: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

contato.jsp.

3. Tambémvamosimportarocabeçalhoeorodapénessapágina,portanto,vamosusarotaglibJSTLcore.

Adicionenotopodapágina:

<%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%>

Vamosimportarocabeçalho,depoisdatag<body>adicione:

<c:importurl="cabecalho.jsp"/>

Faltaorodapé.Antesdefecharotagbody(</body>)adicione:

<c:importurl="rodape.jsp"/>

Cuidadoparanãoapagaroformulário,precisaremosdelemaisparafrente.

Acesse http://localhost:8080/fj21-agenda/adiciona-contato.jsp e verifique o resultado com ocabeçalhoerodapé.

4. PrecisamosimportarojQuerynapáginaadiciona-contato.jsp.Paraissoadicionedepoisdatag<html>eantesdatag<body>,osestilosCSSeosJavascripts

<html><head><linkhref="css/jquery.css"rel="stylesheet"><scriptsrc="js/jquery.js"></script><scriptsrc="js/jquery-ui.js"></script></head>

<body>

.

Page 121: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

<!--Restantedapáginaaqui-->

5. Vamoscriaranossatagparaocalendário.

DentrodeWEB-INFcrieumdiretóriochamadotags.

CrieumarquivochamadocampoData.tagdentrodeWEB-INF/tags/:

<%@attributename="id"required="true"%>

<inputtype="text"id="${id}"name="${id}"/><script>$("#${id}").datepicker({dateFormat:'dd/mm/yy'});</script>

Para utilizá-la, vamos voltar para o adiciona-contato.jsp e junto à declaração da Taglibcore,vamosimportarnossanovatag:

<%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%><%@taglibtagdir="/WEB-INF/tags"prefix="caelum"%>

Bastatrocarmosoinputdadatadenascimentopelanossanovatag:

<formaction="adicionaContato">Nome:<inputtype="text"name="nome"/><br/>E-mail:<inputtype="text"name="email"/><br/>Endereço:<inputtype="text"name="endereco"/><br/>DataNascimento:<caelum:campoDataid="dataNascimento"/><br/>

<inputtype="submit"value="Gravar"/></form>

Recarregue a página adiciona-contato.jsp e clique no campo da data de nascimento. Ocalendáriodeveseraberto,escolhaumadataefaçaagravaçãodocontato.

.

Page 122: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Verifiqueocódigofontegerado,ereparequeoJavascriptdocalendárioeoinputforamgeradosparanósatravésdenossaTaglib.

6. (opcional)ConsulteadocumentaçãodocomponentedatepickerdojQueryUIparavermaisopções.Vocêpodeacessá-laem:http://jqueryui.com/demos/datepicker/

Consulte,porexemplo,asopçõeschangeYearechangeMonth paramostrarmenusmais fáceisparaescolheroanoeomês.Hámuitasoutrasopçõestambém.

Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende

Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!

ConheçaaAluraCursosOnline.

Muitosdosproblemasdodiaadiaquenóspassamos,alguémjápassouantes,portanto,muitasdasvezes, pode acontecer de já existir uma Taglib que resolva o mesmo problema que você pode estarpassando. Portanto, recomendamos que antes de criar a suaTaglib, sempre verifique se já não existealgumaqueresolvaseuproblema.

OmercadoatualmentepossuiváriasTaglibsdisponíveis,eparadiversasfunções,algumasdasmaisconhecidassão:

Displaytag: É uma Taglib para geração fácil de tabelas, e pode ser encontrada emhttp://displaytag.sf.net

Cewolf:ÉumaTaglibparageraçãodegráficosnassuaspáginasetambémpodeserencontradaem:http://cewolf.sourceforge.net/new/

Waffle Taglib: Tags para auxiliar na criação de formulários HTML que é encontrada em:http://waffle.codehaus.org/taglib.html

Agoraéamelhorhoradeaprenderalgonovo

8.5PARASABERMAIS:OUTRASTAGLIBSNOMERCADO

8.6DESAFIO:COLOCANDODISPLAYTAGNOPROJETO

.

Page 123: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

1. Adicioneadisplaytagnoseuprojetoparafazeralistagemdoscontatos.

.

Page 124: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO9

"Ensinaréaprenderduasvezes."--JosephJoubert

Nessecapítulo,vocêaprenderá:

OpadrãoarquiteturalMVC;AconstruirumframeworkMVCsimples.

ColocartodoHTMLdentrodeumaServletrealmentenãonospareceamelhorideia.Oqueacontecequando precisamos mudar o design da página? O designer não vai saber Java para editar a Servlet,recompilá-laecolocá-lanoservidor.

ImagineusarapenasJSP.Ficaríamoscommuitoscriptlet,queémuitodifícildedarmanutenção.

Umaideiamaisinteressanteéusaroqueébomdecadaumdosdois.

OJSPfoifeitoapenasparaapresentaroresultado,eelenãodeveriafazeracessosabancodedadosenemfazerainstanciaçãodeobjetos.IssodeveriaestaremcódigoJava,naServlet.

O ideal então é que a Servlet faça o trabalho árduo, a tal da lógica de negócio. E o JSP apenasapresentevisualmenteosresultadosgeradospelaServlet.AServletficariaentãocomalógicadenegócios(ouregrasdenegócio)eoJSPtemalógicadeapresentação.

ImagineocódigodométododaservletAdicionaContatoServletquefizemosantes:

protectedvoidservice(HttpServletRequestrequest,HttpServletResponseresponse){

//logSystem.out.println("Tentandocriarumnovocontato...");

//acessaobeanContatocontato=newContato();//chamaossetters...

//adicionaaobancodedadosContatoDaodao=newContatoDao();dao.adiciona(contato);

MVC-MODELVIEWCONTROLLER

9.1SERVLETOUJSP?

.

Page 125: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

//ok....visualizaçãoout.println("<html>");out.println("<body>");out.println("Contato"+contato.getNome()+"adicionadocomsucesso");out.println("</body>");out.println("</html>");

}

Repare que, no final do nossométodo,misturamos o códigoHTML com Java. O que queremosextrairdocódigoacimaéjustamenteessasúltimaslinhas.

Seriamuitomais interessanteparaoprogramadoreparaodesigner terumarquivo JSPchamadocontato-adicionado.jspapenascomoHTML:

<html><body>Contato${param.nome}adicionadocomsucesso</body></html>

Buscamosumaformaderedirecionarasrequisições,capazdeencaminharessarequisiçãoparaumoutrorecursodoservidor:porexemploindodeumaservletparaumJSP.

Para isso, fazemosodispatchdasrequisições,paraqueo JSPsósejarenderizadodepoisquesuasregrasdenegócio,dentrodeumaservletporexemplo,foramexecutadas.

.

Page 126: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende

Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!

ConheçaaAluraCursosOnline.

PoderíamosmelhoraranossaaplicaçãosetrabalhássemoscomocódigoJavanaservleteoHTMLapenasnoJSP.

A API de Servlets nos permite fazer tal redirecionamento. Basta conhecermos a URL quequeremosacessarepodemosusarumobjetoRequestDispatcherparaacessaroutrorecursoWeb,sejaesserecursoumapáginaJSPouumaservlet:

RequestDispatcherrd=request.getRequestDispatcher("/contato-adicionado.jsp");rd.forward(request,response);

PodemosfacilmenteexecutaralógicadenossaaplicaçãoWebemumaservleteentãoredirecionarparaumapáginaJSP,ondevocêpossuiseucódigoHTMLetagsqueirãomanipularosdadostrazidospelaservlet.

FORWARDEINCLUDE

Ométodo forward só pode ser chamado quando nada foi ainda escrito para a saída. Nomomentoquealgoforescrito,ficaimpossívelredirecionarousuário,poisoprotocoloHTTPnãopossuimeiosdevoltaratrásnaquiloquejáfoienviadoaocliente.

ExisteoutrométododaclasseRequestDispatcherquerepresentaainclusãodepáginaenãooredirecionamento.Essemétodosechamaincludeepodeserchamadoaqualquerinstanteparaacrescentaraoresultadodeumapáginaosdadosdeoutra.

Agoraéamelhorhoradeaprenderalgonovo

9.2REQUESTDISPATCHER

9.3EXERCÍCIOS:REQUESTDISPATCHER

.

Page 127: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Vamos evoluir nossa adição de contatos antes puramente usando Servlets para usar oRequestDispatcher.

1. Seguindo a separação aprendida nesse capítulo, queremos deixar em um JSP separado aresponsabilidadedemontaroHTMLaserdevolvidoparaousuário.

Crieentãoumnovoarquivocontato-adicionado.jspnapastaWebContent:

<html><body>Contato${param.nome}adicionadocomsucesso</body></html>

2. Altere suaservletAdicionaContatoServlet paraque, após a execuçãoda lógicadenegócios, ofluxodarequisiçãosejaredirecionadoparanossonovoJSP.

Remova no fim da classe o código quemonta a saídaHTML (as chamadas de out.println).VamossubstituirporumachamadaaoRequestDispatchereexibiromesmoresultadousandooJSPquecriamos.Achamadaficanofinaldenossaservlet:

RequestDispatcherrd=request.getRequestDispatcher("/contato-adicionado.jsp");rd.forward(request,response);

3. TesteaURL:http://localhost:8080/fj21-agenda/adiciona-contato.jsp

.

Page 128: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Percebaquejáatingimosumresultadoquenãoerapossívelanteriormente.

MuitosprojetosantigosqueforamescritosemJavautilizavamsomenteJSPouservletseoresultadoera assustador: diferentes linguagens misturadas num único arquivo, tornando difícil a tarefa demanutençãodo código.Como conteúdomostrado até essemomento, é possível escrever um códigocommuitomaisqualidade:cadatecnologiacomasuaresponsabilidade.

Aquitemosváriasservletsacessandoobancodedados,trabalhandocomosDAOsepedindoparaque o JSP apresente esses dados, o diagrama a seguir mostra a representação doAdicionaContatoServletapósamodificaçãodoexercícioanterior.

Temos o problema de ter muitas servlets. Para cada lógica de negócios, teríamos uma servletdiferente,quesignificaváriasportasdeentradas,algoabominávelemumprojetodeverdade.Imaginedezclassesdemodelo,cincológicasdiferentes,issototalizacinquentaformasdiferentesdeacesso.

EsequiséssemosfazerumLogdaschamadasdessas lógicas?TeríamosqueespalharocódigoparaesseLogportodanossaaplicação.

Sabemosdaexistênciadeferramentasparagerartalcódigoautomaticamente,masissonãoresolveoproblemadacomplexidadedeadministrartantasservlets.

Utilizaremosumaideiaquediminuirábastanteonúmerodeportasdeentradasemnossaaplicação:colocar tudo emuma Servlet só e, de acordo comos parâmetros que o cliente usar, decidimos o queexecutar.TeríamosaíumaServletparacontrolaressaparte,comooesboçoabaixo:

//TodasaslógicasdentrodeumaServlet@WebServlet("/sistema")publicclassSistemaTodoServletextendsHttpServlet{

protectedvoidservice(HttpServletRequestrequest,

Resultado

9.4MELHORANDOOPROCESSO

.

Page 129: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

HttpServletResponseresponse){

Stringacao=request.getParameter("logica");ContatoDaodao=newContatoDao();

if(acao.equals("AdicionaContato")){Contatocontato=newContato();contato.setNome(request.getParameter("nome"));contato.setEndereco(request.getParameter("endereco"));contato.setEmail(request.getParameter("email"));dao.adiciona(contato);

RequestDispatcherrd=request.getRequestDispatcher("/contato-adicionado.jsp");rd.forward(request,response);}elseif(acao.equals("ListaContatos")){//buscaalistanoDAO//despachaparaumjsp}elseif(acao.equals("RemoveContato")){//fazaremoçãoeredirecionaparaalista}}}

Poderíamos acessar no navegador algo como http://localhost:8080/<contexto>/sistema?logica=AdicionaContato.

Masparacadaaçãoteríamosumif/elseif,tornandoaServletmuitogrande,comtodaregradenegóciodosistemainteiro.

Podemosmelhorar fazendo refactoring de extrair métodos. Mas continuaríamos com uma classemuitogrande.

Seriamelhorcolocarcadaregradenegócio(comoinserircontato,removercontato, fazerrelatórioetc)emumaclasseseparada.Cadaação(regradenegócio)emnossaaplicaçãoestariaemumaclasse.

Então vamos extrair a nossa lógica para diferentes classes, para quenossa Servlet pudesse ter umcódigomaisenxutocomoesse:

if(acao.equals("AdicionaContato")){newAdicionaContato().executa(request,response);}elseif(acao.equals("ListaContato")){newListaContatos().executa(request,response);}

EteríamosclassesAdicionaContato,ListaContatos,etccomummétodo(digamos,executa)quefazalógicadenegóciosapropriada.

Porém, a cada lógica nova, lógica removida, alteração etc, temos que alterar essa servlet. Isso étrabalhosoemuitopropensoaerros.

Reparedoispontosnocódigoacima.Primeiroqueelepossuiomesmocomportamentodeswitch!EswitchemJavaquasesemprepodesersubstituídocomvantagemporpolimorfismo,comoveremosaseguir.Outraquestãoéquerecebemoscomoparâmetrojustamenteonomedaclassequechamamos

.

Page 130: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

emseguida.

Vamostentargeneralizarentão,queremosexecutaroseguintecódigo:

StringnomeDaClasse=request.getParameter("logica");newnomeDaClasse().executa(request,response);

Queremospegar onomeda classe a partir doparâmetro e instanciá-la. Entretantonãopodemos,poisnomeDaClasseéonomedeumavariáveleocódigoacimanãoéválido.Onossoproblemaéquesó sabemos o que vamos instanciar em tempo de execução (quando o parâmetro chegar) e não emtempodecompilação.

Masapartirdonomedaclassenóspodemosrecuperarumobjetoquerepresentaráasinformaçõescontidas dentro daquela classe, como por exemplo atributos, métodos e construtores. Para queconsigamosesseobjeto,bastautilizarmosaclasseClassinvocandoométodoforNameindicandodequalclassequeremosumarepresentação.IssonosretornaráumobjetodotipoClassrepresentandoaclasse.Comoabaixo:

StringnomeDaClasse="br.com.caelum.mvc.logica."+request.getParameter("logica");Classclasse=Class.forName(nomeDaClasse);

Ótimo,podemosterumarepresentaçãodeAdicionaContatooudeListaContato eassimpordiante.Masprecisamosdealgumaformainstanciaressasclasses.

Já queumadas informações guardadaspeloobjetodo tipoClass é o construtor, nóspodemosinvocá-loparainstanciaraclasseatravésdométodonewInstance.

Objectobjeto=classe.newInstance();

Ecomochamarométodoexecuta?ReparequeotipodeclaradodonossoobjetoéObject.Dessaforma,nãopodemoschamarométodoexecuta.Umaprimeiraalternativaseríamosfazernovamenteif/elseparasabermosqualéalógicaqueestásendoinvocada,comoabaixo:

StringnomeDaClasse="br.com.caelum.mvc."+request.getParameter("logica");Classclasse=Class.forName(nomeDaClasse);

Objectobjeto=classe.newInstance();

if(nomeDaClasse.equals("br.com.caelum.mvc.AdicionaContato")){((AdicionaContato)objeto).executa(request,response);}elseif(nomeDaClasse.equals("br.com.caelum.mvc.ListaContatos")){((ListaContatos)objeto).executa(request,response);}//eassimpordiante

Masestamosvoltandoparaoif/elsequeestávamosfugindonocomeço.Issonãoébom.Todoesseif/elseéocasionadoporcontadotipoderetornodométodonewInstanceserObjectenóstratarmoscadaumadenossaslógicasatravésdeumtipodiferente.

Repareque,tantoAdicionaContatoquantoListaContatos,sãoconsideradasLogicasdentro

.

Page 131: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

donossocontexto.OquepodemosfazerentãoétratarambascomoalgoquesigaocontratodeLogicaimplementandoumainterfacedemesmonomequedeclareométodoexecuta:

publicinterfaceLogica{voidexecuta(HttpServletRequestreq,HttpServletResponseres)throwsException;}

PodemossimplificarnossaServletparaexecutaralógicadeformapolimórficae,tudoaquiloquefazíamosemaproximadamente8linhasdecódigo,podemosfazeremapenas2:

Logicalogica=(Logica)classe.newInstance();logica.executa(request,response);

Dessaforma,umalógicasimplesparalogaralgonoconsolepoderiaserequivalentea:

publicclassPrimeiraLogicaimplementsLogica{publicvoidexecuta(HttpServletRequestreq,HttpServletResponseres)throwsException{System.out.println("Executandoalogicaeredirecionando...");RequestDispatcherrd=req.getRequestDispatcher("primeira-logica.jsp");rd.forward(req,res);}}

Alguém precisa controlar então que ação será executada para cada requisição, e que JSP seráutilizado.Podemosusaruma servlet para isso, e então elapassa a ser a servlet controladoradanossaaplicação,chamandoaaçãocorretaefazendoodispatchparaoJSPdesejado.

Melhorando aindamais nossa servlet controladora, poderíamos deixar nela a responsabilidade denos redirecionarparaumapágina JSPouparaqualqueroutra lógicaao finaldaexecuçãodas lógicas,bastandoqueométodoexecutaretorneumsimplesString,eliminandotodaarepetiçãodecódigoRequestDispatcher.

ComeçaríamosalterandoaassinaturadométodoexecutadainterfaceLogicaqueeravoideagoraretornaráString:

publicinterfaceLogica{Stringexecuta(HttpServletRequestreq,HttpServletResponseres)throwsException;

}

DepoisfaríamosaslógicasretornaremumStringcomonomedo.jspquedeveserchamadoaofinaldassuasexecuções.

publicclassPrimeiraLogicaimplementsLogica{publicStringexecuta(HttpServletRequestreq,HttpServletResponseres)throwsException{System.out.println("Executandoalogicaeredirecionando...");return"primeira-logica.jsp";

.

Page 132: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

}}

Por fim, a servlet controladora deve receber esse String e implementar o código deRequestDispatcher:

@WebServlet("/sistema")publicclassControllerServletextendsHttpServlet{

protectedvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{

Stringparametro=request.getParameter("logica");StringnomeDaClasse="br.com.caelum.mvc.logica."+parametro;

try{Class<?>classe=Class.forName(nomeDaClasse);Logicalogica=(Logica)classe.newInstance();

//RecebeoStringapósaexecuçãodalógicaStringpagina=logica.executa(request,response);

//FazoforwardparaapáginaJSPrequest.getRequestDispatcher(pagina).forward(request,response);

}catch(Exceptione){thrownewServletException("Alógicadenegócioscausouumaexceção",e);}}}

Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.

CasadoCódigo,ebookcompreçodeebook.

NotequeométodoforNamedaclasseClassretornaumobjetodotipoClass,masesseobjetoénovo?Foirecicladoatravésdeumcachedessesobjetos?

EditoraCasadoCódigocomlivrosdeumaformadiferente

9.5RETOMANDOODESIGNPATTERNFACTORY

.

Page 133: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

ReparequenãosabemosoqueaconteceexatamentedentrodométodoforName,masaoinvocá-loeaexecuçãoocorrercomsucesso,sabemosqueaclassequefoipassadaemformadeStringfoilidaeinicializadadentrodavirtualmachine.

Na primeira chamada aClass.forName para determinada classe, ela é inicializada. Já em umachamadaposterior,Class.forNamedevolveaclasseque jáfoi lidaeestánamemória, tudoissosemqueafeteonossocódigo.

Esse exemplo do Class.forName é ótimo para mostrar que qualquer código que isola ainstanciaçãoatravésdealgumrecursodiferentedoconstrutoréumafactory.

1. Crieasuainterfacenopacotebr.com.caelum.mvc.logica:

publicinterfaceLogica{Stringexecuta(HttpServletRequestreq,HttpServletResponseres)throwsException;}

2. CrieumaimplementaçãodainterfaceLogica,nossaclassePrimeiraLogica,tambémnopacotebr.com.caelum.mvc.logica:

publicclassPrimeiraLogicaimplementsLogica{publicStringexecuta(HttpServletRequestreq,HttpServletResponseres)throwsException{

System.out.println("Executandoalogica...");

System.out.println("RetornandoonomedapáginaJSP...");return"primeira-logica.jsp";

}}

3. FaçaumarquivoJSPchamadoprimeira-logica.jspdentrododiretórioWebContent:

<html><body><h1>Páginadanossaprimeiralógica</h1></body></html>

4. VamosescrevernossaServletquecoordenaráofluxodanossaaplicação.

CriesuaservletchamadaControllerServletnopacotebr.com.caelum.mvc.servlet:

@WebServlet("/mvc")publicclassControllerServletextendsHttpServlet{protectedvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{

9.6 EXERCÍCIOS: CRIANDO NOSSAS LÓGICAS E A SERVLET DECONTROLE

.

Page 134: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Stringparametro=request.getParameter("logica");StringnomeDaClasse="br.com.caelum.mvc.logica."+parametro;

try{Classclasse=Class.forName(nomeDaClasse);

Logicalogica=(Logica)classe.newInstance();Stringpagina=logica.executa(request,response);

request.getRequestDispatcher(pagina).forward(request,response);

}catch(Exceptione){thrownewServletException("Alógicadenegócioscausouumaexceção",e);}}}

5. Testeaurlhttp://localhost:8080/fj21-agenda/mvc?logica=PrimeiraLogica

1. Crie uma nova classe chamada RemoveContatoLogic no mesmo pacotebr.com.caelum.mvc.logica.DevemosimplementarainterfaceLogicaedurantesuaexecuçãoreceberemosumidpelorequesteremoveremosocontatonobancoapartirdesteid.

publicclassRemoveContatoLogicimplementsLogica{

publicStringexecuta(HttpServletRequestreq,HttpServletResponseres)throwsException{

longid=Long.parseLong(req.getParameter("id"));

Contatocontato=newContato();contato.setId(id);

ContatoDaodao=newContatoDao();dao.exclui(contato);

System.out.println("Excluindocontato...");

return"lista-contatos.jsp";}

}

2. Napáginalista-contatos.jsp, vamos acrescentar uma colunana tabela que lista os contatos

9.7EXERCÍCIOS:CRIANDOUMALÓGICAPARAREMOVERCONTATOS

.

Page 135: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

comumlinkchamandoalógicaderemoçãoepassandooiddocontato:

<!--códigoomitido-->

<c:forEachvar="contato"items="${dao.lista}"><tr>

<!--códigoomitido-->

<td><ahref="mvc?logica=RemoveContatoLogic&id=${contato.id}">Remover</a></td></tr></c:forEach>

<!--códigoomitido-->

3. Teste a logica de remoção acessando http://localhost:8080/fj21-agenda/lista-

contatos.jspeclicandoemalgumlinkRemover.

AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,

Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex-aluno daCaelumtem15%dedescontonestelink!

ConheçaoscursosonlineAlura.

Agora que todo nosso processamento está passando pela Servlet controladora e conseguimosorganizarnossocódigoemcamadasbemdefinidas,nosdeparamoscomumasituaçãoqueaindaestáumpoucodistantedoideal.

Se olharmos a página lista-contatos.jsp veremos que para fazer a listagem dos contatosfuncionar estamos criando uma instância da classe ContatoDao para utilizá-la depois no<c:forEach>recuperandoumalistadecontatos.

<jsp:useBeanid="dao"class="br.com.caelum.agenda.dao.ContatoDao"/>

<table><c:forEachvar="contato"items="${dao.lista}"><tr><td>${contato.nome}</td>

JáconheceoscursosonlineAlura?

9.8FAZENDOALÓGICAPARALISTAROSCONTATOS

.

Page 136: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

<!--códigoomitido--></tr></c:forEach></table>

Instanciar objetos da camada Model na camada View não é considerada uma boa prática naarquiteturaMVC(antipattern).

Podemos resolver facilmente isso tranferindo essa responsabilidade demontar a lista de contatosparaumalógicaListaContatosLogicedepoispassá-laprontadiretoparaoJSPpelorequest.

Paraguardarmosalgonarequisição,precisamosinvocarométodo.setAttribute()norequest.Passamos para essemétodo uma identificação para o objeto que estamos guardando na requisição etambémpassamosopróprioobjetoparaserguardadonorequest.

publicclassListaContatosLogicimplementsLogica{

publicStringexecuta(HttpServletRequestreq,HttpServletResponseres)throwsException{

//MontaalistadecontatosList<Contato>contatos=newContatoDao().getLista();

//Guardaalistanorequestreq.setAttribute("contatos",contatos);

return"lista-contatos.jsp";}}

Agora é só ajustar a página lista-contatos.jsp para não instanciar mais o ContatoDao ,removendoalinha<jsp:useBeanid="dao"class="br.com.caelum.agenda.dao.ContatoDao"/>,edepoisfazercomqueo<c:forEach>usealistadecontatosquefoicolocadanorequest:

<c:forEachvar="contato"items="${contatos}">

1. Crie uma nova classe chamada ListaContatosLogic no mesmo pacotebr.com.caelum.mvc.logica. Devemos implementar nela a interface Logica e, durante suaexecuçãovamoscriarumalistadecontatosatravésdeumainstânciadaclasseContatoDao,guardá-lanorequesteretornarparaaservletcontroladora:

publicclassListaContatosLogicimplementsLogica{

publicStringexecuta(HttpServletRequestreq,HttpServletResponseres)throwsException{

List<Contato>contatos=newContatoDao().getLista();

req.setAttribute("contatos",contatos);

return"lista-contatos.jsp";}

9.9EXERCÍCIOS:LÓGICAPARALISTARCONTATOS

.

Page 137: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

}

2. Agora,vamosmodificarapáginalista-contatos.jspparanãoinstanciarmaisContatoDaonaView, removendo a linha <jsp:useBean id="dao"

class="br.com.caelum.agenda.dao.ContatoDao"/>,ealteraro<c:forEach>parausaralistadecontatosquefoicolocadapelalógicanorequestaoinvésde${dao.lista}:

<c:forEachvar="contato"items="${contatos}">

3. Agora podemos testar chamando: http://localhost:8080/fj21-agenda/mvc?

logica=ListaContatosLogic

4. Depois dessas alterações, será necessário alterar o retorno da classe RemoveContatoLogic poisagoraa chamadadiretadolista-contatos.jsp não émais possível.Devemos agora chamar alógicaquelistaoscontatos:

publicclassRemoveContatoLogicimplementsLogica{

publicStringexecuta(HttpServletRequestreq,HttpServletResponseres)throwsException{

//códigoomitido

return"mvc?logica=ListaContatosLogic";}

}

ComoalteramosnossalistagemparaseracessadapelalógicaListaContatosLogic,seacessarmosa jsp lista-contatos.jsp diretamente pelo navegador, a página não mostrará nenhum contato.Precisamosentãosemprepassarpelalógica,queporsuavezdisponibilizaráalistagemparaapágina.

Portanto,nãodevemospermitirqueousuárioacessediretamentenossapágina.Paraimpossibilitaresteacessodireto,colocaremosnossaspáginasdentrododiretórioWEB-INF/jsp.

Agoraque estamosusandoMVC,umaboaprática énãodeixarmososusuários acessaremnossaspáginasdiretamente,esimpassandosempreporumalógica.

Nossalógicadelistagemficarádaseguinteforma:

publicclassListaContatosLogicimplementsLogica{

publicStringexecuta(HttpServletRequestreq,HttpServletResponseres)throwsException{

List<Contato>contatos=newContatoDao().getLista();

req.setAttribute("contatos",contatos);

return"/WEB-INF/jsp/lista-contatos.jsp";

9.10ESCONDENDONOSSASPÁGINAS

.

Page 138: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

}

Alémdisso, sequisermosaplicarestemesmoconceitoparaasdemais jsps,precisaremosalterarasdemaislógicascorrespondentesacrescentandoodiretórioWEB-INF/jspantesdonomedapágina.

Querendoaprenderaindamaissobre?Esclarecerdúvidasdosexercícios?Ouvirexplicaçõesdetalhadascomuminstrutor?ACaelum oferece o cursoFJ-21 presencial nas cidades de São Paulo, Rio deJaneiroeBrasília,alémdeturmasincompany.

ConsulteasvantagensdocursoJavaparaDesenvolvimentoWeb

1. CrieumalógicachamadaAlteraContatoLogicetesteamesmaatravésdeumlinknalistagemdalista-contatos.jsp.Lembre-se,antesdechamaressalógicaéprecisocriarumaoutralógicaquemostre os dados do contato em uma nova página, permitindo assim a alteração dos dados, e sódepois,nocliquedeumbotão,queaalteraçãoserádefatoefetivada.

2. Criealógicadeadicionarcontatos(AdicionaContatoLogic).ReparequeelaébemparecidacomaAlteraContatoLogic. Crie um formulário de adição de novo contato. Coloque um link paraadicionarnovoscontatosdentrodolista-contatos.jsp.

3. Desafio:Aslógicasdeadiçãoedealteraçãoficarammuitoparecidas.Tentecriarumaversãodeumadessas lógicas que faça as duas. Dica: A única diferença entre as duas é a presença ou não doparâmetroId.

4. Desafio: Altere seu projeto para que nenhuma jsp seja acessível diretamente, colocando-as nodiretórioWEB-INF/jsp.Modifique também suas lógicas de acordo. OBS: Deverá ser criada umanovalógicaparaavisualizaçãodoformuláriodeadiçãodecontatos.

Generalizandoomodeloacima,podemosdarnomesacadaumadaspartesdessanossaarquitetura.QueméresponsávelporapresentarosresultadosnapáginawebéchamadodeApresentação(View).

Aservlet(eauxiliares)quefazosdispatchesparaquemdeveexecutardeterminadatarefaéchamadadeControladora(Controller).

VocêpodetambémfazerocursoFJ-21dessaapostilanaCaelum

9.11EXERCÍCIOSOPCIONAIS

9.12MODELVIEWCONTROLLER

.

Page 139: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

As classes que representam suas entidades e as que te ajudama armazenar e buscar osdados sãochamadasdeModelo(Model).

EssestrêsformamumpadrãoarquiteturalchamadodeMVC,ouModelViewController.Elepodesofrervariaçõesdediversasmaneiras.OqueoMVCgaranteéaseparaçãodetarefas,facilitandoassimareescritadealgumaparte,eamanutençãodocódigo.

OfamosoStrutsajudavocêaimplementaroMVC,poistemumacontroladorajápronta,comumasériedeferramentasparateauxiliar.OHibernatepodeserusadocomoModel,porexemplo.EcomoViewvocênãoprecisausarsóJSP,podeusaraferramentaVelocity,porexemplo.

Hádiversasopçõesparaacamadadecontrolenomercado.Vejaumpoucosobrealgumasdelas:

StrutsAction-ocontroladormaisfamosodomercadoJava,éutilizadoprincipalmenteporseromais divulgado e com tutoriais mais acessíveis. Possui vantagens características do MVC edesvantagensquenaépocaaindanãoerampercebidas.ÉocontroladorpedidonamaiorpartedasvagasemJavahojeemdia.Éumprojetoquenão terágrandesatualizaçõespoisaequipedelesejuntoucomoWebWorkparafazeroStruts2,novaversãodoStrutsincompatívelcomaprimeiraetotalmentebaseadanoWebWork.

VRaptor-desenvolvidoinicialmenteporprofissionaisdaCaelumebaseadoemdiversasideiasdoscontroladoresmencionadosacima,oVRaptorusaoconceitodefavorecerConvençõesemvezdeConfiguraçõesparaminimizarousodeXMLeanotaçõesemsuaaplicaçãoWeb.

JSF-JSFéumaespecificaçãoJavaparaframeworksMVC.Eleébaseadoemcomponentesepossuiváriasfacilidadesparadesenvolverainterfacegráfica.Devidoaofatodeserumpadrãooficial,eleébastanteadotado.OJSFéensinadoemdetalhesnonossocursoFJ-26.

SpringMVC-éumapartedoSpringFrameworkfocadoemimplementarumcontroladorMVC.ÉfácildeusaremsuasúltimasversõesetemavantagemdeseintegraratodaaestruturadoSpringcomváriastecnologiasdisponíveis.

9.13LISTADETECNOLOGIAS:CAMADADECONTROLE

.

Page 140: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.

CasadoCódigo,LivrosdeTecnologia.

Temostambémdiversasopçõesparaacamadadevisualização.Umpoucosobrealgumasdelas:

JSP - como já vimos, o JavaServer Pages, temos uma boa ideia do que ele é, suas vantagens edesvantagens.Ousodetaglibs(aJSTLporexemplo)eexpressionlanguageémuitoimportantesevocêescolherJSPparaoseuprojeto.Éaescolhadomercadohojeemdia.

Velocity-umprojetoantigo,noqualaELdoJSPsebaseou,capazdefazertudooquevocêprecisaparaasuapáginadeumamaneiraextremamentecompacta.IndicadopelaCaelumparaconhecerumpoucomaissobreoutrasopçõesparacamadadevisualização.

Freemarker-similaraoVelocityecomideiasdoJSP-comosuporteataglibs-ofreemarkervemsendocadavezmaisutilizado,elepossuidiversas ferramentasnahorade formatar seu textoquefacilitammuitootrabalhododesigner.

Sitemesh - não é uma alternativa para as ferramentas anterioresmas simumamaneira de criartemplatesparaseusite,comumaideiamuitoparecidacomostrutstiles,porémgenérica:funcionainclusivecomoutraslinguagenscomoPHPetc.

Em pequenas equipes, é importante uma conversa para mostrar exemplos de cada uma dastecnologias acimaparaodesigner, afinalquemvai trabalhar comaspáginas é ele.Aque elepreferir,vocêusa,afinal todaselas fazemomesmodemaneirasdiferentes.Comoemumprojetoécomumterpoucos designers e muitos programadores, talvez seja proveitoso facilitar um pouco o trabalho paraaqueles.

Seuslivrosdetecnologiaparecemdoséculopassado?

9.14LISTADETECNOLOGIAS:CAMADADEVISUALIZAÇÃO

9.15 DISCUSSÃO EM AULA: OS PADRÕES COMMAND E FRONTCONTROLLER

.

Page 141: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

.

Page 142: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO10

"Aartenuncaestáterminada,apenasabandonada."--LeonardoDaVinci

Aotérminodessecapítulo,vocêserácapazde:

criarclassesquefiltramarequisiçãoearesposta;guardarobjetosnarequisição;descreveroqueéinjeçãodedependências;descreveroqueéinversãodecontrole;

Em qualquer aplicação surgem requisitos que não são diretamente relacionados com a regra denegócio.Umexemploclássicodessesrequisitosnãofuncionaiséaauditoria(Logging).Queremoslogaraschamadasdeumalógicadanossaaplicação.Outrosexemplossãoautorização,tratamentodeerrooucriptografia.Existemváriosoutros,masoquetodoselestememcomuméquenãosãorelacionadoscomasregrasdenegócios.

A pergunta como implementar estas funcionalidades, nos vem a cabeça. A primeira ideia seriacolocar o código diretamente na classe que possui a lógica. A classe seguinte mostra através depseudocódigoaschamadasparafazerauditoriaeautorização:

publicclassRemoveContatoLogicimplementsLogica{

publicvoidexecuta(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{

//auditoriaLogger.info("acessandoremovecontatologic");

//autorizaçãoif(!usuario.ehCliente()){request.getRequestDispatcher("/acessoNegado.jsp").forward(request,response);}

//todalógicapararemoverocontatoaqui//...}}

RECURSOSIMPORTANTES:FILTROS

10.1REDUZINDOOACOPLAMENTOCOMFILTROS

.

Page 143: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Podemosverquealémdalógicaéprecisoimplementarosoutrosrequisitos,masnãosóapenasnalógica que altera o contato, também é necessário colocar omesmo código nas lógicas que adiciona,removeoufazalistagemdoscontatos.Issopodepiorarpensandoqueexistemmuitomaisrequisitosnãofuncionais, como resultado o código aumenta em cada lógica. Desse jeito criamos um acoplamentomuitoforteentrealogicaeaimplementaçãodosrequisitosnãofuncionais.Ograndeproblemaéqueosmesmosficamespalhadosemtodasaslógicas.Aimagemabaixoilustraesseacoplamento:

A API de Servlets nos provê um mecanismo para tirar esse acoplamento e isolar essecomportamento,quesãoosFiltros.Filtros sãoclassesquepermitemqueexecutemoscódigoantesdarequisiçãoetambémdepoisquearespostafoigerada.

Umaboaanalogiaépensarqueaslógicassãoquartosemumacasa.Paraacessarumquartoéprecisopassarporváriasportas.Asportassãoosfiltros,ondevocêpassanaidaenavolta.Cadafiltroencapsulaapenasuma responsabilidade,ou sejaum filtropara fazer auditoria,outropara fazer a segurança etc.Entãoépossívelusarváriosfiltrosemconjunto.Umaportatambémpodeficarfechada,casoousuárionãopossuaacessoalógica,ouseja,ofiltropodenegaraexecuçãodeumalógica.Vejaaimagemseguintequemostraosfiltrosaplicadosnoexemploanterior:

.

Page 144: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

A grande vantagem é que cada requisito fica em um lugar só e conseguimos desacoplar nossaslógicas.

Paracriarmos filtrosutilizandoaAPIdeServletsdoJavaEE5, temosasmesmasdificuldadesquetemosquandovamosdefinirServlets.Paracadafiltroénecessáriocriarmosaclassequeimplementaa interfacejavax.servlet.Filteredepoisdeclararmoso filtronoweb.xml, alémde termosquedeclararparaquaisURL'saquelefiltroseráaplicado.

Configuraçãodeumfiltronoweb.xml:

<filter><filter-name>meuFiltro</filter-name><filter-class>br.com.caelum.filtro.MeuFiltro</filter-class></filter>

<filter-mapping><filter-name>meuFiltro</filter-name><url-pattern>/*</url-pattern></filter-mapping>

MasparadefinirmosumfiltrousandoanovaAPIdeServletsdoJavaEE6,bastaapenascriarmosuma classe que implementa a interface javax.servlet.Filter e anotarmos a classe [email protected]âmetronaanotaçãoopadrãoderequisiçõesqueserãofiltradas:

@WebFilter("/oi")publicclassMeuFiltroimplementsFilter{publicvoiddoFilter(ServletRequestreq,ServletResponseres,FilterChainchain){//...}}

Destaformaindicamosquetodasasrequisiçõesvindasapartirde/oiserãofiltradase,portanto,ofiltroseráaplicadoemcadarequisição.

É possível usar um filtromais especifico. Por exemplo, podemos filtrar todas as requisições para

.

Page 145: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

paginasJSPs:

@WebFilter("/*.jsp")publicclassMeuFiltroimplementsFilter{publicvoiddoFilter(ServletRequestreq,ServletResponseres,FilterChainchain){//...}}

Ouumfiltromaisamplo,filtrandoTODASasrequisiçõesdaaplicação:

@WebFilter("/*")publicclassMeuFiltroimplementsFilter{publicvoiddoFilter(ServletRequestreq,ServletResponseres,FilterChainchain){//...}}

Ao implementar a interface Filter, temos que implementar 3 métodos: init, destroy edoFilter.

Os métodos init e destroy possuem a mesma função dos métodos de mesmo nome daServlet,ouseja,executaralgoquandooseufiltroécarregadopelocontainerequandoédescarregadopelocontainer.

Ométodoque fará todooprocessamentoquequeremosexecutaréodoFilter, que recebe trêsparâmetros:ServletRequest,ServletResponseeFilterChain.

@WebFilter("/*")publicclassFiltroTempoDeExecucaoimplementsFilter{

//implementaçãodoinitedestroy

publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{

//todooprocessamentovaiaqui}}

PercebaasemelhançadessemétodocomométodoservicedaclasseServlet.Aideiadofiltroétambém processar requests,mas ele poderá fazer isso demaneiramais genérica para vários tipos derequests.Masumfiltrovaialémdeumservlet,comumfiltropodemostambémfechar"aporta".EssepodervemdoargumentoFilterChain(acadeiadefiltros).Elenospermiteindicaraocontainerqueorequestdeveprosseguirseuprocessamento. Issoé feitocomumachamadadométododoFilter daclasseFilterChain:

publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{

//passapelaporta

.

Page 146: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

chain.doFilter(request,response);}

Um filtro não serve para processar toda a requisição. A ideia é ele interceptar vários requestssemelhantes,executaralgo,masdepoispermitirqueoprocessamentonormaldorequestprossigaatravésdasServletseJSPsnormais.

Qualquer código colocado antes da chamada chain.doFilter(request,response) seráexecutadona ida,qualquercódigodepoisnavolta.Com issopodemos fazerumverificaçãodeacessoantesdalógica,ouabrirumrecurso(conexãooutransação)antesenavoltafecharomesmo.Umfiltroéidealparafazertratamentodeerroroumedirotempodeexecução.

A única coisa que precisamos fazer para que o nosso filtro funcione é registrá-lo, para que ocontainer saiba que ele precisa ser executado. Fazemos isso de forma simples, usando atributos daanotação @WebFilter. Através dos atributos, declaramos o filtro e quais URLs ou Servlets serãofiltradas.

O atributo filterName define um nome (ou alias) para o filtro. Se não definirmos o atributofilterName para nosso filtro, o nome dele será o nome completo da classe, damesma forma queacontececomasServlets.ParadefinirmosquaisURLpassarãopelonossofiltro,podemosfazê-lodemaneira similaràanotação@WebServlet. Se quisermosdefinir aquele filtropara apenasumaURL,passamos através do parâmetro na anotação @WebFilter como foi feito no exemplo acima-@WebFilter("/oi").Mas,sequisermosdefinirquemaisdeumaURLseráfiltrada,podemosusaroatributourlPatterns:

@WebFilter(filterName="MeuFiltro",ulrPatterns={"/oi","/ola"})publicclassMeuFiltroimplementsFilter{publicvoiddoFilter(ServletRequestreq,ServletResponseres,FilterChainchain){//...}}

PodemosaindaconfigurarquaisservletsserãofiltradosporaquelefiltrodeclarandoseusnomesnoatributoservletNames.Porexemplo:

@WebFilter(filterName="MeuFiltro",servletNames={"meuServlet","outroServlet"})publicclassMeuFiltroimplementsFilter{publicvoiddoFilter(ServletRequestreq,ServletResponseres,FilterChainchain){//...}}

.

Page 147: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

OUTRASANOTAÇÕES

ExistemoutrasanotaçõespresentesnaAPIServlets3.0:

@WEBLISTENER - Utilizada para definir Listeners de eventos que podem ocorrer em váriospontosdasuaaplicação;equivaleaodehoje;

@WEBINITPARAM - Utilizada para especificar parâmetros de inicialização que podem serpassadosparaServletseFiltros.Podeserpassadacomoparâmetroparaasanotações@WebServlete@WebFilter;equivaleaodehoje;

@MULTIPARTCONFIG - Utilizada para definir que um determinado Servlet receberá umarequisiçãodotipomime/multipart.

Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.

CasadoCódigo,LivrosdeTecnologia.

1. Vamoscriaronossofiltroparamedirotempodeexecuçãodeumarequisição.

Crie uma nova classe chamada FiltroTempoDeExecucao no pacotebr.com.caelum.agenda.filtroefaçaelaimplementarainterfacejavax.servlet.FilterAnote-acom@WebFilter edigaqueTODASas requisiçõesparaanossaaplicaçãodevemserfiltradas(@WebFilter("/*")).

DeixeosmétodosinitedestroyvazioseimplementeodoFilter:

@WebFilter("/*")publicclassFiltroTempoDeExecucaoimplementsFilter{

Seuslivrosdetecnologiaparecemdoséculopassado?

10.2 EXERCÍCIOS OPCIONAIS: FILTRO PARA MEDIR O TEMPO DEEXECUÇÃO

.

Page 148: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{

longtempoInicial=System.currentTimeMillis();

chain.doFilter(request,response);

longtempoFinal=System.currentTimeMillis();Stringuri=((HttpServletRequest)request).getRequestURI();Stringparametros=((HttpServletRequest)request).getParameter("logica");System.out.println("Tempodarequisicaode"+uri+"?logica="+parametros+"demorou(ms):"+(tempoFinal-tempoInicial));

}//métodosinitedestroyomitidos}

Reinicieoservidoreacessehttp://localhost:8080/fj21-agenda/mvc?logica=ListaContatosLogic

Procureasaídanoconsole.

Nossaaplicaçãodeagendanecessita,emváriosmomentos,deumaconexãocomobancodedadose,paraisso,onossoDAOinvocaemseuconstrutoraConnectionFactorypedindoparaamesmaumanovaconexão.Masemquallugarficaráofechamentodaconexão?

publicclassContatoDao{privateConnectionconnection;

publicContatoDao(){this.connection=newConnectionFactory().getConnection();}

//métodosadiciona,remove,getListaetc//ondefechamosaconexão?}

Atéomomento,não estamosnospreocupando como fechamentodas conexões comobancodedados. Isso é uma péssima prática para uma aplicação que vai para produção. Estamos deixandoconexões abertas e sobrecarregando o servidor de banco de dados, que pode aguentar apenas umdeterminado número de conexões abertas, o que fará com que sua aplicação pare de funcionarsubitamente.

OutroproblemaquetemosaoseguiressaestratégiadeadquirirconexãonoconstrutordosDAOséquando queremos usar dois DAOs diferentes, por exemplo ContatoDao e FornecedorDao. Aoinstanciarmos ambososDAOs, vamos abrir duas conexões, enquanto poderíamos abrir apenas umaconexãoparafazerasduasoperações.Deoutraformaficaimpossívelrealizarasoperaçõesnumaúnicatransação.

10.3PROBLEMASNACRIAÇÃODASCONEXÕES

.

Page 149: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

JápercebemosquenãoéumaboaideiacolocarmosacriaçãodaconexãonoconstrutordosnossosDAOs.Masqualéolugaridealparacriarmosessaconexãocomobancodedados?

PoderíamoscriaraconexãodentrodecadamétododoDAO,masnessecaso,seprecisássemosusardois métodos diferentes do DAO em uma mesma operação, novamente abriríamos mais de umaconexão.Dessaforma,abrirefecharasconexõesdentrodosmétodosdosDAOstambémnãonospareceumaboaalternativa.

Precisamos,dealgumaforma,criaraconexãoefazercomqueessamesmaconexãopossaserusadaportodososseusDAOsemumadeterminadarequisição.Assim,podemoscriarnossasconexõescomobancodedadosdentrodenossasServlets (ou lógicas,nocasodonosso frameworkMVCvistonocapítuloanterior)eapenaspassá-lasparaoDAOquevamosutilizar.Paraisso,nossosDAOsdeverãoterumconstrutorquerecebaConnection.

Vejamos:

publicclassContatoDao{privateConnectionconnection;

publicContatoDao(Connectionconnection){this.connection=connection;}

//métodosadiciona,remove,getListaetc}

publicclassAdicionaContatoLogicimplementsLogica{publicStringexecuta(HttpServletRequestrequest,HttpServletResponseresponse){Contatocontato=//contatomontadocomosdadosdorequest

Connectionconnection=newConnectionFactory().getConnection();

//passaconexãoproconstrutorContatoDaodao=newContatoDao(connection);dao.adiciona(contato);

connection.close();

//retornaparaoJSP}}

Isso já é uma grande evolução com relação ao que tínhamos no começo mas ainda não é umasolução muito boa. Acoplamos com a ConnectionFactory todas as nossas lógicas que precisamutilizar DAOs. E, em orientação a objetos, não é uma boa prática deixarmos nossas classes comacoplamentoalto.

10.4TENTANDOOUTRASESTRATÉGIAS

.

Page 150: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

INJEÇÃODEDEPENDÊNCIASEINVERSÃODECONTROLE

Aonão fazermosmais a criaçãoda conexãodentrodoContatoDaomas sim recebermos aConnectiondaqualdependemosatravésdoconstrutor,dizemosqueonossoDAOnãotemmaiso controle sobre a criação da Connection e, por isso, estamos Invertendo o Controle dessacriação.AúnicacoisaqueonossoDAOdizéqueeledependedeumaConnection atravésdoconstrutore,porisso,onossoDAOprecisaqueesseobjetodotipoConnectionsejarecebido,ouseja,eleesperaqueadependênciasejainjetada.

Injeção de Dependências e Inversão de Controle são conceitos muito importantes nasaplicaçõesatuaisenósasestudaremoscommaisdetalhesaindanocurso.

Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende

Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!

ConheçaaAluraCursosOnline.

NãoqueremostambémqueanossalógicaconheçaaclasseConnectionFactorymas,aindaassim,precisamosqueelapossuaaconexãoparaquepossamosrepassá-laparaoDAO.

Paradiminuirmosesseacoplamento,queremosque,semprequechegarumarequisiçãoparaanossaaplicação, uma conexão seja aberta e, depois que essa requisição for processada, ela seja fechada.Tambémpodemosadicionarotratamentoatransaçãoaqui,seacharmosnecessário.Precisamosentãointerceptartodarequisiçãoparaexecutaressesprocedimentos.

ComojávistoosFiltrospermitemqueexecutemoscódigoantesdarequisiçãoetambémdepoisquearespostafoigerada.Idealparaabrirumaconexãoantesefecharnavolta.

Vamosentãoimplementarumfiltrocomessecomportamento:

@WebFilter("/*")

Agoraéamelhorhoradeaprenderalgonovo

10.5REDUZINDOOACOPLAMENTOCOMFILTROS

.

Page 151: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

publicclassFiltroConexaoimplementsFilter{//implementaçãodoinitedestroy,senecessário

publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{

//abreumaconexãoConnectionconnection=newConnectionFactory().getConnection();

//indicaqueoprocessamentodorequestdeveprosseguirchain.doFilter(request,response);

//fechaconexãoconnection.close();}}

Comaconexãoaberta,precisamosentãofazercomquearequisiçãosaiadonossofiltroeváparaopróximopasso,sejaeleumoutrofiltro,ouumaServletouumJSP.Dessaforma,nossalógicadenegóciopodeexecutarnormalmente.Paraisso,usamosoargumentoFilterChainquenospermiteindicaraocontainer que o request deve prosseguir seu processamento. Isso é feito com uma chamada aodoFilterdoFilterChain:

Atéagora,conseguimosabrirumaconexãonocomeçodosrequests,prosseguiroprocessamentodorequestnormalmentee fecharaconexãoaposdaexecução.Masnossas lógicasvãoexecutar,digamos,manipulaçõesdeContatosevãoprecisardaconexãoabertanofiltro.Mascomoacessá-la?Como,dentrodeumaServlet,pegarumobjetocriadodentrodeumfiltro,umaoutraclasse?

Aideiaéassociar(pendurar)dealgumaformaaconexãocriadaaorequestatual.IssoporquetantoofiltroquantoaServletestãonomesmorequesteporque,comodefinimos,asconexõesvãoserabertasporrequests.

Paraguardarmosalgonarequisição,precisamosinvocarométodosetAttributenorequest.Passamos para essemétodo uma identificação para o objeto que estamos guardando na requisição e

.

Page 152: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

tambémpassamosopróprioobjetoparaserguardadonorequest.

publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain){

Connectionconnection=newConnectionFactory().getConnection();

//"penduraumobjetonoRequest"request.setAttribute("connection",connection);

chain.doFilter(request,response);

connection.close();}

AoinvocarmosodoFilter,arequisiçãoseguiráoseufluxonormal levandooobjetoconnectionjunto.Oqueousuário requisitou será entãoexecutadoaté a resposta sergerada (porumaServletouJSP). Após isso, a execução volta para o ponto imediatamente abaixo da invocação dochain.doFilter. Ou seja, através de um filtro conseguimos executar algo antes do request serprocessadoedepoisdarespostasergerada.

Pronto,nossoFiltroéoúnicopontodanossaaplicaçãoquecriaráconexões.

Repare comousamosowildcard no parâmetro da anotação para indicar que todas as requisiçõesserãofiltradase,portanto,terãoumaconexãoabertajádisponível.

Só falta na nossa lógica pegarmos a conexão que guardamos no request . Para isso bastainvocarmosométodogetAttributenorequest.Nossalógicaficarádaseguintemaneira:

publicclassAdicionaContatoLogicimplementsLogica{publicStringexecuta(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{

Contatocontato=//contatomontadocomosdadosdorequest

//buscandoaconexãodorequestConnectionconnection=(Connection)request.getAttribute("connection");

ContatoDaodao=newContatoDao(connection);dao.adiciona(contato);

//fazoreturndoJSPcomodecostume}}

Umaoutragrandevantagemdessedesacoplamentoéqueeletornaonossocódigomaisfácildesetestarunitariamente,assuntoqueaprendemosepraticamosbastantenocursoFJ-22.

1. Vamoscriaronossofiltroparaabrirefecharaconexãocomobancodedados

10.6EXERCÍCIOS:FILTROS

.

Page 153: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CrieumanovaclassechamadaFiltroConexaonopacotebr.com.caelum.agenda.filtro efaçaelaimplementarainterfacejavax.servlet.Filter

Anote-acom@WebFilter("/*") para registraro filtrono container e fazer comque todas asrequisiçõespassemporele:

DeixeosmétodosinitedestroyvazioseimplementeodoFilter:

publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{

try{Connectionconnection=newConnectionFactory().getConnection();

//pendurandoaconnectionnarequisiçãorequest.setAttribute("conexao",connection);

chain.doFilter(request,response);

connection.close();}catch(SQLExceptione){thrownewServletException(e);}}

2. CrieumconstrutornoseuContatoDaoquerecebaConnectionearmazene-anoatributo:

publicclassContatoDao{privateConnectionconnection;

publicContatoDao(Connectionconnection){this.connection=connection;}

//outroconstrutoremétodosdoDAO}

3. Na sua RemoveContatoLogic, criada no capítulo anterior, busque a conexão no request, erepasse-aparaoDAO.ProcurenalógicaacriaçãodoDAOefaçaasalterações:

publicclassRemoveContatoLogicimplementsLogica{publicStringexecuta(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{

//...

//(procureoContatoDaonocódigoexistente)//buscaaconexãopenduradanarequisiçãoConnectionconnection=(Connection)request.getAttribute("conexao");

//passeaconexãonoconstrutorContatoDaodao=newContatoDao(connection);

//...}

.

Page 154: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

}

OuvocêpodefazeressamesmamodificaçãonanossaantigaAdicionaContatoServlet.

4. Removaumcontatonasuaaplicaçãoeverifiquequetudocontinuafuncionandonormalmente.

.

Page 155: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO11

"Umhomempintacomseucérebroenãocomsuasmãos."--Michelangelo

Nessecapítulo,vocêaprenderá:

Porqueutilizarframeworks;ComofuncionaoframeworkSpringMVC;AsdiferentesformasdesetrabalharcomoSpringMVC.

Quandoestamosdesenvolvendoaplicações,emqualquerlinguagem,queremosnospreocuparcominfraestrutura omínimopossível. Isso não é diferente quando trabalhamos comuma aplicaçãoWeb.Imagine termos que lidar diretamente com o protocolo HTTP a todo momento que tivermos quedesenvolverumafuncionalidadequalquer.Nesseponto,oscontainerseaAPIdeServletsencapsulamoprotocoloparaquenãoprecisemoslidardiretamentecomele,masmesmoassimexistemuitotrabalhorepetitivoqueprecisamosfazerparaquepossamosdesenvolvernossalógica.

Um exemplo desse trabalho repetitivo que fazíamos era a conversão da data. Como o protocoloHTTP sempre interpreta tudo como texto, é preciso transformar essa data em um objeto do tipo Calendar . Mas sempre que precisamos de uma data temos essa mesma conversão usando aSimpleDateFormat.

Outroexemploé,queparagravarmosumobjetodo tipoContato, precisamospegarnaAPIdeServletsparâmetroporparâmetroparamontarumobjetodo tipoContato invocandoos settersadequados.

NãoseriamuitomaisfácilquenossalógicarecebessedealgumaformaumobjetodotipoContatojá devidamente populado com os dados que vieram na requisição?Nosso trabalho seria apenas, porexemploinvocaroContatoDaopassandooContatoparaseradicionado.

OgrandeproblemaéqueestamosatreladosaAPIdeServlets que ainda exigemuito trabalhobraçalparadesenvolvermosnossalógica.E,justamentepararesolveresseproblema,começaramasurgirosframeworksMVC,comoobjetivodediminuiroimpactodaAPIdeServletsemnossotrabalhoefazercomquepassemosanospreocuparexclusivamentecomalógicadenegócios,queéocódigoquepossuivalorparaaaplicação.

SPRINGMVC

11.1PORQUEPRECISAMOSDEFRAMEWORKSMVC?

.

Page 156: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,

Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex-aluno daCaelumtem15%dedescontonestelink!

ConheçaoscursosonlineAlura.

Logosepercebeuqueo trabalhocomServletse JSPspurosnãoera tãoprodutivoeorganizado.AprópriaSuncomeçouafomentarousodopadrãoMVCedepatternscomoFrontController.Eramuitocomum as empresas implementarem esses padrões e criarem soluções baseadas emmini-frameworkscaseiros.

Mas logosepercebeuqueoretrabalhoeramuitograndedeprojetoparaprojeto,deempresaparaempresa.UsarMVCerabeminteressante,masreimplementaropadrãotodoacadaprojetocomeçouaserinviável.

OStrutsfoiumdosprimeirosframeworksMVCcomaideiadesecriarumcontroladorreutilizávelentreprojetos.Elefoilançadonoano2000comoobjetivodetornarmaissimplesacriaçãodeaplicaçõesWebcomalinguagemJavaaodisponibilizarumasériedefuncionalidadesjáprontas.

Isso fez com que muitas pessoas o utilizassem para desenvolver suas aplicações, tornando-orapidamenteaprincipalsoluçãoMVCnomercadoJava.Umadasconsequênciasdissoéquehojeemdiaeleéumdosmaisutilizadosnomercado.

Noentanto,hoje,eleévistocomoumframeworkquedemandamuitotrabalho,justamenteportersidocriadohámuitotempo,quandomuitasdasfacilidadesdalinguagemJavaaindanãoexistiam.

PorissosurgiramoutrosframeworksMVC.AcomunidadedoStruts,porexemplo,uniuforçascoma de outro framework que começava a ganhar espaço nomercado, que era oWebWork. Ambas ascomunidades se fundiramedesenvolveramoStruts 2, que vema serumaversãomais simplesde setrabalhardoqueoStruts1,ecomaindamaisrecursosefuncionalidades.

Um dos frameworks mais famosos no mercado é o Spring MVC. Spring é um framework queinicialmentenãofoicriadoparaodesenvolvimentoweb.NaessênciaoSpringéumcontainerleveque

JáconheceoscursosonlineAlura?

11.2UMPOUCODEHISTÓRIA

.

Page 157: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

visa fornecerserviçosparasuaaplicaçãocomoporexemploogerenciamentodeobjetosoutransação.Mas como tempo a comunidade Spring entendeuqueo Struts eraultrapassado e começou criarumframeworkMVC próprio. O SpringMVC é um frameworkmoderno que usa os recursos atuais dalinguagem além de usar todo poder do container Spring. Nesse capítulo veremos as funcionalidadesdesseframeworkpoderoso.

STRUTS1

Embora bastante antigo, o Struts 1 ainda é usado em muitas empresas. Os conceitos efundamentossãomuitoparecidosentreasversões,masaversãoantigaémaistrabalhosaepossuiformasparticularesdeuso.

STRUTS2

Apesardonomefamoso,oStruts2nuncafoitãoutilizadoquantooStruts1.EnquantooStruts1 era pioneirona época e se tornouopadrãonodesenvolvimentoweb Java, o Struts 2 era umaescolhaentreváriosframeworksMVCqueofereciamasmesmasfacilidades.

ParaquepossamosaprenderoSpringMVC,vamoscriarumsistemadelistadetarefas.EoprimeiropassoqueprecisamosdaréteroSpringMVCparaadicionarmosemnossaaplicação.SpringMVCvemjuntocomasbibliotecasdoframeworkSpringquepodemosencontrarnositehttp://springsource.org.Lá,épossívelencontrardiversasdocumentaçõesetutoriais,alémdosJARsdoprojeto.

Uma vez que adicionamos os JARs do SpringMVC emnosso projeto dentro do diretórioWEB-INF/lib, precisamos declarar um Servlet, que fará o papel de Front Controller da nossa aplicação,recebendoasrequisiçõeseasenviandoàslógicascorretas.ParadeclararmosaServletdoSpringMVC,bastaadicionarmosnoweb.xmldanossaaplicação:

<servlet><servlet-name>SpringMVCDispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/spring-context.xml</param-value></init-param>

11.3CONFIGURANDOOSPRINGMVC

.

Page 158: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

<load-on-startup>1</load-on-startup></servlet>

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

ReparequeéumaconfiguraçãonormaldeServlet,comservlet-classeurl-pattern,comoasquefizemosantes.Temapenasumelementonovo,oinit-param.Esteparâmetroéumaconfiguraçãoquepodeserpassadaparaoservletpeloweb.xml.Aquidefinimosonomedoarquivodeconfiguraçãodo framework Spring, ospring-context.xml.Quandoo Servlet é carregado, ele vai procurar essespring-context.xmldentrodapastaWEB-INF.

OframeworkSpringpossuisuaprópriaconfiguraçãoXML.OSpring,porsermuitomaisdoqueumcontroladorMVC,poderiaserutilizadoemambientesnãoWeb,ousejanemsempreoSpringpodesebasearnoweb.xml.Porestemotivo,masnãosomenteeste,oSpringdefiniuoseupróprioXMLcomváriasopçõesparaconfiguraraaplicação.

A primeira coisa que faremos nesse arquivo é habilitar o uso de anotações do Spring MVC econfigurarpacotebasedaaplicaçãowebparaoSpringacharasnossasclasses:

<mvc:annotation-driven/><context:component-scanbase-package="br.com.caelum.tarefas"/>

Alémdisso,éprecisoinformaraoSpringolocalondecolocaremososarquivosJSP.ParaissoSpringMVCofereceumaclasseespecialquerecebeonomedapastadosJSPseaextensãodosarquivos.VamoscriartodososJSPsnapasta/WEB-INF/views/:

<beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver"><propertyname="prefix"value="/WEB-INF/views/"/><propertyname="suffix"value=".jsp"/></bean>

IssojáésuficienteparacomeçarcomoSpringMVC.Oarquivocompleto,comtodososcabeçalhos,ficaentãocomo:

<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc-3.0.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:component-scanbase-package="br.com.caelum.tarefas"/>

XMLespecíficodoSpring

.

Page 159: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

<mvc:annotation-driven/>

<beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver"><propertyname="prefix"value="/WEB-INF/views/"/><propertyname="suffix"value=".jsp"/></bean>

</beans>

No nosso framework MVC que desenvolvemos anteriormente, para criarmos nossas lógicas,criávamos uma classe que implementava uma interface. Existem diversas abordagens seguidas pelosframeworks para possibilitar a criação de lógicas. Passando por declaração em um arquivo XML,herdando de alguma classe do framework e, a partir do Java 5, surgiram as anotações, que são umaformadeintroduzirmetadadosdentrodenossasclasses.

OSpringMVCpermitecriaraslógicasdeformasdiferentes,usandoconvençõesoudeclarartudonoXML,porémnaversão3amaneiraindicadaéutilizandoanotações.

Querendoaprenderaindamaissobre?Esclarecerdúvidasdosexercícios?Ouvirexplicaçõesdetalhadascomuminstrutor?ACaelum oferece o cursoFJ-21 presencial nas cidades de São Paulo, Rio deJaneiroeBrasília,alémdeturmasincompany.

ConsulteasvantagensdocursoJavaparaDesenvolvimentoWeb

Paracriarmosnossaprimeiralógica,vamoscriarumaclassechamadaOlaMundoController.Nelavamoscolocarmétodosquesãoasações(Action).OsufixoController não é obrigatórioparaoSpring MVC porém é uma convenção do mercado. Como utilizaremos Spring MVC baseado emanotações,éobrigatórioqueoseuControllerestejadentrodopacotebr.com.caelum.tarefasouem um subpacote. No nosso caso, criaremos a classe dentro do pacote:br.com.caelum.tarefas.controller.

Dentro dessa nossa nova classe, vamos criar um método que imprimirá algo no console e, emseguida, iráredirecionarparaumJSPcomamensagem"Olámundo!".Aclassedeveseranotadacom

11.4CRIANDOASLÓGICAS

VocêpodetambémfazerocursoFJ-21dessaapostilanaCaelum

11.5ALÓGICAOLÁMUNDO!

.

Page 160: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

@Controller, umaanotaçãodoSpringMVC.Ela indica aoSpringqueosmétodosdessa classe sãoações(Action).Podemoscriarummétododequalquernomedentrodessaclasse,desdequeeleestejacom a anotação @RequestMapping. A anotação @RequestMapping recebe um atributo chamadovaluequeindicaqualseráaURLutilizadaparainvocarométodo,comoesseatributojáéopadrãonão precisamos definir. Portanto, se colocarmos o valor olaMundoSpring acessaremos o métododentrodonosso@ControllerpelaURLhttp://localhost:8080/fj21-tarefas/olaMundoSpring.

Vamoschamarométodoexecute,masnovamentepoderiaserqualquernome.EssemétododeveretornarumaString que indicaqual JSPdeve ser executado após a lógica.Por exemplo, podemosretornar"ok"paraenviarousuárioparaumapáginachamadaok.jsp.Ométodonaodeveretornarosufixodapágina,jáqueissofoiconfiguradonoXMLdoSpring.TambémlembrandoqueoSpringMVCprocuraaspáginasJSPdentrodapastaWEB-INF/views.

Dessaforma,teríamosaseguinteclasse:

@ControllerpublicclassOlaMundoController{

@RequestMapping("/olaMundoSpring")publicStringexecute(){System.out.println("ExecutandoalógicacomSpringMVC");return"ok";}}

Umponto importante a senotar équepodemos criaroutrosmétodosque respondamporoutrasURL's, ou seja, vários açõesdentrodessa classe (dentrodomesmo@Controller).Bastaria quenósutilizássemosnovamenteaanotação@RequestMappingessesmétodos.

Por fim, sóprecisamoscriaro JSPquemostraráamensagem"Olámundo!".Bastacriaroarquivook.jspdentrodapastaWEB-INF/views/,quemapeamosanteriormentenoXMLdoSpring.

OJSPteráoseguinteconteúdo:

<html><body><h2>OlámundocomSpringMVC!</h2></body></html>

PodemosacessarnossométodopelaURLhttp://localhost:8080/fj21-tarefas/olaMundoSpring.OqueaconteceéqueapósaexecuçãodométodooSpringMVCverificaqualfoioresultadoretornadopeloseumétodoeprocuradespachararequisiçãoparaapáginaindicada.

Casovocêestejaemcasa,façaodownloaddoSpringFrameworkeuseapenasosseguintesJARsnasuaaplicação:

11.6PARASABERMAIS:CONFIGURANDOOSPRINGMVCEMCASA

.

Page 161: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

commons-logging-1.x.x.jarlog4j-1.2.x.jarmysql-connector-java-5.x.x.jarslf4j-api-1.7.x.jarslf4j-log4j12-1.7.x.jarspring-aspects-4.x.x.RELEASE.jarspring-aop-4.x.x.RELEASE.jarspring-beans-4.x.x.RELEASE.jarspring-context-4.x.x.RELEASE.jarspring-core-4.x.x.RELEASE.jarspring-expression-4.x.x.RELEASE.jarspring-jdbc-4.x.x.RELEASEspring-web-4.x.x.jarspring-webmvc-4.x.x.RELEASE.jar

1. VamosconfiguraroSpringMVCemumnovoprojeto.

Crieumnovoprojetoweb:File->New->Project...->DynamicWebProjectchamadofj21-tarefas.

NaabaServers,cliquecomobotãodireitonoTomcateváemAddandRemove...:

Bastaselecionaronossoprojetofj21-tarefaseclicaremAdd:

Vamoscomeçarimportandoasclassesqueserãonecessáriasaonossoprojeto,comoomodelodeTarefaseoDAO.

Cliquecomobotãodireitonoprojetofj21-tarefaseescolhaaopçãoImport.

SelecioneGeneral->ArchiveFile

Escolhaoarquivoprojeto-tarefas.zipqueestáemDesktop/21econfirmeaimportação.

Abraoarquivoweb.xmlparafazermosadeclaraçãodoservletdoSpringMVC:

<servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/spring-context.xml

11.7 EXERCÍCIOS: CONFIGURANDO O SPRING MVC E TESTANDO ACONFIGURAÇÃO

.

Page 162: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

</param-value></init-param><load-on-startup>1</load-on-startup></servlet>

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

2. VamosfazerumsimplesOláMundo,paratestarmosnossaconfiguração:

Crie uma nova classe chamada OlaMundoController no pacotebr.com.caelum.tarefas.controller

Adicionenessaclasseoseguinteconteúdo:

@ControllerpublicclassOlaMundoController{

@RequestMapping("/olaMundoSpring")publicStringexecute(){System.out.println("ExecutandoalógicacomSpringMVC");return"ok";}}

Dica:UseCtrl+Shift+Oparaimportarasclasses.

Precisamosprepararacamadadevisualização.Crieumapastaviewsparanossos JSPsquedeveficardentrodapastaWebContent/WEB-INF.

Faltao JSPque será exibidoapós a execuçãodanossa lógica.Crieo JSPok.jsp nodiretórioWebContent/WEB-INF/viewsdoprojetocomoconteúdo:

<html><body><h2>OlámundocomSpringMVC!</h2></body></html>

Reinicie o Tomcat e acesse no seu navegador o endereço http://localhost:8080/fj21-tarefas/olaMundoSpring.Oresultadodeveseralgoparecidocom:

.

Page 163: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.

CasadoCódigo,LivrosdeTecnologia.

Vamos começar a criar o nosso sistema de tarefas.Guardaremos uma descrição da tarefa, e umaindicação informando se a tarefa já foi finalizada ou não e quando foi finalizada. Esse sistema écompostopeloseguintemodelo:

publicclassTarefa{privateLongid;privateStringdescricao;privatebooleanfinalizado;privateCalendardataFinalizacao;

//gettersesetters}

Vamoscriarafuncionalidadedeadiçãodenovastarefas.Paraisso,teremosumatelacontendoum

Seuslivrosdetecnologiaparecemdoséculopassado?

11.8ADICIONANDOTAREFASEPASSANDOPARÂMETROS

.

Page 164: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

formuláriocomcamposparaserempreenchidos.Queremosque,aocriarmosumanovatarefa,amesmavenhaporpadrãocomonãofinalizadae,consequentemente,semadatadefinalizaçãodefinida.Dessaforma, nosso formulário terá apenas o campo descricao . Podemos criar um JSP chamadoformulario.jspcontendosomenteocampoparadescrição:

<html><body><h3>Adicionartarefas</h3><formaction="adicionaTarefa"method="post">Descrição:<br/><textareaname="descricao"rows="5"cols="100"></textarea><br/>

<inputtype="submit"value="Adicionar"></form></body></html>

Onosso form,aoser submetido,chamaumaação,ummétododentrodeum@Controller querespondepelaURLadicionaTarefa.Essemétodoprecisareceberosdadosdarequisiçãoegravaratarefaqueousuárioinformounatela.VamoschamaressemétodoadicionaecolocardentrodaclasseTarefasController:

@ControllerpublicclassTarefasController{

@RequestMapping("adicionaTarefa")publicStringadiciona(){JdbcTarefaDaodao=newJdbcTarefaDao();dao.adiciona(tarefa);return"tarefa-adicionada";}}

Mas,comomontaremosoobjetotarefaparapassarmosaonossoDAO?DentrodessanossaclasseTarefasController em nenhum momento temos um HttpServletRequest para pegarmos osparâmetrosenviadosnarequisiçãoemontarmosoobjetotarefa.

Umadasgrandesvantagensdeframeworksmodernoséqueelesconseguempopularosobjetosparanós.Bastaquedealgumaforma,nósfaçamosumaligaçãoentreocampoqueestánatelacomoobjetoquequeremospopular.EcomoSpringMVCnãoédiferente.

Essaligaçãoéfeitaatravésdacriaçãodeumparâmetrodométodoadiciona.Esseparâmetroéoobjeto que deverá ser populado pelo SpringMVC comos dados que vieramda requisição. Portanto,vamoscriarnonossométodoumnovoparâmetrochamadotarefa:

@ControllerpublicclassTarefasController{

@RequestMapping("adicionaTarefa")publicStringadiciona(Tarefatarefa){JdbcTarefaDaodao=newJdbcTarefaDao();dao.adiciona(tarefa);return"tarefa-adicionada";}

.

Page 165: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

}

Queremosqueocampodetextoquecriamosnonossoformuláriopreenchaadescriçãodessatarefa.Para fazermos isso, basta darmos o nome com o caminho da propriedade que queremos definir.Portanto,sedentrodoobjetotarefaqueremosdefinirapropriedadedescricao,bastanomearmosoinputcomdescricao.OSpringMVCcriaoobjetotarefaparanósepreencheesseobjetocomosdadosdarequisição,nessecasocomoparâmetrodescricaodarequisição.ComoaclasseTarefaéumJavaBeanepossuiconstrutorsemargumentosegetters/settersissonãoseráproblema.

Porfim,bastaexibirmosamensagemdeconfirmaçãodequeacriaçãodatarefafoifeitacomsucesso.Criamosoarquivotarefa-adicionada.jspcomoseguinteconteúdoHTML:

<html><body>Novatarefaadicionadacomsucesso!</body></html>

Anossaaplicaçãoteráváriaspáginasrelacionadascomumaoumaistarefas.Queremosorganizaranossa aplicação desde início e separar os arquivos JSPs relacionadas em subpastas. Ou seja, todas aspáginasJSPrelacionadascomomodelotarefaficarãonapastatarefa.Porisso,vamoscriarumanovapastatarefadentrodapastaWEB-INF/viewsparaosJSPsqueoTarefasControllervaiusar.Porpadrão,oSpringMVCnãoprocuraemsubpastas,procuraapenasnapastaviews.Vamosmudaroretornodométodoadiciona edevolveronomedasubpastaeonomedapágina JSP.Nessecasooretornoficacomotarefa/adicionada.

Portanto,ocódigocompletodométodoadicionafica:

@ControllerpublicclassTarefasController{

@RequestMapping("adicionaTarefa")publicStringadiciona(Tarefatarefa){JdbcTarefaDaodao=newJdbcTarefaDao();dao.adiciona(tarefa);return"tarefa/adicionada";}}

Na pasta WEB-INF/views/tarefa também deve ficar o formulário para adicionar uma tarefa.Como discutimos antes, todos os JSPs da tarefa na mesma subpasta. Porém aqui surge um novoproblema:ÉprecisocarregaroJSPnonavegador,masoacessodiretoaopastaWEB-INFéproibidopeloservlet-containereconsequentementenãoépossívelacessaroformulário.Pararesolverissovamoscriaruma nova ação (um novométodo) dentro da classe TarefasController que tem a finalidade dechamar o formulário apenas. Ométodo usa também a anotação @RequestMappping e retorna umStringparachamaroformulário.

MelhoraraorganizaçãodosarquivosJSPs

.

Page 166: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

AbaixoocódigocompletodoTarefasControllercomosdoismétodos:

@ControllerpublicclassTarefasController{

@RequestMapping("novaTarefa")publicStringform(){return"tarefa/formulario";}

@RequestMapping("adicionaTarefa")publicStringadiciona(Tarefatarefa){JdbcTarefaDaodao=newJdbcTarefaDao();dao.adiciona(tarefa);return"tarefa/adicionada";}}

AestruturadaspastaWEB-INFficacomo:

WEB-INF-views-tarefa-formulario.jsp-adicionada.jsp

ParachamaroformuláriousaremosaURL:http://localhost:8080/fj21-tarefas/novaTarefa

Vamoscriaroformulárioenossaaçãoparafazeragravaçãodastarefas.

1. Oprimeiropassoécriarnossoformulárioparaadicionarumatarefa.ParaissocrieumapastatarefadentrodapastaWebContent/WEB-INF/views.Dentrodapasta tarefa adicioneumnovo arquivoformulario.jsp.

<html><body><h3>Adicionartarefas</h3><formaction="adicionaTarefa"method="post">Descrição:<br/><textareaname="descricao"rows="5"cols="100"></textarea><br/><inputtype="submit"value="Adicionar"></form></body></html>

2. Agoraprecisamosummétodo(action)dentrodeum@Controllerparaacessaro JSP.Crieumanovaclassenopacotebr.com.caelum.tarefas.controllerchamadaTarefasController.

Nossa classeprecisa terummétodopara acessaro JSP.Vamoschamarométodo form() e usar aanotação@RequestMapping:

@ControllerpublicclassTarefasController{

11.9EXERCÍCIOS:CRIANDOTAREFAS

.

Page 167: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

@RequestMapping("novaTarefa")publicStringform(){return"tarefa/formulario";}

}

UseCtrl+Shift+Oparaimportarasclasses.

3. Aindafaltaométodoquerealmenteadicionaatarefanobancodedados.Essemétodoéchamadopelo nosso formulário e recebe uma tarefa como parâmetro. Ele novamente usa a anotação@RequestMappingparadefiniraURL.

DentrodaclasseTarefasControllercrieométodoadicionaquerecebeumatarefa.NométodousamosaJdbcTarefaDaoparapersistirosdados.OretornodométododefineolocalenomedoJSP.

Ocódigodeveficar:

@RequestMapping("adicionaTarefa")publicStringadiciona(Tarefatarefa){JdbcTarefaDaodao=newJdbcTarefaDao();dao.adiciona(tarefa);return"tarefa/adicionada";}

4. E, por fim, criamos o arquivo adicionada.jsp na pasta tarefa que mostrará uma mensagem deconfirmaçãodequeatarefafoiefetivamenteadicionada.

<html><body>Novatarefaadicionadacomsucesso!</body></html>

5. ReinicieoTomcat.

Acesse no seu navegador o endereço http://localhost:8080/fj21-tarefas/novaTarefa eadicioneumanovatarefa.

.

Page 168: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Casoaconteçaumaexceção informandoquea tabelanãoestácriada,crie-acomoscriptabaixoetenteinserirnovamenteatarefa.Abraoterminaledigite:

mysql-uroot-p

usefj21;

createtabletarefas(idBIGINTNOTNULLAUTO_INCREMENT,descricaoVARCHAR(255),finalizadoBOOLEAN,dataFinalizacaoDATE,primarykey(id));

Lembrandodedigitarasenhadobancodedadossehouveruma.

Já conseguimos adicionar novas tarefas em nossa aplicação. Porém, o que impede algumusuáriodesatento incluiruma tarefa semdescrição?Até agora,nada.Nósqueremosqueumusuárionão sejacapaz de adicionar uma tarefa sem descrição, para isso precisamos incluir algum mecanismo devalidaçãoemnossaaçãodeadicionartarefas.Avalidaçãodeveserexecutadanoladodoservidor,afimdegarantirqueosdadosserãovalidadosemumlugarondeousuárionãoconsigainterferir.

A maneira mais fácil de validar a tarefa é usar vários ifs no método adiciona da classe TarefasController antes de chamar dao.adiciona(tarefa) , executando a validaçãoprogramaticamente.Ocódigoseguintemostraaideia:

@RequestMapping("adicionaTarefa")publicStringadiciona(Tarefatarefa){

11.10INCLUINDOVALIDAÇÃONOCADASTRODETAREFAS

Validandoprogramaticamente

.

Page 169: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

if(tarefa.getDescricao()==null||tarefa.getDescricao().equals("")){return"tarefa/formulario";}

JdbcTarefaDaodao=newJdbcTarefaDao();dao.adiciona(tarefa);return"tarefa/adicionada";}

Oproblema aqui é quantomais atributos na tarefamais ifs teremos. É provável também quevamosrepetirumifououtroquandovalidarmosatarefaemmétodosdiferentes,porexemplo,paraadicionaroualteraratarefa.Sabemosquecopiarecolarcódigonãoéumaboamaneiradereaproveitarcódigo.Oqueprecisamosédealgumartifícioqueseja igualparaqualquermétodo,algoqueajudenavalidaçãodosdados.

Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende

Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!

ConheçaaAluraCursosOnline.

A partir do Java EE 6 temos uma especificação que resolve este problema. A JSR 303, tambémconhecidacomoBeanValidation,defineumasériedeanotaçõeseumaAPIparacriaçãodevalidaçõesparaseremutilizadasemJavaBeans,quepodemservalidadosagoraemqualquercamadadaaplicação.

Com o Bean Validation declaramos através de anotações as regras de validação dentro do nossomodelo,porexemplo,nanossatarefa:

publicclassTarefa{

privateLongid;

@Size(min=5)privateStringdescricao;

privatebooleanfinalizado;privateCalendardataFinalizacao;

//...}

Agoraéamelhorhoradeaprenderalgonovo

11.11VALIDAÇÃOCOMBEANVALIDATION

.

Page 170: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Pronto!Com essas anotações, qualquer objeto do tipoTarefa pode ser validadona camada decontroller.SófaltaavisaroSpringMVCquerealmentequeremosexecutaravalidação.IssoéfeitopelaanotaçãoValidquedevemosusarnaantesdoparâmetrodaação:

@RequestMapping("adicionaTarefa")publicStringadiciona(@ValidTarefatarefa){JdbcTarefaDaodao=newJdbcTarefaDao();dao.adiciona(tarefa);return"tarefa/adicionada";}

Comoestamos falandodeSpringMVC,antesdachamadadométodoéexecutadaavalidação,ousejaseráverificadoseadescriçãodatarefanãoestávazia.Seestiver,serálançadaumaexceçãodotipoConstraintViolationExceptionquepossuiadescriçãodoerro.

Não queremosmostrar uma exceção para o usuário e sim apenas voltar para o formulário paramostrarumamensagemqueavalidaçãofalhou.OSpringMVCpodeguardaroresultado(oserrosdevalidação) emumobjetodo tipoBindingResult.Assimnão será lançadoum exceção. Este objetoBindingResultsetornaumparâmetrodaação.Entãosóéprecisoperguntarparaeleseexisteumerrodevalidaçãoeseexistir,voltarparaoformulário.Vejaocódigo:

@RequestMapping("adicionaTarefa")publicStringadiciona(@ValidTarefatarefa,BindingResultresult){

if(result.hasFieldErrors("descricao")){return"tarefa/formulario";}

JdbcTarefaDaodao=newJdbcTarefaDao();dao.adiciona(tarefa);return"tarefa/adicionada";}

Nocódigoacimaverificamosseexisteumdeerrovalidaçãorelacionadocomoatributodescricaodatarefa.Tambémpodemosconferirseexistealgumerrodevalidação,maisgenérico:

@RequestMapping("adicionaTarefa")publicStringadiciona(@ValidTarefatarefa,BindingResultresult){

if(result.hasErrors()){return"tarefa/formulario";}

ParaexibirasmensagensdevalidaçãonoJSPusamosumtagespecialqueoSpringMVCoferece.Otagsechamaform:errors:

<form:errorspath="tarefa.descricao"/>

Oatributopathindicacomqueatributoessamensagemestárelacionada.

Abaixoestáocódigocompletodoformulárioformulario.jspdapastatarefa.Reparequeépreciso

Mostrandoasmensagensdevalidação

.

Page 171: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

importarotaglibdoSpringMVC:

<%@tagliburi="http://www.springframework.org/tags/form"prefix="form"%><html><body><h3>Adicionartarefas</h3><formaction="adicionaTarefa"method="post">Descrição:<br/><textarearows="5"cols="100"name="descricao"></textarea><br/><form:errorspath="tarefa.descricao"cssStyle="color:red"/><br/><inputtype="submit"value="Adicionar"/></form></body></html>

Para deixar as mensagens de nossa aplicação mais fáceis de alterar, é comum criar um arquivoseparado do HTML que possui apenas mensagens. Este arquivo é normalmente chamadomensagens.propertiesoumessages.properties.

NapastaWEB-INFdoprojetopodemosentãocriarestearquivocomoseguinteconteúdo:

tarefa.adicionada.com.sucesso=Tarefaadicionadacomsucesso!...

Reparequedefinimosasmensagensemumestilode:<chave>=<valor>.

OSpringMVCpodecarregarautomaticamenteestearquivo,desdequealinhaabaixosejaincluídanoarquivospring-context.xml:

<beanid="messageSource"class="org.springframework.context.support.ReloadableResourceBundleMessageSource"><propertyname="basename"value="/WEB-INF/mensagens"/></bean>

Basta então usar a taglibfmt paramostramensagens do arquivo mensagens.properties napáginaHTML:

<fmt:messagekey="tarefa.adicionada.com.sucesso"/>

Podemos ainda personalizar as mensagens de validação do Bean Validation, escrevendo nossasmensagensdentrodoatributomessagedasanotações:

publicclassTarefa{

privateLongid;

Mensagensinternacionalizadas

Personalizandoasmensagensdeerros

.

Page 172: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

@Size(min=5,message="Descriçãodeveterpelomenos5carateres")privateStringdescricao;...

Para não deixar as mensagens de validação espalhadas em nossas classes, podemos isolar estasmensagens no arquivo padrão de mensagens do Bean Validation, chamadoValidationMessages.properties:

tarefa.descricao.pequena=Descriçãodeveconterpelomenos{min}caracteres...

O arquivo deve ficar dentro da pasta src. Depois podemos referenciar as chaves das mensagensdentrodasanotaçõestambémpeloatributomessage:

publicclassTarefa{

privateLongid;

@Size(min=5,message="{tarefa.descricao.pequena}")privateStringdescricao;}

1. ParaconfiguraroframeworkBeanValidationéprecisocopiarquatrojars.

Primeiro,váaoDesktop,eentrenodiretório21/jars-hibernate-validator.

Haverá quatro JARs: classmate-x.x.x.jar, hibernate-validator-x.x.x.Final.jar, jboss-logging-x.x.x.GA.jarevalidation-api-x.x.x.Final.jar

Copie-os (CTRL+C) e cole-os (CTRL+V) dentro do workspace do eclipse na pasta fj21-tarefas/WebContent/WEB-INF/lib

2. Abra a classe Tarefa. Nela é preciso definir as regras de validação através das anotações doframeworkBeanvalidation.Aatributodescricaodeveterpelomenos5caracteres:

publicclassTarefa{

privateLongid;

@Size(min=5)privateStringdescricao;

3. AbraaclasseTarefasControllereprocureométodoadiciona.Coloqueaanotação@ValidnafrentedoparâmetroTarefatarefaeadicioneoparâmetroBindingResultnaassinaturadométodo.

Alémdisso,nomesmométodo,adicioneaverificaçãoseháerrosdevalidação.Ométodocompletofica:

11.12EXERCÍCIOS:VALIDANDOTAREFAS

.

Page 173: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

@RequestMapping("adicionaTarefa")publicStringadiciona(@ValidTarefatarefa,BindingResultresult){

if(result.hasFieldErrors("descricao")){return"tarefa/formulario";}

JdbcTarefaDaodao=newJdbcTarefaDao();dao.adiciona(tarefa);return"tarefa/adicionada";}

4. AbraoJSPformulario.jsp(dapastaWEB-INF/views/tarefa).AdicionenoiníciodapáginaadeclaraçãodataglibdoSpringMVC:

<%@tagliburi="http://www.springframework.org/tags/form"prefix="form"%>

DentrodoHTMLadicioneatagform:errorsacimadotagform.Adicioneapenasotagform:errors:

<form:errorspath="tarefa.descricao"/><formaction="adicionaTarefa"method="post">

5. Reinicie o Tomcat e acesse no seu navegador o endereço http://localhost:8080/fj21-tarefas/novaTarefaEnvieumarequisiçãoSEMpreencheradescriçãodatarefa,amensagemdevalidaçãodeveaparecer.

Comojáconseguimosadicionartarefasemnossaaplicação,precisamossaberoquefoiadicionado.Paraissoprecisamoscriarumanovafuncionalidadequelistaastarefas.AfunçãodessaaçãoseráinvocaroJdbcTarefaDaoparaconseguiralistadastarefasqueestãonobancodedados.Podemosadicionar

11.13LISTANDOASTAREFASEDISPONIBILIZANDOOBJETOSPARAAVIEW

.

Page 174: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

umnovométododentrodaclasseTarefasController:

@RequestMapping("listaTarefas")publicStringlista(){JdbcTarefaDaodao=newJdbcTarefaDao();List<Tarefa>tarefas=dao.lista();return"tarefa/lista";}

Essa lista de tarefas deverá ser disponibilizada para o JSP fazer sua exibição. Para que possamosdisponibilizarumobjetoparao JSP, temosquealteraroretornodométodolista.A ideia é queoSpringMVCnãosórecebeonomedapáginaJSP(tarefa/lista)quandochamaométodolista,oSpringMVCtambémrecebeosdadosparaoJSP.OsdadosparaaexibiçãonatelaeonomedapáginaJSPforamencapsuladospeloSpringMVCemumaclasseespecialquesechamaModelAndView.VamoscriarumobjetodotipoModelAndViewepreencheressemodelocomnossalistadetarefasedefinironomedapáginaJSP.Ométodolistadeveretornaresseobjeto,nãomaisapenasumString.Vejacomoficaocódigo:

@RequestMapping("listaTarefas")publicModelAndViewlista(){JdbcTarefaDaodao=newJdbcTarefaDao();List<Tarefa>tarefas=dao.lista();

ModelAndViewmv=newModelAndView("tarefa/lista");mv.addObject("tarefas",tarefas);returnmv;}

Dessaforma,serádisponibilizadoparaoJSPumobjetochamadotarefasquepodeseracessadoviaExpressionLanguagecomo${tarefas}.PoderíamosemseguidaiterarsobreessalistautilizandoaTagforEachdaJSTLcore.

VendoocódigodaaçãolistapodeaparecerestranhoinstanciarumaclassedoframeworkSpring(ModelAndView) dentro do nosso controlador. Isso até influencia negativamente a testabilidade dométodo. Por isso, O Spring MVC dá uma outra opção, oferece uma alternativa ao uso da classeModelAndView.NanossaaçãopodemosreceberumobjetoquerepresentaomodeloparaonossoJSP.SpringMVCpodepassarumparâmetroparaométododocontroladorque tema funçãodomodelo.Essemodelo podemos preencher com a lista de tarefas.Assim também continuaremos devolver umaStringcomoretornodométodoqueindicaocaminhoparaoJSP:

@RequestMapping("listaTarefas")publicStringlista(Modelmodel){JdbcTarefaDaodao=newJdbcTarefaDao();List<Tarefa>tarefas=dao.lista();model.addAttribute("tarefas",tarefas);return"tarefa/lista";}

Dessamaneiranãoéprecisoinstanciaromodelo,esimapenasdisponibilizaralista.

.

Page 175: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.

CasadoCódigo,ebookcompreçodeebook.

1. Vamoscriaralistagemdasnossastarefasmostrandoseamesmajáfoifinalizadaounão.

Na classe TarefasController adicione o método lista que recebe um Model comoparâmetro:

@RequestMapping("listaTarefas")publicStringlista(Modelmodel){JdbcTarefaDaodao=newJdbcTarefaDao();model.addAttribute("tarefas",dao.lista());return"tarefa/lista";}

Parafazeralistagem,vamosprecisardaJSTL(iremosfazerumforEach),portantoprecisamosimportá-la.Primeiro,váaoDesktopeentrenodiretório21/jars-jstl.

HaverãodoisJARs,javax.servlet.jsp.jstl-x.x.x.jarejavax.servlet.jsp.jstl-api-x.x.x.jar.

Copie-os (CTRL+C) e cole-os (CTRL+V) dentro do workspace do eclipse na pasta fj21-tarefas/WebContent/WEB-INF/lib

NoEclipse,dêumF5noseuprojeto.Pronto,aJSTLjáestáemnossoprojeto.

CrieoJSPquefaráaexibiçãodastarefasdentrodapastaWebContent/WEB-INF/views/tarefa.Chame-odelista.jspeadicioneoseguinteconteúdo:

<%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%><%@tagliburi="http://java.sun.com/jsp/jstl/fmt"prefix="fmt"%><html><body>

<ahref="novaTarefa">Criarnovatarefa</a>

<br/><br/>

EditoraCasadoCódigocomlivrosdeumaformadiferente

11.14EXERCÍCIOS:LISTANDOTAREFAS

.

Page 176: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

<table><tr><th>Id</th><th>Descrição</th><th>Finalizado?</th><th>Datadefinalização</th></tr><c:forEachitems="${tarefas}"var="tarefa"><tr><td>${tarefa.id}</td><td>${tarefa.descricao}</td><c:iftest="${tarefa.finalizadoeqfalse}"><td>Nãofinalizado</td></c:if><c:iftest="${tarefa.finalizadoeqtrue}"><td>Finalizado</td></c:if><td><fmt:formatDatevalue="${tarefa.dataFinalizacao.time}"pattern="dd/MM/yyyy"/></td></tr></c:forEach></table></body></html>

Reinicie o Tomcat e acesse o endereço http://localhost:8080/fj21-tarefas/listaTarefas e veja oresultado.

Tarefas podem ser adicionadas por engano, ou pode ser que não precisemosmais dela, portanto,queremos removê-las. Para fazer essa remoção, criaremos um link na listagem que acabamos dedesenvolverque,aoserclicado, invocaráanovaaçãoparaaremoçãodetarefaspassandoocódigodatarefaparaserremovida.

OlinkpodeserfeitocomHTMLnalistadetarefasdaseguinteforma:

<td><ahref="removeTarefa?id=${tarefa.id}">Remover</a></td>

11.15REDIRECIONANDOAREQUISIÇÃOPARAOUTRAAÇÃO

.

Page 177: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Podemos desenvolver ummétodo para fazer a remoção.A lógica não possui nenhumanovidade,basta recuperarmosoparâmetro comoaprendemosnesse capítulo e invocarmosoDAO para fazer aremoção:

@RequestMapping("removeTarefa")publicStringremove(Tarefatarefa){JdbcTarefaDaodao=newJdbcTarefaDao();dao.remove(tarefa);return"paraondeir???";}

Aquestãoé:Paraquallugarredirecionarousuárioapósaexclusão?

PoderíamoscriarumnovoJSPcomumamensagemdeconfirmaçãodaremoção,masusualmenteisso não costuma ser bom, porque precisaríamos navegar até a lista das tarefas novamente casotenhamos que remover outra tarefa. Seria muito mais agradável para o usuário que ele fosseredirecionadodiretoparaalistadastarefas.

Umadasformasquepoderíamosfazeresseredirecionamentoéenviarousuáriodiretamenteparaapágina que lista as tarefas (tarefa/lista.jsp). Mas, essa não é uma boa abordagem, porqueprecisaríamos,outravez,disponibilizaralistadastarefasparaoJSP,algoquejáfazemosnaaçãodelistarastarefas,ométodolistanaclasseTarefasController.

Jáqueométodolistafazessetrabalho,poderíamos,aoinvésderedirecionaraexecuçãoparaoJSP, enviá-la para essa ação. Para isso, o retorno dométodo deve ser um poucomodificado.VamoscontinuardevolvendoumaStringmasessaStringdeveindicarquequeremoschamarumaoutraação.Podemosfazerumredirecionamentonaladodoservidor(forward)oupelonavegador,noladodocliente(redirect).

Parafazerumredirecionamentonoladodoservidorbastausaroprefixoforwardnoretorno:

@RequestMapping("removeTarefa")publicStringremove(Tarefatarefa){JdbcTarefaDaodao=newJdbcTarefaDao();dao.remove(tarefa);return"forward:listaTarefas";}

Parafazerumredirecionamentonoladodoclienteusamosoprefixoredirect:

@RequestMapping("removeTarefa")publicStringremove(Tarefatarefa){JdbcTarefaDaodao=newJdbcTarefaDao();dao.remove(tarefa);return"redirect:listaTarefas";}

1. Vamosfazerafuncionalidadederemoçãodetarefas.

11.16EXERCÍCIOS:REMOVENDOEALTERANDOTAREFAS

.

Page 178: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Adicionenoarquivolista.jspumacolunacomumlinkqueaoserclicadoinvocaráaActionpararemovertarefa.

<td><ahref="removeTarefa?id=${tarefa.id}">Remover</a></td>

CrieumnovométodoremovenaclasseTarefasControllercomocódigo:

@RequestMapping("removeTarefa")publicStringremove(Tarefatarefa){JdbcTarefaDaodao=newJdbcTarefaDao();dao.remove(tarefa);return"redirect:listaTarefas";}

Acesse a lista de tarefas em http://localhost:8080/fj21-tarefas/listaTarefas e remova algumastarefas.

2. Criaremosa telapara fazeraalteraçãodas tarefas,comoporexemplo,marcá-lacomofinalizada edefinirmosadatadefinalização.

Primeirovamoscriarumnovolinknanossalistagemqueenviaráousuárioparaatelacontendoosdadosdatarefaselecionada:

<td><ahref="mostraTarefa?id=${tarefa.id}">Alterar</a></td>

Vamoscriarumanovaaçãoquedadoumid,devolveráaTarefacorrespondenteparaumJSP,quemostraráosdadosparaqueaalteraçãopossaserfeita.

CrieumnovométodomostranaclasseTarefasController:

@RequestMapping("mostraTarefa")publicStringmostra(Longid,Modelmodel){JdbcTarefaDaodao=newJdbcTarefaDao();model.addAttribute("tarefa",dao.buscaPorId(id));return"tarefa/mostra";}

CrieoJSPmostra.jspdentrodapastaviews/tarefaparamostraratarefaescolhida:

<%@taglibprefix="fmt"uri="http://java.sun.com/jsp/jstl/fmt"%>

<html><body><h3>Alterartarefa-${tarefa.id}</h3><formaction="alteraTarefa"method="post">

<inputtype="hidden"name="id"value="${tarefa.id}"/>

Descrição:<br/><textareaname="descricao"cols="100"rows="5"><%----%>${tarefa.descricao}<%----%></textarea><br/>

Finalizado?<inputtype="checkbox"name="finalizado"value="true"${tarefa.finalizado?'checked':''}/><br/>

.

Page 179: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Datadefinalização:<br/><inputtype="text"name="dataFinalizacao"value="<fmt:formatDatevalue="${tarefa.dataFinalizacao.time}"pattern="dd/MM/yyyy"/>"/><br/>

<inputtype="submit"value="Alterar"/></form></body></html>

Para o Spring MVC saber converter automaticamente a data no formato brasileiro para umCalendar éprecisousar a anotaçã[email protected] a classeTarefa e adicione aanotaçãoacimadoatributodataFinalizacao:

@DateTimeFormat(pattern="dd/MM/yyyy")privateCalendardataFinalizacao;

Falta criar um método que cuidará da alteração da tarefa. Na classe TarefasControlleradicioneessemétodo:

@RequestMapping("alteraTarefa")publicStringaltera(Tarefatarefa){JdbcTarefaDaodao=newJdbcTarefaDao();dao.altera(tarefa);return"redirect:listaTarefas";}

Acessealistadetarefasemhttp://localhost:8080/fj21-tarefas/listaTarefasealterealgumastarefas.

AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,

Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex-aluno daCaelumtem15%dedescontonestelink!

ConheçaoscursosonlineAlura.

1. Adicioneocampocomcalendárioque fizemosnocapítulodecriaçãodeTagsemnossoprojetoeutilize-onoformuláriodealteração.

JáconheceoscursosonlineAlura?

11.17DESAFIO-CALENDÁRIO

.

Page 180: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Sempre que precisamos finalizar uma tarefa, precisamos entrar na tela de alteração da tarefa quequeremoseescolheradatadefinalização.Essadatadefinalizaçãonamaioriadasvezeséaprópriadataatual.

Para facilitar a usabilidade para o usuário, vamos adicionar umnovo link na nossa tabela que sechamará"Finalizaragora".Aoclicarnesselink,umaaçãoseráinvocadaparafinalizarmosatarefanodiaatual.

A questão é que não queremos navegar para lugar algum ao clicarmos nesse link. Queremospermanecernamesmatela,semquenadaaconteça,nemsejarecarregado.

Ouseja,dealgumaformaprecisamosmandararequisiçãoparaaação,masaindaassimprecisamosmanter a página do jeito que ela estava ao clicar no link. Podemos fazer isso através de uma técnicachamadaAJAX,quesignificaAsynchronousJavascriptandXML.

AJAX nadamais é do que uma técnica que nos permite enviar requisições assíncronas, ou seja,manter a página que estava aberta intacta, e recuperar a resposta dessa requisição para fazermosqualquer processamento com eles. Essas respostas costumam ser XML, HTML ou um formato detransferênciadedadoschamadoJSON(JavascriptObjectNotation).

PararealizarmosumarequisiçãoAJAX,precisamosutilizarJavascript.EnocursovamosutilizarosuportequeojQuerynosforneceparatrabalharcomAJAX.

ParafazermosumarequisiçãoparaumdeterminadoendereçocomojQuery,bastadefinirmosqualmétodoutilizaremosparaenviaressarequisição(POSTouGET).OjQuerynos forneceduas funções:$.poste$.get,cadaumaparacadamétodo.

Paraasfunçõesbastapassarmosoendereçoquequeremosinvocar,comoporexemplo:

$.get("minhaPagina.jsp")

Nessecaso,estamosenviandoumarequisiçãoviaGETparaoendereçominhaPagina.jsp.

Sabendoisso,vamoscriarumlinkqueinvocaráumafunçãoJavascriptefarárequisiçãoAJAXparaumaaçãoquefinalizaráatarefa:

<td><ahref="#"onclick="finalizaAgora(${tarefa.id})">Finalizaragora</a></td>

VamoscriarafunçãofinalizaAgoraquerecebeoiddatarefaqueseráfinalizadaeapassarácomoparâmetroparaaação:

<scripttype="text/javascript">functionfinalizaAgora(id){$.get("finalizaTarefa?id="+id);

11.18MELHORANDOAUSABILIDADEDANOSSAAPLICAÇÃO

.

Page 181: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

}</script>

Por fim, basta criarmos a nossa ação que receberá o parâmetro e invocará um método doJdbcTarefaDaoparafazerafinalizaçãodatarefa.Noentanto,arequisiçãoqueestamosfazendonãogerarárespostanenhumaenóssempreretornamosumaStringoresultadoquedeterminaqualJSPseráexibido.Dessavez,nãoexibiremosnemumJSPeneminvocaremosoutraAction.OprotocoloHTTPsempre retorna um código indicando qual é o estado dessa resposta, ou seja, se foi executado comsucesso,seapáginanãofoiencontrada,sealgumerroaconteceueassimpordiante.

OprotocoloHTTPdefinequeocódigo200indicaqueaexecuçãoocorreucomsucesso,portanto,vamosapenasindicarnanossarespostaocódigo,semdevolvernadanocorpodanossaresposta.ParasetarocódigodarespostaprogramaticamenteprecisamosdoobjetoHttpServletResponse.PodemosreceberarespostaHTTPcomoparâmetrodequalquermétodoqueéumaação.ComarespostanamãopodemoschamarométodosetStatus(200).

Dessaforma,poderíamosterummétodonaclasseTarefasControllerparafazerafinalizaçãodatarefacomoseguintecódigo:

@RequestMapping("finalizaTarefa")publicvoidfinaliza(Longid,HttpServletResponseresponse){JdbcTarefaDaodao=newJdbcTarefaDao();dao.finaliza(id);response.setStatus(200);}

Oprimeiroparâmetroéa idda tarefaquevematravésdarequisição,osegundoéarespostaparasetarocódigoHTTP.

Quando estamos usando um Framework MVC como o Spring, queremos que toda a parte demanipulaçãoderequesteresponsefiqueporcontadoframework.Daformaquemostramosantesépossívelobtero resultadoqueesperamos,masmanipularo statusda respostaéuma tarefaquenãoqueremos fazer diretamente. O Spring nos ajuda nessa tarefa, fazendo com que o retorno do nossométodosejaHTTP200,excetoemcasodealgumaexception.Paraisso,[email protected]óprionomedaannotation fala, tudoque for retornado, seráocorpodanossaresposta.Ousenadaforretornado,entãoarespostaserávaziaporémostatusHTTPserá200.Nossocódigopodeficarmaisenxutoesemamanipulaçãodoresponse:

@ResponseBody@RequestMapping("finalizaTarefa")publicvoidfinaliza(Longid){JdbcTarefaDaodao=newJdbcTarefaDao();dao.finaliza(id);}

11.19 UTILIZANDO AJAX PARA MARCAR TAREFAS COMOFINALIZADAS

.

Page 182: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Através do jQuery, podemos enviar uma requisição AJAX para o servidor, e na ação vamosmanipulararespostaesetarapenasostatus200.Tambémseriaútilnotificarousuáriodaaplicaçãoquearequisição finalizoucomsucesso.O jQuery já forneceum jeitomuito simplesde implementar isso.Éprecisoadicionarno JavaScriptuma funçãoqueéchamadaquandoarequisição terminacomsucesso(status200).

<scripttype="text/javascript">functionfinalizaAgora(id){$.get("finalizaTarefa?id="+id,function(dadosDeResposta){alert("TarefaFinalizada!");});}</script>

Repare que $.get recebe mais uma função como parâmetro (também chamado callback desucesso).Nela,definimosapenasumsimplesalertparamostrarumamensagemaousuário.Tambémépossível manipular o HTML da página dinamicamente. O jQuery oferece recursos poderosos paraalterarqualquerelementoHTMLdentrodonavegador.

Por exemplo, podemos selecionar um elemento da página pela id e mudar o conteúdo desseelemento:

$("#idDoElementoHTML").html("NovoconteúdoHTMLdesseelemento");

Para o nosso exemplo, então é interessante atualizar a coluna da tarefa para indicar que ela foifinalizada:

$("#tarefa_"+id).html("Tarefafinalizada");

LeiamaissobreojQuerynadocumentação:

http://api.jquery.com/jQuery.get/http://api.jquery.com/id-selector/

Querendoaprenderaindamaissobre?Esclarecerdúvidasdosexercícios?Ouvirexplicaçõesdetalhadascomuminstrutor?ACaelum oferece o cursoFJ-21 presencial nas cidades de São Paulo, Rio deJaneiroeBrasília,alémdeturmasincompany.

ConsulteasvantagensdocursoJavaparaDesenvolvimentoWeb

VocêpodetambémfazerocursoFJ-21dessaapostilanaCaelum

11.20 CONFIGURAR O SPRING MVC PARA ACESSAR ARQUIVOS

.

Page 183: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

OcontroladordoSpringMVC,ousejaoservletnoweb.xml,foiconfiguradopararecebertodasasrequisições incluindo essas que foram enviadas para receber o conteúdo de arquivos comuns comoimagens, css ou scripts. Queremos que o controlador não atenda essas requisições que não são paraações.Paraissoéprecisoadicionarnoarquivospring-context.xmlummapeamentoqueinformaaoSpringMVCqueeledeveignorartodoacessoaconteúdoestático.

<mvc:default-servlet-handler/>

1. Abraoarquivospring-context.xmleacrescente:

<mvc:default-servlet-handler/>

Na pasta WebContent crie uma nova pasta resources, vamos colocar nela tudo relativo aconteúdoestáticodonossosistema.

2. Vamos adicionar AJAX na nossa aplicação. Para isso, utilizaremos o jQuery que precisamosimportarparanossoprojetoeemnossaspáginas.

VáaoDesktop,eentrenapasta21;

Copieodiretóriojs e cole-odentrodeWebContent/resources no seuprojeto fj21-tarefas;Casovocêestejaemcasa,façaodownloademhttp://jquery.com/download

Precisamosimportaro jQueryemnossapáginade listagem.Para isso,adicione logoapósaTag<html>oseguintecódigonoarquivolista.jsp:

<head><scripttype="text/javascript"src="resources/js/jquery.js"></script></head>

Pronto,importamosojQueryparanossaaplicação.

3. Casoatarefanãoestejafinalizada,queremosqueelapossuaumnovolinkquesechamará"Finalizaragora".Aoclicarnele,seráchamadaviaAJAXumaActionquemarcaráatarefacomofinalizadaeadatadehojeserámarcadacomoadatadefinalizaçãodamesma.

Altereacolunaquemostraa tarefacomonão finalizadanoarquivolista.jsp.Adicioneumlinkqueaoserclicada,chamaráumafunçãoJavascriptpassandooidda tarefapara finalizar.Tambémadicioneumaidparacadaelemento<td>.

Noarquivoprocureoc:ifparatarefasnãofinalizadas,altereoelementotddentroc:if:

<c:iftest="${tarefa.finalizadoeqfalse}"><tdid="tarefa_${tarefa.id}"><ahref="#"onClick="finalizaAgora(${tarefa.id})">

COMUNS

11.21EXERCÍCIOS:AJAX

.

Page 184: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Finalizaagora!</a></td></c:if>

Crie a função JavascriptfinalizaAgora para chamar a ação que criaremos a seguir via umarequisiçãoPOST:

<!--ComeçodapáginacomoimportdoJavascript--><body><scripttype="text/javascript">functionfinalizaAgora(id){$.post("finalizaTarefa",{'id':id},function(){//selecionandooelementohtmlatravésda//IDealterandooHTMLdele$("#tarefa_"+id).html("Finalizado");});}</script>

<ahref="novaTarefa">Criarnovatarefa</a><br/><br/>

<table><!--Restodapáginacomatabela-->

4. Vamos criar o método para finalizar a tarefa. Após o mesmo ser executado, ele não deverá nosredirecionarparalugarnenhum,apenasindicarqueaexecuçãoocorreucomsucesso.

AbraaclasseTarefasControllerAdicioneométodofinalizacomoconteúdo:

@ResponseBody@RequestMapping("finalizaTarefa")publicvoidfinaliza(Longid){JdbcTarefaDaodao=newJdbcTarefaDao();dao.finaliza(id);}

Acessealistagemhttp://localhost:8080/fj21-tarefas/listaTarefasecliquenonovolinkparafinalizartarefa.Atelamudasemprecisarumaatualizaçãointeiradapágina.

5. (Opcional,Avançado)Nomesmoestilodoexercícioanterior,useojQueryparaacionarométodoremoveTarefaquandoclicadoemumbotãode"excluir".Paraisso,crieumanovacolunanatabela

.

Page 185: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

comumlinkqueoonClickvaichamaroendereçoassociadoaremoveTarefa,eviaAJAXdevemosremoveralinhadatabela.PraissovocêpodeusarumrecursopoderosodojQueryepedirquesejaescondidaalinhadeondeveiooclique:

$(elementoHtml).closest("tr").hide();

Dessamaneiravocênemprecisariausaridsnastrs.

AgoraaofinalizarnossatarefaviaAJAXousuáriotemumfeedbacknaalteraçãodoHTMLdeNãoFinalizadoparaFinalizado.Porémtodasastarefasfinalizadaspossuemacolunadedatadefinalizaçãopreenchidas,menosasqueacabamosdefinalizar.

Pararesolveresseproblema,dealgumaformaonossoControllerdeveriapassarumadataparanossojQuery.Mascomo?Umasoluçãopossívelseriaescrevê-ladiretonoresponse.Algoparecidocomisso:

@RequestMapping("finalizaTarefa")publicvoidfinaliza(Longid,HttpServletResponseresponse)throwsIOException{JdbcTarefaDaodao=newJdbcTarefaDao();dao.finaliza(id);DatedataDeFinalizacao=dao.buscaPorId(id).getDataFinalizacao().getTime();Stringdata=newSimpleDateFormat("dd/MM/yyyy").format(dataDeFinalizacao);response.getWriter().write(data);response.setStatus(200);}

ResolvenossoproblemamasaindaassimteríamosqueficartrabalhandodiretoemumcamadamaisbaixaquesãoasclassesdeHTTPServletRequesteHTTPServletResponse.Agoraalémde finalizarumatarefanossaactiontemasresponsabilidadesdebuscarpeladatafinalizada,formataradata,escrevernoresponseemudarostatuspara200.Responsabilidadedemais,nãoémesmo?

RetornarumaJSPjánostrazobenefíciodostatus200,necessárioparanossafunçãodecallbacknojQuery.SabendodissousaremosumaJSPpararenderizaradataformatada.MasanteséprecisopassaressadataanossaJSP,ousimplesmentepassarumaTarefaparaelaedepoisfazercomqueaActionretorneaStringreferenteaJSP.

@RequestMapping("finalizaTarefa")publicStringfinaliza(Longid,Modelmodel){JdbcTarefaDaodao=newJdbcTarefaDao();dao.finaliza(id);model.addAttribute("tarefa",dao.buscaPorId(id));return"tarefa/dataFinalizada";}

AgorasófaltarealmentecriarmosoarquivodataFinalizadanapasta/WEB-INF/views/tarefaeformataradatausandoatag.

<%@tagliburi="http://java.sun.com/jsp/jstl/fmt"prefix="fmt"%>

11.22PARASABERMAIS:ALTERANDOVALORDADATACOMAJAX

.

Page 186: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

<fmt:formatDatevalue="${tarefa.dataFinalizacao.time}"pattern="dd/MM/yyyy"/>

Legal, já renderizamos uma data formatada e por consequência o status 200 é enviado para ojQuery.SóqueatéagoranãofizemosnadacomessadataqueoJSPrenderizou.Paraquesepeguealgoenviado pelo nosso servidor, a função de callback deve receber um parâmetro com esse conteúdo.Vamosexecutarumalertcomestavariável.

<scripttype="text/javascript">functionfinalizaAgora(id){$.post("finalizaTarefa",{'id':id},function(resposta){$("#tarefa_"+id).html("Finalizado");alert(resposta);});}</script>

Aexecuçãodessealertnosmostraadata,faltaapenasinseri-laemlugarapropriado.VamosusaramesmaestratégiaqueusamosparamudardeNãoFinalizadoparaFinalizado,atrelandoumidanossa<td>referenteaocampodededata.

<tdid="tarefa_data_${tarefa.id}"><fmt:formatDatevalue="${tarefa.dataFinalizacao.time}"pattern="dd/MM/yyyy"/></td>

Fazendoissobastatrocarmosoconteúdodo<td>nafunção.

<scripttype="text/javascript">functionfinalizaAgora(id){$.post("finalizaTarefa",{'id':id},function(resposta){$("#tarefa_"+id).html("Finalizado");$("#tarefa_data_"+id).html(resposta);});}</script>

Onosso desafio foi cumprido de forma elegante,mas ainda assim poderíamosmelhorar o nossocódigo.AfunçãodecallbackdoAJAXtemquemodificardois<td>'s e isso tornaria repetitivoparamodeloscommaisalteraçõesqueanossaTarefa.Sabendoqueafunçãorecebeapenasumparâmetroderesposta,teríamosmaisproblemasaoterquepassarmaisdeumparâmetroaela.Comoresolverestaquestão?Umasoluçãoviávelépassaraprópria<tr>,completa,comasalteraçãonecessárias.ParaissoumaalteraçãonaJSPsefaznecessária.

<%@tagliburi="http://java.sun.com/jsp/jstl/fmt"prefix="fmt"%>

<td>${tarefa.id}</td><td>${tarefa.descricao}</td><td>Finalizada</td><td><fmt:formatDatevalue="${tarefa.dataFinalizacao.time}"pattern="dd/MM/yyyy"/></td><td><ahref="removeTarefa?id=${tarefa.id}">Remover</a></td><td><ahref="mostraTarefa?id=${tarefa.id}">Alterar</a></td>

UmaalteraçãononomedoaquivodataFinalizada.jspseriamaisdoquerecomendada, jáque

.

Page 187: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

agoranãopossui apenasumadata e sim todas as alteraçõesdeuma<tr>.Vamos renomeá-loparafinalizada.jsp . Sem esquecer de modificar o retorno da action de tarefa/dataFinalizada paratarefa/finalizada:

@RequestMapping("finalizaTarefa")publicStringfinaliza(Longid,Modelmodel){...return"tarefa/finalizada";}

Agoraqueretornamosuma<tr> comtodasasalteraçõesvamosmodificara funçãodecallback,para que ela apenasmodifique o conteúdo da <tr> correspondente a tarefa finalizada. Para isso éprecisodiferenciarum<tr>dooutro.Vamosutilizaragoraumidnaprópria<tr>eremoveremososidsdesnecessáriosdos<td>'s.

<table>...<c:forEachitems="${tarefas}"var="tarefa"><trid="tarefa_${tarefa.id}"><td>${tarefa.id}</td><td>${tarefa.descricao}</td>

<c:iftest="${tarefa.finalizadoeqtrue}"><td>Finalizado</td></c:if>

<c:iftest="${tarefa.finalizadoeqfalse}"><td><ahref="#"onClick="finalizaAgora(${tarefa.id})">Finalizar</a></td></c:if>

<td><fmt:formatDatevalue="${tarefa.dataFinalizacao.time}"pattern="dd/MM/yyyy"/></td>

<td><ahref="removeTarefa?id=${tarefa.id}">Remover</a></td><td><ahref="mostraTarefa?id=${tarefa.id}">Alterar</a></td>

</tr>

</c:forEach>....

</table>

Eporúltimo,faltamudarafunçãodecallbackparaqueestamodifiqueoconteúdodo<tr>.

...$.post("finalizaTarefa",{'id':id},function(resposta){$("#tarefa_"+id).html(resposta);});...

.

Page 188: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Agorasim,temosumcódigosimplesefácildemanter.Tudooqueumbomprogramadorgostariadeencontrar.

Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.

CasadoCódigo,LivrosdeTecnologia.

1. Vamos buscar uma tarefa e passá-la para nossa JSP através do Model. Abra oTarefasController.javaemodifiqueaactionquefinalizaumatarefaparaoquesegue:

@RequestMapping("finalizaTarefa")publicStringfinaliza(Longid,Modelmodel){JdbcTarefaDaodao=newJdbcTarefaDao();dao.finaliza(id);model.addAttribute("tarefa",dao.buscaPorId(id));return"tarefa/finalizada";}

2. Agorafaltacriarmosoarquivofinalizada.jspdentrododiretório:/WEB-INF/views/tarefa/.Quedeveráteroseguinteconteúdodarelacionadaatarefafinalizada.

<%@tagliburi="http://java.sun.com/jsp/jstl/fmt"prefix="fmt"%>

<td>${tarefa.id}</td><td>${tarefa.descricao}</td><td>Finalizada</td><td><fmt:formatDatevalue="${tarefa.dataFinalizacao.time}"pattern="dd/MM/yyyy"/></td><td><ahref="removeTarefa?id=${tarefa.id}">Remover</a></td><td><ahref="mostraTarefa?id=${tarefa.id}">Alterar</a></td>

3. Porúltimodevemosmodificaroarquivotarefa/lista.jspparaqueeletenhaumidentificadordecadalinha,ouseja,elementodatabela.Demaneiraanálogaaoquefoifeitonoexercícioanteriorvamosconcatenarcomoidda tarefaumvalordetarefa_. Lembre-sede removeros idsdosoutros'sjáqueelesnãoserãonecessáriosepodemestarcomomesmonomedoidentificadorda.

....

Seuslivrosdetecnologiaparecemdoséculopassado?

11.23EXERCÍCIOSOPCIONAIS:MELHORANDONOSSOAJAX

.

Page 189: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

<c:forEachitems="${tarefas}"var="tarefa"><trid="tarefa_${tarefa.id}"><td>${tarefa.id}</td><td>${tarefa.descricao}</td>

<c:iftest="${tarefa.finalizadoeqtrue}"><td>Finalizado</td></c:if>

<c:iftest="${tarefa.finalizadoeqfalse}"><td><ahref="#"onClick="finalizaAgora(${tarefa.id})">Finalizar</a></td></c:if>

<td><fmt:formatDatevalue="${tarefa.dataFinalizacao.time}"pattern="dd/MM/yyyy"/></td>....</tr>.....

4. EagoraparafazerusodoconteúdorenderizadopelaJSP,énecessárioqueafunçãodecallbackdoAJAX receba como parâmetro esse conteúdo. Vamos alterar a função do finalizaAgora nomesmoarquivolista.jsp,paraoquesegue:

<scripttype="text/javascript">functionfinalizaAgora(id){$.post("finalizaTarefa",{'id':id},function(resposta){$("#tarefa_"+id).html(resposta);});}</script>

5. Reinicieo servidor e verifiqueque agora ao clicarno linkFinalizar o usuário tema alteraçãotantodeNãoFinalizadaparaFinalizadaquandoumamudançanadatadefinalização.

.

Page 190: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO12

"Experiênciaéapenasonomequedamosaosnossoserros."--OscarWilde

Nessecapítulo,vocêaprenderá:

Oescopodesessãoecomoelefunciona;Oquesãointerceptadores;Implantarsuaaplicaçãoemqualquercontainer.

Écomumhojeemdiaacessarmosalgumsitequepeçaparafazermosnossologinparapodermosteracesso a funcionalidades da aplicação. Esse processo também é conhecido como autenticação. Mas,comoositesabe,nasrequisiçõesseguintesquefazemos,quemsomosnós?

Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.

CasadoCódigo,LivrosdeTecnologia.

OprotocoloHTTPutilizadoparaoacessoàpáginasélimitadopornãomanterdetalhescomoqueméquementreumaconexãoeoutra.Pararesolverisso,foiinventadoumsistemaparafacilitaravidados

SPRINGMVC:AUTENTICAÇÃOEAUTORIZAÇÃO

12.1AUTENTICANDOUSUÁRIOS:COMOFUNCIONA?

Seuslivrosdetecnologiaparecemdoséculopassado?

12.2COOKIES

.

Page 191: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

programadores.

Umcookieénormalmenteumpardestringsguardadonocliente,assimcomoummapadestrings.Essepardestringspossuidiversaslimitaçõesquevariamdeacordocomoclienteutilizado,oquetornaatécnica de utilizá-los algo do qual não se deva confiar muito. Já que as informações do cookie sãoarmazenadas no cliente, o mesmo pode alterá-la de alguma maneira... sendo inviável, por exemplo,guardaronomedousuáriologado...

Quandoumcookieésalvonocliente,eleéenviadodevoltaaoservidortodavezqueoclienteefetuarumanovarequisição.Destaforma,oservidorconsegueidentificaraqueleclientesemprecomosdadosqueocookieenviar.

Umexemplodebomusodecookiesénatarefadelembraronomedeusuárionapróximavezqueelequiserselogar,paraquenãotenhaqueredigitaromesmo.

Cadacookiesóéarmazenadoparaumwebsite.Cadawebsitepossuiseuspróprioscookieseestesnãosãovistosemoutrapágina.

Usar Cookies parece facilitarmuito a vida,mas através de um cookie não é possívelmarcar umclientecomumobjeto,somentecomStrings.Imaginegravarosdadosdousuáriologadoatravésdecookies.Serianecessárioumcookieparacadaatributo:usuario,senha,id,datadeinscrição,etc.Semcontarafaltadesegurança.

OCookietambémpodeestardesabilitadonocliente,sendoquenãoserápossívellembrarnadaqueousuáriofez...

Umasessãofacilitaavidadetodosporpermitiratrelarobjetosdequalquertipoaumcliente,nãosendolimitadasomenteàstringseéindependentedecliente.

AabstraçãodaAPIfacilitaotrabalhodoprogramadorpoiselenãoprecisasabercomoéqueasessãofoiimplementadanoservletcontainer,elesimplesmentesabequeafuncionalidadeexisteeestáláparaouso.Seoscookiesestiveremdesabilitados,asessãonãofuncionaráedevemosrecorrerparaumatécnica(trabalhosa)chamadaurl-rewriting.

A sessão nadamais é que um tempo que o usuário permanece ativo no sistema. A cada páginavisitada, o tempo de sessão é zerado. Quando o tempo ultrapassa um limite demarcado no arquivoweb.xml,oclienteperdesuasessão.

Paraconfigurar3minutoscomoopadrãodetempoparaousuárioperderasessãobasta incluiro

12.3SESSÃO

12.4CONFIGURANDOOTEMPOLIMITE

.

Page 192: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

seguintecódigonoarquivoweb.xml:

<session-config><session-timeout>3</session-timeout></session-config>

Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende

Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!

ConheçaaAluraCursosOnline.

Podemoscriarumaaçãoque faráo logindaaplicação.Casoousuário informadona telade loginexista,guardaremosomesmonasessãoeentraremosnosistema,ecasonãoexistavamosvoltarparaapáginadelogin.

OSpringMVCnospossibilitareceberasessãoemqualquermétodo,sóéprecisocolocaroobjetoHttpSessioncomoparâmetro.Porexemplo:

@ControllerpublicclassLoginController{

publicStringefetuaLogin(HttpSessionsession){//....

AsessãoéparecidacomumobjetodotipoMap<String,Object>,podemosguardarnelaqualquerobjetoquequisermosdando-lhesumachavequeéumaString.Portanto,para logarmosousuárionaaplicação poderíamos criar uma ação que recebe os dados do formulário de login e a sessãoHTTP,guardandoousuáriologadodentrodamesma:

@RequestMapping("efetuaLogin")publicStringefetuaLogin(Usuariousuario,HttpSessionsession){if(newJdbcUsuarioDao().existeUsuario(usuario)){session.setAttribute("usuarioLogado",usuario);return"menu";}else{//....

Agoraéamelhorhoradeaprenderalgonovo

12.5REGISTRANDOOUSUÁRIOLOGADONASESSÃO

12.6EXERCÍCIO:FAZENDOOLOGINNAAPLICAÇÃO

.

Page 193: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

1. Vamos criar o formulário de Login, uma ação para chamar este formulário e uma outra querealmenteautenticaousuário.

Crie a página formulario-login.jsp dentro de WebContent/WEB-INF/views com oconteúdo:

<html><body><h2>PáginadeLogindasTarefas</h2><formaction="efetuaLogin"method="post">Login:<inputtype="text"name="login"/><br/>Senha:<inputtype="password"name="senha"/><br/><inputtype="submit"value="Entrarnastarefas"/></form></body></html>

Crie uma nova classe chamada LoginController no pacote br.com.caelum.tarefas.controller . Crie um método para exibir o formulario-

login.jsp:

@ControllerpublicclassLoginController{

@RequestMapping("loginForm")publicStringloginForm(){return"formulario-login";}}

Namesma classe LoginController coloque o método que verifica o existência do usuario.AcrescenteométodoefetuaLogin:

@RequestMapping("efetuaLogin")publicStringefetuaLogin(Usuariousuario,HttpSessionsession){if(newJdbcUsuarioDao().existeUsuario(usuario)){session.setAttribute("usuarioLogado",usuario);return"menu";}return"redirect:loginForm";}

Apósousuárioselogar,eleseráredirecionadoparaumapáginaqueconterálinksparaasoutraspáginasdosistemaeumamensagemdeboasvindas.

Crieapáginamenu.jspemWebContent/WEB-INF/viewscomocódigo:

<html><body><h2>PáginainicialdaListadeTarefas</h2><p>Bemvindo,${usuarioLogado.login}</p><ahref="listaTarefas">Cliqueaqui</a>paraacessaralistadetarefas</body></html>

.

Page 194: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Acesseapáginadeloginemhttp://localhost:8080/fj21-tarefas/loginFormeseloguenaaplicação.

Verifiqueobancodedadosparaterumloginesenhaválidos.Paraisso,noterminalfaça:

mysql-uroot-pusefj21;select*fromusuarios;

Usandoasenhacorretaprobanco,sehouver.Seatabelanãoexistir,vocêpodecriá-laexecutandoocomando:

createtableusuarios(loginVARCHAR(255),senhaVARCHAR(255));

Casonãoexistausuárioscadastrados,cadastrealgumutilizandoomesmoterminalabertoantesdaseguintemaneira:

insertintousuarios(login,senha)values('seu_usuario','sua_senha');

Nãopodemospermitirquenenhumusuárioacesseastarefassemqueeleestejalogadonaaplicação,pois essa não é uma informação pública. Precisamos portanto garantir que antes de executarmosqualqueraçãoousuárioestejaautenticado,ouseja,armazenadonasessão.

UtilizandooSpringMVC,podemosutilizaroconceitodos Interceptadores,que funcionamcomoFiltrosqueaprendemosanteriormente,mascomalgumasfuncionalidadesamaisqueestãorelacionadasaoframework.

Para criarmos um Interceptador basta criarmos uma classe que implemente a interface org.springframework.web.servlet.HandlerInterceptor . Ao implementar essa interface,precisamosimplementar3métodos:preHandle,postHandleeafterCompletion.

OsmétodospreHandleepostHandleserãoexecutadosantesedepois,respectivamente,daação.EnquantoométodoafterCompletionéchamadonofinaldarequisição,ousejaapósterrenderizadooJSP.

Paranossaaplicaçãoqueremosverificaroacessoantesdeexecutarumaação,por issovamosusarapenas o método preHandle da interface HandlerInterceptor . Porém, usando a interface HandlerInterceptor somos obrigados implementar todos os métodos definidos na interface.Queremos usar apenas o preHandle . Por isso o Spring MVC oferece uma classe auxiliar(HandlerInterceptorAdapter) que já vem comuma implementação padrão para cadamétodo dainterface.Entãoparafacilitarotrabalhovamosestenderessaclasseesobrescreverapenasométodoqueédonossointeresse:

12.7 BLOQUEANDO ACESSOS DE USUÁRIOS NÃO LOGADOS COMINTERCEPTADORES

.

Page 195: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

publicclassAutorizadorInterceptorextendsHandlerInterceptorAdapter{

@OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objectcontroller)throwsException{//....response.sendRedirect("loginForm");returnfalse;}}

O método preHandle recebe a requisição e a resposta, além do controlador que está sendointerceptado.O retorno é um booleano que indica se queremos continuar com a requisição ou não.Portanto,aclasseAutorizadorInterceptorsódevedevolvertrueseousuárioestálogado.Casoousuárionãoestejaautorizadovamosredirecionarparaoformuláriodelogin.

ParapegarousuáriologadoéprecisoacessarasessãoHTTP.Oobjetorequestpossuiummétodoquedevolveasessãodousuárioatual:

HttpSessionsession=request.getSession();

DessamaneirapodemosverificarnoInterceptadoraexistênciadoatributousuarioLogado:

publicclassAutorizadorInterceptorextendsHandlerInterceptorAdapter{

@OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objectcontroller)throwsException{

if(request.getSession().getAttribute("usuarioLogado")!=null){returntrue;}

response.sendRedirect("loginForm");returnfalse;}}

Falta só mais uma verificação. Existem duas ações na nossa aplicação que não necessitam deautorização.SãoasaçõesdoLoginController,necessáriasparapermitiraautenticaçãodousuário.Alémdisso,vamosgarantir tambémqueapastaderesourcespodeseracessadamesmosem login.Essapastapossuiasimagens,cssearquivosJavaScript.NoentantoaclasseAutorizadorInterceptorfica:

publicclassAutorizadorInterceptorextendsHandlerInterceptorAdapter{

@OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objectcontroller)throwsException{

Stringuri=request.getRequestURI();if(uri.endsWith("loginForm")||uri.endsWith("efetuaLogin")||uri.contains("resources")){

.

Page 196: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

returntrue;}

if(request.getSession().getAttribute("usuarioLogado")!=null){returntrue;}

response.sendRedirect("loginForm");returnfalse;}}

Ainda precisamos registrar o nosso novo interceptador. Mas o Spring MVC não permite quefaçamos isso via anotações, então usaremos a configuração via XML nesse caso. Já vimos o arquivo spring-context.xml , nele vamos usar o tag mvc:interceptors para cadastrar a classeAutorizadorInterceptor:

<mvc:interceptors><beanclass="br.com.caelum.tarefas.interceptor.AutorizadorInterceptor"/></mvc:interceptors>

Caso seja necessário alguma ordem na execução de diversos interceptors, basta registrá-los nasequênciadesejadadentrodatagmvc:interceptors.

Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.

CasadoCódigo,ebookcompreçodeebook.

1. VamoscriarumInterceptorquenãopermitiráqueousuárioacesseasaçõessemantesterlogadonaaplicação.

CrieaclasseAutorizadorInterceptornopacotebr.com.caelum.tarefas.interceptorEstenda a classe HandlerInterceptorAdapter do packageorg.springframework.web.servlet.handler

EditoraCasadoCódigocomlivrosdeumaformadiferente

12.8EXERCÍCIOS:INTERCEPTANDOASREQUISIÇÕES

.

Page 197: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

SobrescreveométodopreHandle.OusuáriosópodeacessarosmétodosdoLoginControllerSEM ter feito o login.Caso outra lógica seja chamada é preciso verificar se o usuário existe nasessão.Existindonasessão, seguiremoso fluxonormalmente,casocontrário indicaremosqueousuário não está logado e que deverá ser redirecionado para o formulário de login. O códigocompletodointerceptadorfica:

publicclassAutorizadorInterceptorextendsHandlerInterceptorAdapter{

@OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objectcontroller)throwsException{

Stringuri=request.getRequestURI();if(uri.endsWith("loginForm")||uri.endsWith("efetuaLogin")||uri.contains("resources")){returntrue;}

if(request.getSession().getAttribute("usuarioLogado")!=null){returntrue;}

response.sendRedirect("loginForm");returnfalse;}}

Temos que registrar o nosso novo interceptador noXMLdo spring.Abra o arquivospring-context.xml.Dentrodatag<beans>adicione:

<mvc:interceptors><beanclass="br.com.caelum.tarefas.interceptor.AutorizadorInterceptor"/></mvc:interceptors>

2. Reinicieoservidoretenteacessaralistadetarefasemhttp://localhost:8080/fj21-tarefas/listaTarefas.Vocêdeveráserredirecionadoparaoformuláriodelogin.

1. Façaologoutdaaplicação.Crieumlinknomenu.jspque invocaráummétodoqueremoveráousuáriodasessãoeredirecioneanavegaçãoparaaactiondoformuláriodelogin(loginForm).

Nomenu.jspacrescente:

<ahref="logout">Sairdosistema</a>

NaclasseLoginControlleradicioneométodoparaologouteinvalideasessãodousuário:

@RequestMapping("logout")publicStringlogout(HttpSessionsession){

12.9EXERCÍCIOSOPCIONAIS:LOGOUT

.

Page 198: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

session.invalidate();return"redirect:loginForm";}

.

Page 199: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO13

"Fazertroçadafilosofiaé,naverdade,filosofar"--BlaisePascal

Nessecapítulo,vocêaprenderá:

OqueéumcontainerdeinversãodecontrollerComogerenciarqualquerobjetoeinjetardependênciascomoSpringImplantarsuaaplicaçãoemqualquercontainer.

NanossaclasseTarefasControllerusamosoJdbcTarefaDaopara executarosmétodosmaiscomunsnobancodedados relacionadocomaTarefa. Emcadamétododo controller criamosumJdbcTarefaDaoparaacessarobanco.ReparenocódigoabaixoquantasvezesinstanciamosoDAOnamesmaclasse:

@ControllerpublicclassTarefasController{

@RequestMapping("mostraTarefa")publicStringmostra(Longid,Modelmodel){JdbcTarefaDaodao=newJdbcTarefaDao();model.addAttribute("tarefa",dao.buscaPorId(id));return"tarefa/mostra";}

@RequestMapping("listaTarefas")publicStringlista(Modelmodel){JdbcTarefaDaodao=newJdbcTarefaDao();model.addAttribute("tarefas",dao.lista());return"tarefa/lista";}

@RequestMapping("adicionaTarefa")publicStringadiciona(@ValidTarefatarefa,BindingResultresult){

if(result.hasFieldErrors("descricao")){return"tarefa/formulario";}

JdbcTarefaDaodao=newJdbcTarefaDao();dao.adiciona(tarefa);return"tarefa/adicionada";}

SPRINGIOCEDEPLOYDAAPLICAÇÃO

13.1 MENOS ACOPLAMENTO COM INVERSÃO DE CONTROLE EINJEÇÃODEDEPENDÊNCIAS

.

Page 200: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

//outrosmétodosremove,alteraefinalizatambémcriamaJdbcTarefaDao}

AclasseTarefasControllerinstanciaumobjetodotipoJdbcTarefaDaomanualmente.EstamosrepetindoacriaçãodoDAOemcadamétodo.Podemosmelhorarocódigo,criaroJdbcTarefaDaonoconstrutordaclasseTarefasControllereusarumatributo.AssimpodemosapagartodasaslinhasdecriaçãodoDAO:

@ControllerpublicclassTarefasController{

privateJdbcTarefaDaodao;

publicTarefasController(){this.dao=newJdbcTarefaDao();}

@RequestMapping("mostraTarefa")publicStringmostra(Longid,Modelmodel){//daojáfoicriadomodel.addAttribute("tarefa",dao.buscaPorId(id));return"tarefa/mostra";}

@RequestMapping("listaTarefas")publicStringlista(Modelmodel){//daojáfoicriadomodel.addAttribute("tarefas",dao.lista());return"tarefa/lista";}

//outrosmétodostambémaproveitamoatributodao

}

Onossocódigomelhorou,poistemosmenoscódigoparamanter,mashámaisumproblema.ReparequecontinuamosresponsáveispelacriaçãodoDAO.AclassequefazusodesteDAOestáintimamenteligada com a maneira de instanciação do mesmo, fazendo com que ela mantenha um alto grau deacoplamento.

DizemosqueaclasseTarefasControllertemumadependênciacomoJdbcTarefaDao.VáriosmétodosdeladependemdoJdbcTarefaDao.Nocódigoacimacontinuamosadarnewdiretamentenaimplementação JdbcTarefaDao para usá-la. Nossa aplicação cria a dependência, chamandodiretamenteaclasseespecífica.

O problema em gerenciar a dependência diretamente na aplicação fica evidente se analisamos aclasse JdbcTarefaDao . Se a classe precisar de um processo de construção mais complicado,precisaremosnospreocuparcomissoemtodososlugaresondecriamosoJdbcTarefaDao.

ParaentenderissovamosverificaroconstrutordoDAO:

publicclassJdbcTarefaDao{

.

Page 201: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

privatefinalConnectionconnection;

publicJdbcTarefaDao(){try{this.connection=newConnectionFactory().getConnection();}catch(SQLExceptione){thrownewRuntimeException(e);}}

//métodosomitidos}

Reparequeaquiexisteomesmoproblema.ODAOtambémresolveasuadependênciaecriaatravésda ConnectionFactory, a conexão. Estamos acoplados à classe ConnectionFactory enquantoapenasqueremosumaconexão.Aclasseestácomaresponsabilidadedeprocuraradependência.Essaresponsabilidadedeveestaremoutrolugar.Paramelhorar,vamosentãodeclararadependênciaemumlugar natural que é o construtor. O código fica muito mais simples e não precisa mais daConnectionFactory:

publicclassJdbcTarefaDao{

privatefinalConnectionconnection;

publicJdbcTarefaDao(Connectionconnection){this.connection=connection;}

//métodosomitidos}

Jácomessapequenamudança,nãopodemoscriaroJdbcTarefaDaosemnospreocuparmoscomaconexãoantes.VejacomoficariaocódigodaclasseTarefasController:

@ControllerpublicclassTarefasController{

privateJdbcTarefaDaodao;

publicTarefasController(){try{Connectionconnection=newConnectionFactory().getConnection();this.dao=newJdbcTarefaDao(connection);}catch(SQLExceptione){thrownewRuntimeException(e);}}

//métodosomitidos}

AclasseTarefasControllernãosócriaráoDAO,comotambémaconexão. Jádiscutimosquenãoqueremosserresponsáveis,entãovamosagirigualaoJdbcTarefaDaoedeclararadependêncianoconstrutor.Novamentevaisimplificardemaisonossocódigo:

@ControllerpublicclassTarefasController{

.

Page 202: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

privateJdbcTarefaDaodao;

publicTarefasController(JdbcTarefaDaodao){this.dao=dao;}

//métodosomitidos}

Assimcada classedelega adependênciapara cima enão se responsabilizapela criação.Quem forusaressaclasseTarefasController,agora,vaiprecisarsatisfazerasdependências.MasquemnofinalsepreocupacomacriaçãodoDAOecomaconexão?

Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende

Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!

ConheçaaAluraCursosOnline.

OpadrãodeprojetosDependencyInjection(DI)(Injeçãodedependências),procuraresolveressesproblemas.Aideiaéqueaclassenãomaisresolvaassuasdependênciasporcontaprópriamasapenasdeclaraquedependedealgumaoutraclasse.Edealgumaoutraformaquenãosabemosainda,alguémresolverá essa dependência para nós. Alguém pega o controle dos objetos que liga (ou amarra) asdependências. Não estamos mais no controle, há algum container que gerencia as dependências eamarratudo.Essecontainerjáexistiaejáusamoselesemsaber.

Reparequecom@Controller já definimosque anossa classe fazpartedo SpringMVC,mas aanotaçãovaialémdisso.TambémdefinimosquequeremosqueoSpringcontroleoobjeto.Springénofundoumcontainerquedánew paranós e tambémsabe resolver e ligar asdependências.Por isso,oSpringtambéméchamadoContainerIoC(InversionofControl)ouContainerDI.

Essas são as principais funcionalidades de qualquer container de inversão de controle/injeção dedependência. O Spring é um dos vários outros containers disponíveis no mundo Java. Segue umapequenalistacomoscontainersmaisfamosos:

Agoraéamelhorhoradeaprenderalgonovo

13.2CONTAINERDEINJEÇÃODEDEPENDÊNCIAS

.

Page 203: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Spring IoC ou sóSpring base de qualquer projeto Spring, popularizouDI e o desenvolvimentocomPOJOsJBossSeam2ContainerDIqueseintegramuitobemcomJSF,principalmentenaversão1.2doJSFGuiceContainerDIcriadopeloGooglequefavoreceuconfiguraçõesprogramáticassemXMLCDIEspecificaçãoqueentroucomoJavaEE6,fortementeinfluenciadopeloJBossSeameGuicePicoContainermuitoleveeflexível,foipioneironessaáreaEJB3ContainerJavaEEcomumsuportelimitadoaoDI

OSpringContainersabecriaroobjeto,mastambémligaasdependênciasdele.ComooSpringestánocontrole,eleadministratodoociclodavida.Paraissoacontecerseráprecisodefinirpelomenosduasconfigurações:

declararoobjetocomocomponenteligaradependência

ParareceberoDAOemnossocontrolador,usaremosaanotação@Autowiredacimadoconstrutor(wire-amarrar).IssoindicaaoSpringqueeleprecisaresolvereinjetaradependência:

@ControllerpublicclassTarefasController{

privateJdbcTarefaDaodao;

@AutowiredpublicTarefasController(JdbcTarefaDaodao){this.dao=dao;}

//métodosomitidos}

ParaoSpringconseguircriaroJdbcTarefaDaovamosdeclararaclassecomocomponente.AquioSpringpossuiaanotação@Repositoryquedeve serutilizadanasclassescomooDAO.Alémdisso,vamos também amarrar a conexão com @Autowired . Veja o código similar a classeTarefasController:

@RepositorypublicclassJdbcTarefaDao{

privatefinalConnectionconnection;

@AutowiredpublicJdbcTarefaDao(Connectionconnection){this.connection=connection;}

//métodosomitidos}

13.3CONTAINERSPRINGIOC

.

Page 204: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Aousar@Autowirednoconstrutor,oSpringtentadescobrircomoabrirumaconexão,masclaroqueoContainernão faz ideia comqual bancoqueremosnos conectar.Para solucionar issoo Springoferece uma configuração de XML que define um provedor de conexões. No mundo JavaEE, esteprovedoréchamadoDataSourceeabstraiasconfiguraçõesdeDriver,URL,etcdaaplicação.

Sabendo disso, devemos declarar um DataSource no XML do Spring, dentro do spring-context.xml:

<beanid="mysqlDataSource"class="org.apache.commons.dbcp.BasicDataSource"><propertyname="driverClassName"value="com.mysql.jdbc.Driver"/><propertyname="url"value="jdbc:mysql://localhost/fj21"/><propertyname="username"value="root"/><propertyname="password"value="<SENHADOBANCOAQUI>"/></bean>

DefinimosumbeannoXML.Umbeanéapenasumsinônimoparacomponente.Aofinal,cadabeanse torna um objeto administrado pelo Spring. Para o Spring Container, a mysqlDataSource , o JdbcTarefaDao e TarefasController são todos componentes(ou beans) que foramligados/amarrados.Ouseja,umdependeaooutro.OSpringvaicriartodoseadministrarociclodavidadeles.

Com a mysqlDataSource definida, podemos injetar ela na JdbcTarefaDao para recuperar aconexãoJDBC:

@RepositorypublicclassJdbcTarefaDao{

privatefinalConnectionconnection;

@AutowiredpublicJdbcTarefaDao(DataSourcedataSource){try{this.connection=dataSource.getConnection();}catch(SQLExceptione){thrownewRuntimeException(e);}}

//métodosomitidos}

Pronto! Repare que no nosso projeto o controlador -- depende do --> dao que -- depende do -->datasource.OSpringvaiprimeirocriaramysqlDataSource,depoisoDAOenofinalocontrolador.Eleéoresponsávelpelacriaçãodetodaacadeiadedependências.

.

Page 205: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

SPRINGIOC

Vimos apenas uma parte do poderoso framework Spring. A inversão de controle não só selimitaainjeçãodedependências,oSpringtambémsabeassumiroutraspreocupaçõescomunsentreaplicaçõesdenegócios,comoporexemplo,tratamentodetransaçãoousegurança.

Além disso, é comum integrar outros frameworks e bibliotecas com Spring. Não é raroencontrarprojetosqueusamcontroladoresMVCcomoStrutsouJSFcomSpring.OSpringémuitoflexívelesabegerenciarqualquercomponente,sejaelesimples,comoumaclassedonossoprojeto,ouumframeworksofisticadocomooHibernate.OtreinamentoFJ-27mostracomoaproveitaromelhordoSpring.

Vimos como injetar uma dependência com Spring usando o construtor da classe junto com aanotaçã[email protected] éumpontodeinjeção quedeixa claroque essadependência éobrigatóriajáquenãohácomoinstanciaroobjetosempassarpeloseuconstrutor.

Háoutrospontosdeinjeçãocomo,porexemplo,oatributo.Podemosusaraanotação@Autowireddiretamente no atributo. Assim o construtor não émais necessário, por exemplo podemos injetar oJdbcTarefaDaonaclasseTarefasController:

@ControllerpublicclassTarefasController{

@AutowiredprivateJdbcTarefaDaodao;

//semconstrutor}

Outra forma é criar um método dedicado para dependência, normalmente é usado um setteraplicandoaanotaçãoemcimadométodo:

@ControllerpublicclassTarefasController{

privateJdbcTarefaDaodao;

//semconstrutor

@AutowiredpublicvoidsetTarefaDao(JdbcTarefaDaodao){this.dao=dao;}}

Hávantagensedesvantagensdecada forma,masemgeraldevemos favoreceroconstrutor jáque

13.4OUTRASFORMASDEINJEÇÃO

.

Page 206: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

issoéolugarnaturalparaadependência.Noentantoéimportanteconhecerosoutrospontosdeinjeçãopois alguns frameworks/bibliotecas exigem o construtor sem parâmetro, obrigando o desenvolvedorusaroatributooumétodo.ComoveremosnoapêndiceatémesmooSpringprecisaemalgunscasosoconstrutorsemargumentos.

PARASABERMAIS:@INJECT

AinjeçãodedependênciaéumtópicobastantedifundidonaplataformaJava.Existemvárioscontainercomessepoder,tantoqueissoéopadrãoparaamaioriadosprojetosJavahojeemdia.

CDI(ContexteDependencyInjection,JSR-299)éaespecificaçãoqueestásepopularizando.OSpringsódásuportelimitadoaoCDImasaproveitaasanotaçõespadronizadaspelaespecificaçãoJSR-330.Dessamaneira basta adicionar o JAR da especificação (java.inject) no classpath eassimpodemossubstituiraanotação@Autowiredcom@Inject:

@ControllerpublicclassTarefasController{

privateJdbcTarefaDaodao;

@InjectpublicTarefasController(JdbcTarefaDaodao){this.dao=dao;}

//métodosomitidos}

Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.

CasadoCódigo,ebookcompreçodeebook.

EditoraCasadoCódigocomlivrosdeumaformadiferente

13.5 EXERCÍCIOS: INVERSÃO DE CONTROLE COM O SPRING

.

Page 207: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

1. ParaconfiguraraDatasourceéprecisocopiardoisJARs.

Primeiro,váaoDesktop,eentrenodiretório21/jars-datasource.

HaverádoisJARs,commons-dbcp-x.x.jarecommons-pool-x.x.jar.

Copie-os (CTRL+C) e cole-os (CTRL+V) dentro de workspace/fj21-

tarefas/WebContent/WEB-INF/lib

2. Noarquivospring-context.xmladicioneaconfiguraçãodaDatasource:

(Dica:umexemplodessaconfiguraçãoencontra-senapasta21/jars-datasource)

<beanid="mysqlDataSource"class="org.apache.commons.dbcp.BasicDataSource"><propertyname="driverClassName"value="com.mysql.jdbc.Driver"/><propertyname="url"value="jdbc:mysql://localhost/fj21"/><propertyname="username"value="root"/><propertyname="password"value="<SENHADOBANCOAQUI>"/></bean>

Reparequedefinimosaspropriedadesdaconexão,igualaantigaclasseConnectionFactory.

3. VamosconfiguraraclasseJdbcTarefaDaocomocomponente(Bean)doSpring.Paraisso,adicioneaanotação@Repositoryemcimadaclasse:

@RepositorypublicclassJdbcTarefaDao{...}

UseCtrl+Shift+Oparaimportaraanotação.

4. Alémdisso,altereoconstrutordaclasseJdbcTarefaDao.Useaanotação@AutowiredemcimadoconstrutorecoloqueaDataSourcenoconstrutor.Atravésdelaobteremosumanovaconexão.AclasseDataSourcevemdopackagejavax.sql.

AltereoconstrutordaclasseJdbcTarefaDao:

@AutowiredpublicJdbcTarefaDao(DataSourcedataSource){try{this.connection=dataSource.getConnection();}catch(SQLExceptione){thrownewRuntimeException(e);}}

AoalteraroconstrutorvãoaparecererrosdecompilaçãonaclasseTarefasController.

5. AbraaclasseTarefaController.NelavamoscriarumatributoparaaJdbcTarefaDaoegeraroconstrutorquerecebeoDAO,novamenteusandoaanotação@Autowired:

CONTAINER

.

Page 208: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

@ControllerpublicclassTarefasController{

privatefinalJdbcTarefaDaodao;

@AutowiredpublicTarefasController(JdbcTarefaDaodao){this.dao=dao;}}

6. Altere todososmétodosquecriamumainstânciadaclasseJdbcTarefaDao.São justamenteessemétodosquepossuemerrosdecompilação.

Removatodasaslinhascomo:

JdbcTarefaDaodao=newJdbcTarefaDao();

Porexemplo,ométodoparalistarastarefasficacomo:

@RequestMapping("listaTarefas")publicStringlista(Modelmodel){model.addAttribute("tarefas",dao.lista());return"tarefa/lista";}

Arrume os outros erros de compilação, apague todas as linhas que instanciam a classeJdbcTarefaDao.

7. ReinicieoTomcateacesseaaplicação.Tudodevecontinuarfuncionando.8. (opcional)AclasseConnectionFactoryaindaénecessária?

Melhoramosgradativamenteanossaaplicaçãomodificandoclasseseutilizandoframeworks,tudonoladodoservidor,masoqueousuáriofinalenxergaéoHTMLgeradoqueéexibidoemseunavegador.Utilizamosalgumastagsparaestruturarasinformações,masnossaapresentaçãoaindadeixaadesejar.Nãoháatrativoestético.

Paraaprimorarovisual,vamosaplicarCSSnasnossaspáginas.CSSéumacrônimoparaCascadingStyleSheets,quepodemostraduzirparaFolhasdeEstiloemCascata.Osestilosdefinemolayout,porexemplo,acor,otamanho,oposicionamentoesãodeclaradosparaumdeterminadoelementoHTML.OCSSalteraaspropriedadesvisuaisdaqueleelementoe,porcascata,todososseuselementosfilhos.Emgeral, o HTML é usado para estruturar conteúdos da página (tabelas, parágrafos, div etc) e o CSSformataedefineaaparência.

AsintaxedoCSStemumaestruturasimples:éumadeclaraçãodepropriedadesevaloresseparadosporum sinal dedois pontos(:), e cadapropriedade é separadaporum sinal deponto e vírgula(;), da

13.6APRIMORANDOOVISUALATRAVÉSDECSS

SintaxeeinclusãodeCSS

.

Page 209: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

seguintemaneira:

background-color:yellow;color:blue;

Como estamos declarando as propriedades visuais de um elemento em outro lugar do nossodocumento, precisamos indicar de alguma maneira a qual elemento nos referimos. Fazemos issoutilizandoumseletorCSS.

Noexemploaseguir,usaremososeletorp,quealterarátodososparágrafosdodocumento:

p{color:blue;background-color:yellow;}

Existem várias lugares que podemos declarar os estilos, mas o mais comum é usar um arquivoexterno, com a extensão .css. Para que seja possível declarar nosso CSS em um arquivo à parte,precisamosindicaremnossodocumentoHTMLumaligaçãoentreeleeafolhadeestilo.

Aindicaçãodeusodeumafolhadeestilosexternadeveserfeitadentrodatag<head> donossodocumentoHTML:

<!DOCTYPEhtml><html><head><linktype="text/css"rel="stylesheet"href="tarefas.css"></head><body><p>Oconteúdodestatagseráexibidoemazulcomfundoamarelo!</p>

</body></html>

Edentrodoarquivotarefas.css:

p{color:blue;background-color:yellow;}

Declaraçãonoarquivoexterno

.

Page 210: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

PROGRAMAÇÃOFRONT-END

Apreocupaçãocomaorganizaçãodocódigonãoéexclusivadoprogramadorback-end,istoé,aquelequeprocessaseucódigonoservidor.

Hátambémoprogramadorfront-end,aqueleresponsávelpelocódigoquerodanonavegadordo cliente, que também deve se preocupar com a organização de seu código, inclusive com aapresentaçãoatravésdeCSSedeumHTMLbemestruturado.

A Caelum oferece os treinamentosWD-43 eWD-47 para quem quer dominar as melhorestécnicas de desenvolvimento Web com semântica perfeita, estilos CSS poderosos e JavaScriptscorretosefuncionais.

1. Noseuprojeto,crieumanovapastacssdentrodapastaWebContent/resources.

2. VáaoDesktopeentrenodiretório21/css.Copieoarquivotarefas.css(CTRL+C) para a pastaWebContent/resources/css(CTRL+V).

3. Abraapáginaformulario-login.jspqueestádentrodapastaWebContent/WEB-INF/views.

4. NapáginaJSP,adicioneumcabeçalho(<head></head>)comolinkparaoarquivoCSS.Adicioneocabeçalhoentredatag<html>e<body>:

<head><linktype="text/css"href="resources/css/tarefas.css"rel="stylesheet"/></head>

AtravésdolinkdefinimosocaminhoparaoarquivoCSS.

Cuidado:Napáginadeveexistirapenasumcabeçalho(<head></head>).

5. ReinicieoTomcatechamaapáginadelogin:

http://localhost:8080/fj21-tarefas/loginForm

Apáginajádeveaparecercomumvisualnovo.

6. Aplique o mesmo arquivo CSS em todas as outras páginas. Tenha cuidado para não repetir ocabeçalho,algumaspáginasjápossuematag<head>,outrasnão.

Verifiqueoresultadonaaplicação.

13.7EXERCÍCIOSOPCIONAIS:APLICANDOCSSNASPÁGINAS

.

Page 211: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,

Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex-aluno daCaelumtem15%dedescontonestelink!

ConheçaoscursosonlineAlura.

Geralmente,aodesenvolvermosumaaplicaçãoWeb,possuímosumambientededesenvolvimentocomumservidorqueestáemnossasmáquinas locais.Depoisqueodesenvolvimentoestáfinalizadoenossa aplicação está pronta para ir ao ar, precisamos enviá-la para um ambiente que costumamoschamar de ambiente de produção. Esse processo de disponibilizarmos nosso projeto em umdeterminadoambienteéoquechamamosdedeploy(implantação).

Oservidordeproduçãoéolocalnoqualoprojetoestaráhospedadoesetornaráacessívelparaosusuáriosfinais.

Mascomofazemosparaenviarnossoprojetoqueestáemnossasmáquinaslocaisparaumservidorexterno?

OprocessopadrãodedeploydeumaaplicaçãowebemJavaéodecriarumarquivocomextensão.war,quenadamaiséqueumarquivozipcomodiretóriobasedaaplicaçãosendoaraizdozip.

Nonosso exemplo, todo o conteúdo do diretórioWebContent pode ser incluído emum arquivotarefas.war.Apóscompactarodiretório,efetuaremosodeploy.

JáconheceoscursosonlineAlura?

13.8DEPLOYDOPROJETOEMOUTROSAMBIENTES

.

Page 212: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

NoTomcat,bastacopiaroarquivo.warnodiretórioTOMCAT/webapps/.Eleserádescompactadopelo container e um novo contexto chamado tarefas estará disponível. Repare que o novo contextogeradopeloTomcatadotaomesmonomequeoseuarquivo.war,ouseja,nossoarquivochamava-setarefas.wareocontextosechamatarefas.

Ao colocarmos owar no Tomcat, podemos acessar nossa aplicação pelo navegador através doendereço:http://localhost:8080/tarefas/loginForm

1. Vamospraticarcriandoumwareutilizando-o,mas,antesdecomeçarmos,certifique-sedequeoTomcatestejanoar.

CliquecomobotãodireitonoprojetoeváemExport->WARfile

CliquenobotãoBrowseeescolhaapastadoseuusuárioeonometarefas.war.

13.9EXERCÍCIOS:DEPLOYCOMWAR

.

Page 213: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CliqueemFinish

Pronto,nossowarestácriado!

2. Vamosinstalarnossowar!

AbraoFileBrowser

Cliquedadireitanoarquivotarefas.wareescolhaCut(Recortar).

Váparaodiretórioapache-tomcat,webapps.Certifique-sedequeseuTomcatestejarodando.

Coleoseuarquivoaqui:(Edit->Paste).Reparequeodiretóriotarefasfoicriado.

.

Page 214: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

PodemosacessaroprojetoatravésdaURL:http://localhost:8080/tarefas/loginForm

Querendoaprenderaindamaissobre?Esclarecerdúvidasdosexercícios?Ouvirexplicaçõesdetalhadascomuminstrutor?ACaelum oferece o cursoFJ-21 presencial nas cidades de São Paulo, Rio deJaneiroeBrasília,alémdeturmasincompany.

ConsulteasvantagensdocursoJavaparaDesenvolvimentoWeb

13.10DISCUSSÃOEMAULA:LIDANDOCOMDIFERENTESNOMESDECONTEXTO

VocêpodetambémfazerocursoFJ-21dessaapostilanaCaelum

.

Page 215: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO14

"É uma experiência eterna de que todos os homens com poder são tentados a abusar." -- Baron deMontesquieu

Nestecapítulo,vocêaprenderáa:

EntenderadiferençaentreaJPAeoHibernate;UsaraferramentadeORMJPAcomHibernate;Gerarastabelasemumbancodedadosqualquerapartirdesuasclassesdemodelo;InserirecarregarobjetospeloJPAnobanco;BuscarváriosobjetospeloJPA;

Com a popularização do Java em ambientes corporativos, logo se percebeu que grande parte dotempo do desenvolvedor era gasto na codificação de queries SQL e no respectivo código JDBCresponsávelportrabalharcomelas.

Alémdeumproblemadeprodutividade,algumasoutraspreocupaçõesaparecem:SQLque,apesarde ter umpadrãoANSI, apresenta diferenças significativas dependendodo fabricante.Não é simplestrocarumbancodedadospelooutro.

Háainda amudançadoparadigma.Aprogramaçãoorientada aobjetosdiferemuitodo esquemaentidade relacional e precisamos pensar das duas maneiras para fazer um único sistema. Pararepresentarmosasinformaçõesnobanco,utilizamostabelasecolunas.Astabelasgeralmentepossuemchave primária (PK) e podem ser relacionadas por meio da criação de chaves estrangeiras (FK) emoutrastabelas.

Quando trabalhamos com uma aplicação Java, seguimos o paradigma orientado a objetos, onderepresentamos nossas informações por meio de classes e atributos. Além disso, podemos utilizartambémherança,composiçãopararelacionaratributos,polimorfismo,enumerações,entreoutros.Esseburaco entre esses dois paradigmas gera bastante trabalho: a todo momento devemos "transformar"objetosemregistroseregistrosemobjetos.

UMAINTRODUÇÃOPRÁTICAAOJPACOMHIBERNATE

14.1MAPEAMENTOOBJETORELACIONAL

.

Page 216: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Querendoaprenderaindamaissobre?Esclarecerdúvidasdosexercícios?Ouvirexplicaçõesdetalhadascomuminstrutor?ACaelum oferece o cursoFJ-21 presencial nas cidades de São Paulo, Rio deJaneiroeBrasília,alémdeturmasincompany.

ConsulteasvantagensdocursoJavaparaDesenvolvimentoWeb

Ferramentas para auxiliar nesta tarefa tornaram-se populares entre os desenvolvedores Java e sãoconhecidas como ferramentas de mapeamento objeto-relacional (ORM). O Hibernate é umaferramenta ORM open source e é a líder de mercado, sendo a inspiração para a especificação JavaPersistenceAPI(JPA).OHibernatenasceusemJPAmashojeemdiaécomumacessaroHibernatepelaespecificaçãoJPA.Comotodaespecificação,eladevepossuirimplementações.Entreasimplementaçõesmaiscomuns,podemoscitar:HibernatedaRedHat,EclipseLinkdaEclipseFoundationeoOpenJPAdaApache.ApesardoHibernateteroriginadoaJPA,oEclipseLinkéaimplementaçãoreferencial.

OHibernate abstrai o seu código SQL, toda a camada JDBC e o SQL será gerado em tempo deexecução.Maisqueisso,elevaigeraroSQLqueserveparaumdeterminadobancodedados,jáquecadabancofalaum"dialeto"diferentedessalinguagem.AssimhátambémapossibilidadedetrocardebancodedadossemterdealterarcódigoJava,jáqueissoficacomoresponsabilidadedaferramenta.

Comousaremos JPAabstraímosmais ainda,podemosdesenvolver semconhecerdetalhes sobreoHibernateeatétrocaroHibernatecomumaoutraimplementaçãocomoOpenJPA:

VamosusaroJPAcomHibernate,ouseja,precisamosbaixarosJARsnositedoHibernate.Ositeoficial do Hibernate é o www.hibernate.org, onde você baixa a última versão na seção ORM eDownload.

ComoZIPbaixadoemmãos,vamosdescompactaroarquivo.DessapastavamosusartodososJARsobrigatórios(required).NãopodemosesqueceroJARdaespecificaçãoJPAqueseencontranapastajpa.

ParausaroHibernateeJPAnoseuprojetoénecessáriocolocartodosessesJARsnoclasspath.

VocêpodetambémfazerocursoFJ-21dessaapostilanaCaelum

14.2JAVAPERSISTENCEAPIEFRAMEWORKSORM

14.3BIBLIOTECASDOHIBERNATEEJPA

.

Page 217: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

OHibernate vai gerar o código SQL para qualquer banco de dados. Continuaremos utilizando obancoMySQL,portantotambémprecisamosoarquivo.jarcorrespondenteaodriverJDBC.

Paraestecapítulo,continuaremosutilizandoaclassequerepresentaumatarefa:

packagebr.com.caelum.tarefas.modelo;

publicclassTarefa{privateLongid;privateStringdescricao;privatebooleanfinalizado;privateCalendardataFinalizacao;}

Criamososgetters e settersparamanipularoobjeto,mas fique atentoque sódevemosusar essesmétodosserealmentehouvernecessidade.

EssaéumaclassecomoqualqueroutraqueaprendemosaescreveremJava.PrecisamosconfiguraroHibernateparaqueelesaibadaexistênciadessaclassee,destaforma,saibaquedeveinserirumalinhanatabelaTarefatodavezqueforrequisitadoqueumobjetodessetiposejasalvo.Emvezdeusarmosotermo"configurar",falamosemmapearumaclasseatabela.

Para mapear a classe Tarefa , basta adicionar algumas poucas anotações em nosso código.Anotação éumrecursodo Javaquepermite inserirmetadados em relaçãoanossa classe, atributos emétodos.Essasanotaçõesdepoispoderãoser lidaspor frameworksebibliotecas,paraqueeles tomemdecisõesbaseadasnessaspequenasconfigurações.

Paraessanossaclasseemparticular,precisamosdeapenasquatroanotações:

@EntitypublicclassTarefa{

@Id@GeneratedValueprivateLongid;

privateStringdescricao;privatebooleanfinalizado;

@Temporal(TemporalType.DATE)privateCalendardataFinalizacao;

//métodos...}

@Entityindicaqueobjetosdessaclassesetornem"persistível"nobancodedados.@Idindicaqueo atributo id é nossa chave primária (você precisa ter uma chave primária em toda entidade) e@GeneratedValuedizquequeremosqueestachavesejapopuladapelobanco(istoé,quesejausado

14.4 MAPEANDO UMA CLASSE TAREFA PARA NOSSO BANCO DEDADOS

.

Page 218: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

um auto increment ou sequence , dependendo do banco de dados). Com @TemporalconfiguramoscomomapearumCalendarparaobanco,aquiusamosapenasadata(semhora),maspoderíamos ter usado apenas a hora ( TemporalType.TIME ) ou timestamp(TemporalType.TIMESTAMP).Essasanotaçõesprecisamdosdevidosimports,epertencemaopacotejavax.persistence.

Masemquetabelaessaclasseserágravada?Emquaiscolunas?Quetipodecoluna?Naausênciadeconfiguraçõesmaisespecíficas,oHibernatevaiusarconvenções:aclasseTarefaserágravadanatabeladenometambémTarefa,eoatributodescricaoemumacolunadenomedescricaotambém!

Se quisermos configurações diferentes das convenções, basta usarmos outras anotações, que sãocompletamente opcionais. Por exemplo, para mapear o atributo dataFinalizacao numa colunachamadadata_finalizadofaríamos:

@Column(name="data_finalizado",nullable=true)privateCalendardataFinalizacao;

Parausarumatabelacomonometarefas:

@Entity@Table(name="tarefas")publicclassTarefa{

Reparequenasentidadeshátodasasinformaçõessobreastabelas.Baseadonelaspodemosatépedirgerarastabelasnobanco,masparaissoéprecisoconfiguraroJPA.

Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.

CasadoCódigo,LivrosdeTecnologia.

EmqualbancodedadosvamosgravarnossasTarefass?Qualéo login?Qualéasenha?OJPAnecessitadessasconfigurações,eparaissocriaremosoarquivopersistence.xml.

Seuslivrosdetecnologiaparecemdoséculopassado?

14.5CONFIGURANDOOJPACOMASPROPRIEDADESDOBANCO

.

Page 219: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

AlgunsdadosquevãonessearquivosãoespecíficosdoHibernateepodemserbemavançados,sobrecontroledecache,transações,connectionpooletc,tópicosquesãoabordadosnocursoFJ-25.

Paranosso sistema,precisamosdequatro linhas comconfiguraçõesque já conhecemosdo JDBC:string de conexão com o banco, o driver, o usuário e senha. Além dessas quatro configurações,precisamosdizerqualdialetodeSQLdeveráserusadonomomentoqueasqueriessãogeradas;nonossocaso,MySQL.VamostambémmostraroSQLnoconsoleparaacompanharotrabalhodoHibernate.

Vamostambémconfiguraracriaçãodastabelasbaseadonasentidades.

Segueumaconfiguraçãocompletaquedefineumaunidadedepersistência(persistence-unit)comonometarefas,seguidospeladefiniçãodoprovedor,entidadeseproperties:

<persistencexmlns="http://java.sun.com/xml/ns/persistence"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/persistencehttp://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"version="2.0">

<persistence-unitname="tarefas">

<!--provedor/implementacaodoJPA--><provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

<!--entidademapeada--><class>br.com.caelum.tarefas.modelo.Tarefa</class>

<properties><!--dadosdaconexao--><propertyname="javax.persistence.jdbc.driver"value="com.mysql.jdbc.Driver"/><propertyname="javax.persistence.jdbc.url"value="jdbc:mysql://localhost/fj21"/><propertyname="javax.persistence.jdbc.user"value="root"/><propertyname="javax.persistence.jdbc.password"value="<SENHADOBANCOAQUI>"/>

<!--propriedadesdohibernate--><propertyname="hibernate.dialect"value="org.hibernate.dialect.MySQL5InnoDBDialect"/><propertyname="hibernate.show_sql"value="true"/><propertyname="hibernate.format_sql"value="true"/>

<!--atualizaobanco,geraastabelasseforpreciso--><propertyname="hibernate.hbm2ddl.auto"value="update"/>

</properties></persistence-unit></persistence>

É importante saber que o arquivo persistence.xml deve ficar na pasta META-INF do seuclasspath.

14.6USANDOOJPA

.

Page 220: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

ParausaroJPAnonossocódigoJava,precisamosutilizarsuaAPI.Elaébastantesimplesediretaerapidamentevocêestaráhabituadocomsuasprincipaisclasses.

Nosso primeiro passo é fazer com que o JPA leia a nossa configuração: tanto o nosso arquivopersistence.xmlquantoasanotaçõesquecolocamosnanossaentidadeTarefa.Paratal,usaremosaclassecomomesmonomedoarquivoXML:Persistence.ElaéresponsáveldecarregaroXMLeinicializarasconfigurações.ResultadodessaconfiguraçãoéumaEntityManagerFactory:

EntityManagerFactoryfactory=Persistence.createEntityManagerFactory("tarefas");

Estamosprontos para usar o JPA.Antes de gravar umaTarefa, precisamos que exista a tabelacorrespondentenonossobancodedados.Emvezdecriarmososcriptquedefineoschema(ouDDLdeum banco, data definition language) do nosso banco (os famosos CREATE TABLE ....) podemosdeixar isto a cargo do próprioHibernate. Ao inicializar a EntityManagerFactory também já serágeradaumatabelaTarefas pois configuramosqueobancodeve ser atualizadapelapropriedadedoHibernate:hbm2ddl.auto.

Caso você esteja fazendo esse passo de casa. É preciso baixar o ZIP do Hibernate ORM 4.x(http://hibernate.org),extraí-lo,ecopiartodososJARsdaspastaslib/requiredelib/jpa.

Paraessaaplicaçãousaremosasseguintesversões:

antlr-2.7.7.jardom4j-1.6.1.jarhibernate-commons-annotations-4.0.4.Final.jarhibernate-core-4.3.0.Final.jarhibernate-entitymanager-4.3.0.Final.jarhibernate-jpa-2.1-api-1.0.0.Final.jarjandex-1.1.0.Final.jarjavassist-3.18.1-GA.jarjboss-logging-3.1.3.GA.jarjboss-logging-annotations-1.2.0.Beta1.jarjboss-transaction-api_1.2_spec-1.0.0.Final.jar

14.7PARASABERMAIS:CONFIGURANDOOJPACOMHIBERNATEEMCASA

.

Page 221: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende

Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!

ConheçaaAluraCursosOnline.

1. Vamosprepararnossoprojetofj21-tarefascomasdependênciasdoHibernate.

CopieosJARsdoHibernateparaapastaWebContent/WEB-INF/libdoseuprojetodessaforma:

Váaodiretório21/jars-jpa/hibernate;

SelecionetodososJARs,cliquecomobotãodireitoeescolhaCopy(ouCTRL+C);

ColetodososJARsnapastaWebContent/WEB-INF/libdoprojetofj21-tarefas(CTRL+V)

2. AnoteaclasseTarefacomoumaentidadedebancodedados.Lembre-sequeessaéumaanotaçãodopacotejavax.persistence.

Obs:Nãoapaguenenhumaanotação,apenasadicioneasanotaçõesdoJPA.

@EntitypublicclassTarefa{

}

Namesmaclasseanoteseuatributoidcomochaveprimáriaecomocampodegeraçãoautomática:

@Id@GeneratedValueprivateLongid;

Agora é precisomapear o atributodataFinalizacao para gravar apenas a data (sem hora) nobanco:

@Temporal(TemporalType.DATE)privateCalendardataFinalizacao;

3.

Agoraéamelhorhoradeaprenderalgonovo

14.8EXERCÍCIOS:CONFIGURANDOOJPAEGERANDOOSCHEMADOBANCO

.

Page 222: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Cliquecomobotãodireitonapastasrcdoprojetodofj21-tarefaseescolhaNew->Folder.EscolhaMETA-INFcomonomedessapasta.

Váaodiretóriocaelum/21/jars-jpaecopieoarquivopersistence.xmlparaapastaMETA-INF.

O arquivo é apenas um esboço, falta configurar a unidade de persistência com o provedor,entidadesepropriedades.Adicionedentrodoelementopersistence:

<persistence-unitname="tarefas">

<provider>org.hibernate.ejb.HibernatePersistence</provider><class>br.com.caelum.tarefas.modelo.Tarefa</class>

<properties><propertyname="javax.persistence.jdbc.driver"value="com.mysql.jdbc.Driver"/><propertyname="javax.persistence.jdbc.url"value="jdbc:mysql://localhost/fj21"/><propertyname="javax.persistence.jdbc.user"value="root"/><propertyname="javax.persistence.jdbc.password"value="<SENHADOBANCOAQUI>"/>

<propertyname="hibernate.dialect"value="org.hibernate.dialect.MySQL5InnoDBDialect"/><propertyname="hibernate.show_sql"value="true"/><propertyname="hibernate.format_sql"value="true"/>

.

Page 223: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

<propertyname="hibernate.hbm2ddl.auto"value="update"/></properties></persistence-unit>

Asduaspropriedadesshow_sqleformat_sqlfazemcomquetodoSQLgeradopeloHibernateapareçanoconsole.

4. CrieaclasseGeraTabelasnopacotebr.com.caelum.tarefas.jpa.

packagebr.com.caelum.tarefas.jpa;

//importsomitidos

publicclassGeraTabelas{

publicstaticvoidmain(String[]args){EntityManagerFactoryfactory=Persistence.createEntityManagerFactory("tarefas");

factory.close();}}

5. CriesuatabelaexecutandoaclasseGeraTabelas.Paraisso,cliquedadireitanocódigoeváemRunAs->JavaApplication.

NãoéprecisorodaroTomcatparaesseexercício.

6. Agora,abraumanovaabanoTerminaledigitemysql-uroot-p,usandoasenhacorreta,sehouver.Após isto, digiteuse fj21; e em seguida, show tables;. Se seu banco de dados já existia, e não foiprecisocriá-lonopassoanterior,vocêvainotarapresençadeuma tabela chamada tarefas.Não éestaatabelaquequeremos.ProcuramospelatabelaTarefa,comT,emmaiúsculo(igualaonomedaclasseTarefa).

7. (opcional)Casoalgumerrotenhaocorrido,épossívelqueoHibernatetenhalogadoumamensagem,mas vocênão a viu dado que o Log4J não está configurado.Mesmo que tudo tenha ocorrido demaneiracorreta,émuitoimportanteteroLog4Jconfigurado.

Paraisso,adicionenoarquivolog4j.propertiesdentrodapastasrc paraque todoo logdonívelinfoouacimasejaenviadoparaoconsoleappenderdoSystem.out(defaultdoconsole):

log4j.logger.org.hibernate=info

.

Page 224: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

ParasecomunicarcomoJPA,precisamosdeumainstânciadeumobjetodotipoEntityManager.AdquirimosumaEntityManageratravésdafábricajáconhecida:EntityManagerFactory.

EntityManagerFactoryfactory=Persistence.createEntityManagerFactory("tarefas");

EntityManagermanager=factory.createEntityManager();

manager.close();factory.close();

AtravésdeumobjetodotipoEntityManager,épossívelgravarnovosobjetosnobanco.Paraisto,bastautilizarométodopersistdentrodeumatransação:

Tarefatarefa=newTarefa();tarefa.setDescricao("EstudarJPA");tarefa.setFinalizado(true);tarefa.setDataFinalizacao(Calendar.getInstance());

EntityManagerFactoryfactory=Persistence.createEntityManagerFactory("tarefas");EntityManagermanager=factory.createEntityManager();

manager.getTransaction().begin();manager.persist(tarefa);manager.getTransaction().commit();

System.out.println("IDdatarefa:"+tarefa.getId());

manager.close();

CUIDADOSAOUSAROJPA

AousaroJPAprofissionalmente,fiqueatentocomalgunscuidadosquesãosimples,masnãodada a devida atenção podem gerar gargalos de performance. Abrir EntityManager sindiscriminadamenteéumdessesproblemas.EssepostdaCaelumindicaoutros:

http://bit.ly/bRc5g

EssesdetalhesdodiaadiaassimcomoJPAcomHibernateavançadosãovistosnocursoFJ-25daCaelum,deHibernateeJPAavançados.

Parabuscarumobjetodadasuachaveprimária,nocasoo seuid, utilizamosométodofind,conformeoexemploaseguir:

EntityManagerFactoryfactory=Persistence.createEntityManagerFactory("tarefas");

14.9TRABALHANDOCOMOSOBJETOS:OENTITYMANAGER

Persistindonovosobjetos

Carregarumobjeto

.

Page 225: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

EntityManagermanager=factory.createEntityManager();

Tarefaencontrada=manager.find(Tarefa.class,1L);

System.out.println(encontrada.getDescricao());

1. CrieumaclassechamadaAdicionaTarefanopacotebr.com.caelum.tarefas.jpa,elavaicriarumobjetoeadicioná-loaobanco:

packagebr.com.caelum.tarefas.jpa;

//importsomitidos

publicclassAdicionaTarefa{

publicstaticvoidmain(String[]args){

Tarefatarefa=newTarefa();tarefa.setDescricao("EstudarJPAeHibernate");tarefa.setFinalizado(true);tarefa.setDataFinalizacao(Calendar.getInstance());

EntityManagerFactoryfactory=Persistence.createEntityManagerFactory("tarefas");EntityManagermanager=factory.createEntityManager();

manager.getTransaction().begin();manager.persist(tarefa);manager.getTransaction().commit();

System.out.println("IDdatarefa:"+tarefa.getId());

manager.close();}}

2. RodeaclasseAdicionaTarefaeadicionealgumastarefasnobanco.Saídapossível:

3. Verifiqueosregistrosnobanco,seconectecomoclientedomysql:

mysql-uroot-pusefj21;select*fromTarefa;

Usandoasenhacorreta,sehouver.RodenovamenteaclasseAdicionaTarefaeverifiqueobanco.

4. Vamoscarregartarefaspelachaveprimária.

14.10EXERCÍCIOS:GRAVANDOECARREGANDOOBJETOS

.

Page 226: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CrieumaclassechamadaCarregaTarefanopacotebr.com.caelum.tarefas.jpa:

packagebr.com.caelum.tarefas.jpa;

//importsomitidos

publicclassCarregaTarefa{

publicstaticvoidmain(String[]args){

EntityManagerFactoryfactory=Persistence.createEntityManagerFactory("tarefas");EntityManagermanager=factory.createEntityManager();

Tarefaencontrada=manager.find(Tarefa.class,1L);System.out.println(encontrada.getDescricao());

manager.close();}}

5. RodeaclasseCarregaTarefaeverifiqueasaída.

Casorecebeuumaexception,verifiqueoiddatarefa.Eledeveexistirnobanco.

Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.

CasadoCódigo,ebookcompreçodeebook.

EditoraCasadoCódigocomlivrosdeumaformadiferente

14.11REMOVENDOEATUALIZANDOOBJETO

.

Page 227: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Remover e atualizar os objetos com JPA também é muito simples. O EntityManager possuimétodosparacadaoperação.Pararemoveréprecisocarregaraentidadeantesedepoisusarométodoremove:

EntityManagermanager=//abrirumEntityManagerTarefaencontrada=manager.find(Tarefa.class,1L);

manager.getTransaction().begin();manager.remove(encontrada);manager.getTransaction().commit();

Paraatualizarumentidadequejápossuiumidexisteométodomerge,porexemplo:

Tarefatarefa=newTarefa();tarefa.setId(2);//esseidjáexistenobancotarefa.setDescricao("EstudarJPAeHibernate");tarefa.setFinalizado(false);tarefa.setDataFinalizacao(null);

EntityManagermanager=//abrirumEntityManager

manager.getTransaction().begin();manager.merge(tarefa);manager.getTransaction().commit();

OJPApossuiumalinguagemprópriadequeriesparafacilitarabuscadeobjetoschamadadeJPQL.Ocódigoaseguirmostraumapesquisaqueretornatodasastarefasnãofinalizadas:

EntityManagermanager=//abrirumEntityManagerList<Tarefa>lista=manager.createQuery("selecttfromTarefaastwheret.finalizado=false").getResultList();

for(Tarefatarefa:lista){System.out.println(tarefa.getDescricao());}

Também podemos passar um parâmetro para a pesquisa. Para isso, é preciso trabalhar com umobjetoquerepresentaapesquisa(javax.persistence.Query):

EntityManagermanager=//abrirumEntityManager

Queryquery=manager.createQuery("selecttfromTarefaast"+"wheret.finalizado=:paramFinalizado");query.setParameter("paramFinalizado",false);

List<Tarefa>lista=query.getResultList();

Este é apenas o começo.O JPA émuitopoderoso e, no cursoFJ-25, veremos como fazer queriescomplexas,comjoins,agrupamentos,projeções,demaneiramuitomaissimplesdoquesetivéssemosdeescreverasqueries.Alémdisso,oJPAcomHibernateémuitocustomizável:podemosconfigurá-loparaquegereasqueriesdeacordocomdicasnossas,dessa formaotimizandocasosparticularesemqueas

14.12BUSCANDOCOMUMACLÁUSULAWHERE

.

Page 228: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

queriesqueelegeraporpadrãonãosãodesejáveis.

UmaconfusãoquepodeserfeitaaprimeiravistaépensarqueoJPAcomHibernateélento,pois,eleprecisagerarasnossasqueries,lerobjetosesuasanotaçõeseassimpordiante.Naverdade,oHibernatefazumasériedeotimizaçõesinternamentequefazemcomqueoimpactodessastarefassejapróximoanada.Portanto,oHibernateé,sim,performático,ehojeemdiapodeserutilizadoemqualquerprojetoquesetrabalhacombancodedados.

1. CrieumaclassechamadaBuscaTarefasnopacotebr.com.caelum.tarefas.jpa:

Cuidado,aclasseQueryvemdopacotejavax.persistence:

packagebr.com.caelum.tarefas.jpa;

importjavax.persistence.Query;//outrosimportsomitidos

publicclassBuscaTarefas{

publicstaticvoidmain(String[]args){

EntityManagerFactoryfactory=Persistence.createEntityManagerFactory("tarefas");EntityManagermanager=factory.createEntityManager();

//cuidado,useoimportjavax.persistence.QueryQueryquery=manager.createQuery("selecttfromTarefaast"+"wheret.finalizado=:paramFinalizado");query.setParameter("paramFinalizado",true);

List<Tarefa>lista=query.getResultList();

for(Tarefat:lista){System.out.println(t.getDescricao());}

manager.close();}}

2. RodeaclasseBuscaTarefaseverifiqueasaída.

14.13EXERCÍCIOS:BUSCANDOCOMJPQL

.

Page 229: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,

Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex-aluno daCaelumtem15%dedescontonestelink!

ConheçaoscursosonlineAlura.

JáconheceoscursosonlineAlura?

.

Page 230: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO15

"Anucaéummistérioparaavista."--PaulValéry

O curso FJ-21, Java para desenvolvimento Web, procura abordar as principais tecnologias domercadoWebemJavadesdeseusfundamentosatéosframeworksmaisusados.

Maseagora,paraondedirecionarseusestudosesuacarreira?

Ospróximoscapítulosdaapostilasãoapêndicesextrasparaexpandirseuestudoemalgumasáreasquepodemserdeseuinteresse:

JPAeSpring-MostracomointegrarJPAcomSpringparautilizarJPAnacamadadepersistêncianoprojetofj21-tarefas.

Servlets3.0eJavaEE6-MostraasúltimasnovidadesdoJavaEE6napartedeWeblançadasemdezembrode2009.Éaindaumaversãomuitorecentequeomercadonãoadotaepoucosservidoressuportam.Mas é bom estar atualizado comas próximasnovidades que se tornarão realidadenomercadoempoucotempo.

TópicosdaServletAPI-AbordaváriostópicossobreServletseJSPsquenãoabordamosantes.Sãodetalhesamaisealgunsrecursosmaisavançados.ÉinteressanteparaexpandirseuconhecimentoeajudarentendermelhoropadrãoServlets.

EAGORA?

15.1OSAPÊNDICESDESSAAPOSTILA

.

Page 231: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,

Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex-aluno daCaelumtem15%dedescontonestelink!

ConheçaoscursosonlineAlura.

OmercadodeframeworksJavaéimenso.Hámuitasopçõesboasdisponíveisnomercadoemuitospontosaconsiderarnaadoçãoouestudodealgumnovoframework.

OStrutscomcertezaéoframeworkcommaiorunanimidadenomercado,emespecialporcausadesuaversão1.x.Aversão2.0nãotemtantaforçamaséumdosmaisimportantes.

OVRaptor,criadonaUSPem2004emantidohojepelaCaelumeporumagrandecomunidade,nãotem o tamanho do mercado de outros grandes frameworks. Mas tem a vantagem da extremasimplicidadeegrandeprodutividade,alémdeserbemfocadonomercadobrasileiro,comdocumentaçãoemportuguêsemuitomaterialdisponível.ACaeluminclusivedisponibilizaumcursodeVRaptor,oFJ-28quepossuisuaapostiladisponívelparadownloadgratuitonaInternetem:

http://www.caelum.com.br/apostilas

Um dos frameworks mais usados hoje é o JavaServer Faces - JSF. Seu grande apelo é ser oframeworkoficialdoJavaEEparaWeb,enquantoquetodososoutrossãodeterceiros.OJSFtemaindamuitascaracterísticasdiferentesdoStrutsoudoVRaptorquevimosnessecurso.

Emespecial,oJSFéditoumframeworkcomponent-based,enquantoqueStruts(1e2)eVRaptorsãoditos request-based ou action-based. A ideia principal de um framework de componentes é abstrairmuitosdosconceitosdaWebedoprotocoloHTTPprovendoumaformadeprogramaçãomaisparecidacomprogramaçãoparaDesktop.OJSFtemcomponentesvisuaisricos jáprontos, funcionaatravésdetratamentodeeventoseéstateful(aocontráriodaWeb"normal"ondetudoéstateless).NaCaelum,ocursoFJ-26tratadeJavaServerFaces:

http://www.caelum.com.br/curso/fj26

JáconheceoscursosonlineAlura?

15.2FRAMEWORKSWEB

.

Page 232: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Mas o JSF não é único framework baseado em componentes.Há outras opções (menos famosas)comooGoogleWebToolkit -GWT ouoApacheWicket.Damesma forma,háoutros frameworksrequest-based além de Struts e VRaptor, como o Stripes ou oSpringMVC. Na Caelum, o Spring eSpringMVCétratadoemdetalhesnocursoFJ-27,juntocomoutrasfuncionalidadesdoSpring:

http://www.caelum.com.br/curso/fj27

Todaessapluralidadedeframeworkséboaparafomentarcompetiçãoeinovaçãonomercado,maspodeconfundirmuitooprogramadorqueestá iniciandonessemeio.Umbomcaminhoaseguirapósesse curso FJ-21 é continuar aprofundando seus conhecimentos no SpringMVC e noVRaptor (comajudada apostila aberta) epartirdepoisparao estudodo JSF.Osoutros frameworksvocêvai acabareventualmente encontrando algum dia em sua carreira,mas não se preocupe em aprender todos nocomeço.

Quando falamos de frameworks voltados para persistência e bancos de dados, felizmente, não hátanta dúvida quanto nomundo dos frameworksWeb.OHibernate é praticamente unanimidade nomercadoJava,principalmenteseusadocomoimplementaçãodaJPA.Háoutraspossibilidades,comooToplink, o EclipseLink, o OpenJPA, o DataNucleus, o JDO, o iBatis etc. Mas o Hibernate é o maisimportante.

NaCaelum,abordamosJPAeHibernateavançadonocursoFJ-25:

http://www.caelum.com.br/curso/fj25

HáaindalivrosedocumentaçõesdisponíveissobreHibernate.RecomendamosfortementequevocêaprofundeseusestudosnoHibernatequeémuitousadoepedidonomercadoJavahoje.

ACaelumdisponibilizaparadownloadgratuito algumasdas apostilasde seus treinamentos.Vocêpodebaixardiretonosite:

http://www.caelum.com.br/apostilas

OBlogdaCaeluméaindaoutraformadeacompanharnovidadeseexpandirseusconhecimentos:

http://blog.caelum.com.br

Diversasrevistas,noBrasilenoexterior,estudamomundoJavacomoninguémepodemajudaroinicianteaconhecermuitodoqueestáacontecendoláforanasaplicaçõescomerciais.

LembrandoqueaeditoraCasadoCódigopossuilivrosdeJSFeJPAquepodemteauxiliartambém

15.3FRAMEWORKSDEPERSISTÊNCIA

15.4ONDESEGUIRSEUSESTUDOS

.

Page 233: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

nacontinuaçãoereforçodosseusestudos:

http://www.CasaDoCodigo.com.br

Querendoaprenderaindamaissobre?Esclarecerdúvidasdosexercícios?Ouvirexplicaçõesdetalhadascomuminstrutor?ACaelum oferece o cursoFJ-21 presencial nas cidades de São Paulo, Rio deJaneiroeBrasília,alémdeturmasincompany.

ConsulteasvantagensdocursoJavaparaDesenvolvimentoWeb

VocêpodetambémfazerocursoFJ-21dessaapostilanaCaelum

.

Page 234: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO16

"Ocaminhodoinfernoestápavimentadodeboasintenções."--Marx

Nestecapítulo,vocêaprenderáa:

IntegrarJPAcomSpring;InjetaroEntityManagerdentrodoDAO;GerenciarastransaçõescomSpring;

DentreasdiversascaracterísticasdoSpringumadasquemaischamaaatençãoéaintegraçãonativacomdiversastecnologiasimportantesdomercado.PodemoscitaroHibernateeoJPA.

VimosqueoSpringéumcontainerquecontrolaobjetos(oucomponentes),administrandoociclodavidadeles,inclusiveligandounsaosoutros(amarrando-os).NocasodoJPA,queremosqueoSpringcuidedaaberturaedofechamentodaEntityManagerFactoryedoEntityManager.Comisso,todosos componentes do Spring podem receber como dependência um EntityManager , mas agoracontroladopeloSpring.Novamenteaplicandoainversãodecontrole.

Mas a inversão de controle não se limita a inicialização de objetos. O Spring também tira dodesenvolvedoraresponsabilidadedecontrolaratransação.AodelegarocontroledoEntityManagerparaoSpring,eleconsegueabrirefechartransaçõesautomaticamente.

VejacomoéainicializaçãodoJPAsemaajudadoSpring:

EntityManagerFactoryfactory=Persistence.createEntityManagerFactory("tarefas");EntityManagermanager=factory.createEntityManager();

manager.getTransaction().begin();

//aquiusaoEntityManager

manager.getTransaction().commit();manager.close();

NessepequenotrechodecódigopodemosvercomoétrabalhosoinicializaroJPAmanualmente.Éprecisoabrir e fechar todosos recursospara realmentecomeçarausaroEntityManager.OSpring

APÊNDICE-INTEGRAÇÃODOSPRINGCOMJPA

16.1GERENCIANDOOENTITYMANAGER

.

Page 235: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

deveassumiressasresponsabilidadesefacilitarassimousodoJPA.

AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,

Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex-aluno daCaelumtem15%dedescontonestelink!

ConheçaoscursosonlineAlura.

Paraintegrar-secomoJPA,oSpringdisponibilizaumBeanquedevemoscadastrarnoarquivoXML.ElerepresentaaEntityManagerFactory,masagoragerenciadapeloSpring.Ouseja,todainicializaçãodafábricaficaaoencargodoSpring:

<beanid="entityManagerFactory"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><propertyname="dataSource"ref="mysqlDataSource"/><propertyname="jpaVendorAdapter"><beanclass="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/></property></bean>

ReparequeoBeandefineHibernatecomoimplementaçãodoJPAerecebeamysqlDataSourcequejádefinimosanteriormentedentrodoXMLdoSpring.ComoanossaDatasourcejásabeosdadosdodriver,loginesenha,oarquivopersistence.xmldoJPAtambémficamaissimples:

<persistencexmlns="http://java.sun.com/xml/ns/persistence"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/persistencehttp://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"version="2.0">

<persistence-unitname="tarefas">

<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

<class>br.com.caelum.tarefas.modelo.Tarefa</class>

<properties>

<!--SEMaspropriedadesURL,login,senhaedriver-->

JáconheceoscursosonlineAlura?

16.2CONFIGURANDOOJPANOSPRING

.

Page 236: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

<propertyname="hibernate.dialect"value="org.hibernate.dialect.MySQL5InnoDBDialect"/><propertyname="hibernate.show_sql"value="true"/><propertyname="hibernate.format_sql"value="true"/><propertyname="hibernate.hbm2ddl.auto"value="update"/></properties></persistence-unit>

</persistence>

Com JPA configurado podemos aproveitar a inversão de controle e injetar o EntityManagerdentrodequalquercomponenteadministradopeloSpring.

Vamos criaruma classeJpaTarefaDao parausar oEntityManager.A classeJpaTarefaDaoprecisadoEntityManager.ComoJPAéumaespecificação,oSpringtambémaproveitaumaanotaçãodeespecificaçãoparareceberadependência.Nessecasonãopodemosusaraanotação@AutowireddoSpringesim@PersistenceContext. Infelizmenteaanotação@PersistenceContext não funcionacom construtores, exigindo um outro ponto de injeção. Usaremos o atributo para declarar adependência:

@RepositorypublicclassJpaTarefaDao{

@PersistenceContextprivateEntityManagermanager;

//semconstrutor

//aquivemosmétodos}

Nos métodos do JpaTarefaDao faremos o uso do EntityManager usando os métodos jáconhecidoscomopersist(..)parapersistirumatarefaouremove(..)pararemover:

@RepositorypublicclassJpaTarefaDao{

@PersistenceContextprivateEntityManagermanager;

//semconstrutor

publicvoidadiciona(Tarefatarefa){manager.persist(tarefa);}

publicvoidaltera(Tarefatarefa){manager.merge(tarefa);}

publicList<Tarefa>lista(){returnmanager.createQuery("selecttfromTarefat").getResultList();}

16.3INJETANDOOENTITYMANAGER

.

Page 237: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

publicTarefabuscaPorId(Longid){returnmanager.find(Tarefa.class,id);}

publicvoidremove(Tarefatarefa){TarefatarefaARemover=buscaPorId(tarefa.getId());manager.remove(tarefaARemover);}

publicvoidfinaliza(Longid){Tarefatarefa=buscaPorId(id);tarefa.setFinalizado(true);tarefa.setDataFinalizacao(Calendar.getInstance());manager.merge(tarefa);}}

A implementação do JpaTarefaDao ficou muito mais simples se comparada com oJdbcTarefaDao,emalgunsmétodoséapenasumalinhadecódigo.

VoltandoparanossaclasseTarefasControllervamoslembrarqueinjetamosoJdbcTarefaDaoparatrabalharcomobancodedados:

@ControllerpublicclassTarefasController{

privatefinalJdbcTarefaDaodao;

@AutowiredpublicTarefasController(JdbcTarefaDaodao){this.dao=dao;}

@RequestMapping("mostraTarefa")publicStringmostra(Longid,Modelmodel){model.addAttribute("tarefa",dao.buscaPorId(id));return"tarefa/mostra";}

//outrosmétodosomitidos}

Quandoolhamosparaosmétodospropriamenteditos,porexemplo,mostra, percebemosqueoqueé realmentenecessárioparaexecutá-loéalgumDAO.A lógica emsi é independenteda instânciaespecíficaqueestamosinstanciando,ousejaparaaclasseTarefasControllernãoimportaseestamosusandoJDBCouJPA.QueremosumdesacoplamentodaimplementaçãodoDAOespecifico,ealgodevedecidirqualimplementaçãousaremosporbaixodospanos.

Oproblemadesse tipodechamadaéque,nodiaemqueprecisarmosmudara implementaçãodoDAO,precisaremosmudarnossaclasse.Agoraimaginequetenhamos10controladoresnosistemaqueusem nosso JdbcTarefaDao. Se todas usam a implementação específica, quando formos mudar a

16.4BAIXOACOPLAMENTOPELOUSODEINTERFACE

.

Page 238: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

implementaçãoparausar JPAparapersistênciaporexemplo,digamos,JpaTarefaDao, precisaremosmudaremvárioslugares.

OqueprecisamosentãoéapenasumaTarefaDaodentrodaclasseTarefasController, entãovamosdefinir(extrair)umanovainterfaceTarefaDao:

publicinterfaceTarefaDao{

TarefabuscaPorId(Longid);List<Tarefa>lista();voidadiciona(Tarefat);voidaltera(Tarefat);voidremove(Tarefat);voidfinaliza(Longid);}

EaclasseJdbcTarefaDaoimplementaráessainterface:

@RepositorypublicclassJdbcTarefaDaoimplementsTarefaDao{

//implementaçãodonossodaousandojdbc}

Dessa maneira vamos injetar uma implementação compatível com a interface dentro da classeTarefasController

@ControllerpublicclassTarefasController{

privateTarefaDaodao;//usandoainterfaceapenas!

@AutowiredpublicTarefasController(TarefaDaodao){this.dao=dao;}

//métodosomitidos}

Agora a vantagem dessa abordagem é que podemos usar uma outra implementação da interfaceTarefaDaosemalteraraclasseTarefasController,nonossocasovamosusarJpaTarefaDao:

@RepositorypublicclassJpaTarefaDaoimplementsTarefaDao{

@PersistenceContextEntityManagermanager;

//semconstrutor

//métodosomitidos}

Repare que o DAO também vai implementar a interface TarefaDao . Assim temos duasimplementaçõesdamesmainterface:

.

Page 239: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Como o Spring não sabe qual das duas implementações deve ser utilizada é preciso qualificar adependência:

@ControllerpublicclassTarefasController{

privateTarefaDaodao;//usaapenasainterface!

@Autowired@Qualifier("jpaTarefaDao")publicTarefasController(TarefaDaodao){this.dao=dao;}

//métodosomitidos}

DessamaneiraoSpringinjetaráoJpaTarefaDao.

Querendoaprenderaindamaissobre?Esclarecerdúvidasdosexercícios?Ouvirexplicaçõesdetalhadascomuminstrutor?ACaelum oferece o cursoFJ-21 presencial nas cidades de São Paulo, Rio deJaneiroeBrasília,alémdeturmasincompany.

ConsulteasvantagensdocursoJavaparaDesenvolvimentoWeb

Parao suporteà transação serativadoprecisamos fazerduasconfiguraçõesnoXMLdoSpring.Aprimeiraéhabilitarogerenciadordetransação(TransactionManager).Porém,comooSpringpodecontrolar JPA, Hibernate e outros, devemos configurar o gerenciador exatamente para uma dessastecnologias. No caso do JPA, a única dependência que o JpaTransactionManager precisa é umaentityManagerFactory:

<beanid="transactionManager"class="org.springframework.orm.jpa.JpaTransactionManager"><propertyname="entityManagerFactory"ref="entityManagerFactory"/></bean>

VocêpodetambémfazerocursoFJ-21dessaapostilanaCaelum

16.5GERENCIANDOATRANSAÇÃO

.

Page 240: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

entityManagerFactoryéonomedoBeanconfiguradoanteriormente:

Asegundaparteéavisarqueocontroledetransaçõesseráfeitoviaanotação,parecidocomaformadehabilitarousodeanotaçõesparaoSpringMVC.

<tx:annotation-driven/>

Por fim, podemos usar o gerenciamento da transação dentro das nossas classes. Aqui ficamuitosimples,ésóusaraanotação@Transactionalnométodoqueprecisadeumatransação,porexemplonométodoadicionadaclasseTarefasController:

@Transactional@RequestMapping("adicionaTarefa")publicStringadiciona(@ValidTarefatarefa,BindingResultresult){

if(result.hasFieldErrors("descricao")){return"tarefa/formulario";}

dao.adiciona(tarefa);return"redirect:listaTarefas";}

Amesmaanotaçãotambémpodeserutilizadanaclasse.Issosignificaquetodososmétodosdaclasseserãoexecutadosdentrodeumatransação:

@Transactional@ControllerpublicclassTarefasController{

Repareaquiabelezadainversãodecontrole.Nãohánecessidadedechamarbegin(),commit()ourollback(),bastausar@Transactional e o Spring assume a responsabilidade emgerenciar atransação.

Há um problema ainda, usando o gerenciamento de transação pelo Spring exige a presença doconstrutorpadrãosemparâmetros.Vamostrocaraquitambémopontodeinjeçãodoconstrutorparaoatributo.Aclassecompletaficacomo:

packagebr.com.caelum.tarefas.controller;

//imports

@Controller@TransactionalpublicclassTarefasController{

@AutowiredTarefaDaodao;

@RequestMapping("novaTarefa")publicStringform(){return"tarefa/formulario";}

@RequestMapping("adicionaTarefa")publicStringadiciona(@ValidTarefatarefa,BindingResultresult){

.

Page 241: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

if(result.hasFieldErrors("descricao")){return"tarefa/formulario";}

dao.adiciona(tarefa);return"tarefa/adicionada";}

@RequestMapping("listaTarefas")publicStringlista(Modelmodel){model.addAttribute("tarefas",dao.lista());return"tarefa/lista";}

@RequestMapping("removeTarefa")publicStringremove(Tarefatarefa){dao.remove(tarefa);return"redirect:listaTarefas";}

@RequestMapping("mostraTarefa")publicStringmostra(Longid,Modelmodel){model.addAttribute("tarefa",dao.buscaPorId(id));return"tarefa/mostra";}

@RequestMapping("alteraTarefa")publicStringaltera(Tarefatarefa){dao.altera(tarefa);return"redirect:listaTarefas";}

@RequestMapping("finalizaTarefa")publicStringfinaliza(Longid,Modelmodel){dao.finaliza(id);model.addAttribute("tarefa",dao.buscaPorId(id));return"tarefa/finalizada";}}

1. VamosusarJPAatravésdoSpring.ParaissoéprecisocopiarosJARseguintes:

aopalliance.jar

spring-orm-4.x.x.RELEASE.jar

spring-tx-4.x.x.RELEASE.jar

Paraisso:

VáaoDesktop,eentrenodiretórioCaelum/21/jars-jpa/spring4.

Copie os JARs ( CTRL+C ) e cole-o ( CTRL+V ) dentro de workspace/fj21-

tarefas/WebContent/WEB-INF/lib

16.6EXERCÍCIOS:INTEGRANDOJPACOMSPRING

.

Page 242: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

2. No projeto fj21-tarefas , vá a pasta WebContent/WEB-INF e abra o arquivo spring-context.xml.

NeleéprecisodeclararoentityManagerFactoryeogerenciadordetransações.

Você pode copiar essa parte do XML do arquivo Caelum/21/jars-jpa/spring4/spring-

jpa.xml.txt.Copieoconteúdodoarquivoecoledentrodospring-context.xml:

<!--gerenciamentodejpapelospring--><beanid="entityManagerFactory"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><propertyname="dataSource"ref="mysqlDataSource"/><propertyname="jpaVendorAdapter"><beanclass="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/></property></bean>

<!--gerenciamentodatransaçãopelospring--><beanid="transactionManager"class="org.springframework.orm.jpa.JpaTransactionManager"><propertyname="entityManagerFactory"ref="entityManagerFactory"/></bean>

<tx:annotation-driven/>

Comessasdeclarações,SpringgerenciaaEntityManagerFactory e habilita o gerenciamentodetransações.

3. O próximo passo é criar a interface TarefaDao. Crie uma nova interface dentro do packagebr.com.caelum.tarefas.dao:

packagebr.com.caelum.tarefas.dao;

//importsomitidos

publicinterfaceTarefaDao{

TarefabuscaPorId(Longid);List<Tarefa>lista();voidadiciona(Tarefat);voidaltera(Tarefat);voidremove(Tarefat);voidfinaliza(Longid);}

4. CrieumaclasseJpaTarefaDaoquerecebeoEntityManager.ImplementeainterfaceTarefaDaocomtodososmétodos.

packagebr.com.caelum.tarefas.dao;

//importsomitidos

@RepositorypublicclassJpaTarefaDaoimplementsTarefaDao{

@PersistenceContextEntityManagermanager;

.

Page 243: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

//semconstrutor

publicvoidadiciona(Tarefatarefa){manager.persist(tarefa);}

publicvoidaltera(Tarefatarefa){manager.merge(tarefa);}

publicList<Tarefa>lista(){returnmanager.createQuery("selecttfromTarefat").getResultList();}

publicTarefabuscaPorId(Longid){returnmanager.find(Tarefa.class,id);}

publicvoidremove(Tarefatarefa){TarefatarefaARemover=buscaPorId(tarefa.getId());manager.remove(tarefaARemover);}

publicvoidfinaliza(Longid){Tarefatarefa=buscaPorId(id);tarefa.setFinalizado(true);tarefa.setDataFinalizacao(Calendar.getInstance());}}

5. Altere a classe TarefasController , use a interface TarefaDao apenas. Assim a classeTarefasControllerficadesacopladodaimplementação.Nãoesquecedeapagaroconstrutor:

@ControllerpublicclassTarefasController{

@AutowiredTarefaDaodao;//usaapenasainterface!

//semconstrutor

//métodosomitidos,semmudança}

6. Por fim, vamos habilitar o gerenciamento de transação para qualquer método da classeTarefasController.

Abraaclasseeuseaanotação@Transactionalemcimadaclasse:

@Transactional@ControllerpublicclassTarefasController{

7. ReinicieoTomcateacesseaaplicaçãodetarefasemhttp://localhost:8080/fj21-tarefas/listaTarefas.

.

Page 244: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO17

"Aquelequecastigaquandoestáirritado,nãocorrige,vinga-se"--MicheldeMontaigne

Nestecapítulo,vocêaprenderá:

OqueéInversãodeControle,InjeçãodeDependênciaseConventionoverConfiguration;ComoutilizarumframeworkMVCbaseadoemtaisideias;ComoabstrairacamadaHTTPdasualógicadenegócios;ComonãoutilizararquivosXMLparaconfiguraçãodasuaaplicação;AusaroframeworkMVCVRaptor3.

Vamos lembrar como fica um código utilizando um controlador MVC simples para acessar osparâmetrosdorequest,enviadospelocliente.

Éfácilnotarcomoasclasses,interfaceseapetrechosdaquelecontroladorinfectamonossocódigoesurgeanecessidadedeconheceraAPIdeservletsafundo.OcódigoaseguirmostraumaActiondoStruts1queutilizaumDAOparaincluirumcontatonobancodedados.

publicclassAdicionaContatoimplementsAction{

publicStringexecuta(HttpServletRequestreq,HttpServletResponseres)throwsException{Contatocontato=newContato();contato.setNome(req.getParameter("nome"));contato.setEndereco(req.getParameter("endereco"));contato.setEmail(req.getParameter("email"));

ContatoDaodao=newContatoDao();dao.adiciona(contato);

return"/ok.jsp";}}

Baseadonocódigoacima,percebemosqueestamosfortementeatreladosaHttpServletRequesteseumétodogetParameter.Fora isso,usamosdiversasclassesestranhasaonossoprojeto:Action,HttpServletRequesteHttpServletResponse.Seestivéssemoscontrolandomelhoraconexão,seria

APÊNDICE-VRAPTOR3EPRODUTIVIDADENAWEB

17.1MOTIVAÇÃO:EVITANDOAPISCOMPLICADAS

.

Page 245: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

necessário importarConnection também!Nenhumadessas classes e interfaces citadas faz parte donossoprojeto!Nãoéocódigoquemodelaminhalógica!

Émuitochato,enadaprático,repetirissoemtodaasuaaplicação.Sendoassim,visandofacilitaressetipodetrabalho,vimosqueoStrutsAction,porexemplo,utilizaalgunsrecursosquefacilitamonossotrabalho:

publicclassAdicionaContatoextendsAction{

publicActionForwardexecute(ActionMappingmap,ActionFormform,HttpServletRequestreq,HttpServletResponseres)throwsException{

Contatocontato=((ContatoForm)form).getContato();

ContatoDaodao=newContatoDao();dao.adiciona(contato);

returnmap.findForward("ok");}}

Mas,mesmoassim,imagineoslimitesdetalcódigo:

Vocênãopoderecebermaisdeumactionform;SuaclassedeveestenderActionForm.Sevocêqueriaestenderoutra,azar;Vocêdeverecebertodosessesargumentosquenãofoivocêquemcriou;Vocêdeveretornaressetipoquenãofoivocêquemcriou;VocêdevetrabalharcomStringsoutiposmuitopobres.Osistemadeconversãoécomplexoparainiciantes;O código fica muito alienado: ele é escrito de tal forma que o programador precisa agradar oframeworkenãooframeworkagradaroprogramador;Você acaba criando classes repetidas: deve criar dois beans repetidos ou parecidos, ou aindaescrevermuitocódigoxmlparasubstituirumdeles.

Dadoessesproblemas,surgiramdiversosoutrosframeworks,inclusivediversospatternsnovos,entreeles,InjeçãodeDependências(DependencyInjection),InversãodeControle(InversionofControl-IoC)eohábitodepreferirterconvençõesemvezdeconfiguração(ConventionoverConfiguration-CoC).

ImaginequepossamosdeixardeestenderAction:

publicclassAdicionaContato{publicActionForwardexecute(ActionMappingmap,ActionFormform,HttpServletRequestreq,HttpServletResponseres)throwsException{Contatocontato=((ContatoForm)form).getContato();

ContatoDaodao=newContatoDao();dao.adiciona(contato);

returnmap.findForward("ok");}

.

Page 246: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

}

Nessemomentoestamoslivresparamudarnossométodoexecute.Desejamosqueele se chameadiciona,enãoumnomegenéricocomoexecute,semcontarquenãoprecisamosdetodosaquelesquatroargumentos.Afinal,nãoutilizamosorequesteresponse:

publicclassAdicionaContato{publicActionForwardadiciona(ActionMappingmap,ActionFormform)throwsException{

Contatocontato=((ContatoForm)form).getContato();

ContatoDaodao=newContatoDao();dao.adiciona(contato);

returnmap.findForward("ok");}}

Aospoucos,ocódigovaificandomaissimples.ReparequenamaioriadasvezesqueretornamosoActionForward,oretornoé"ok".Seráquesempre temosque fazer isso?Nãoseriamais fácilnãoretornarvaloralgum,jáquesempreretornamosomesmovalor?Portanto,vamosremoveressevalorderetornoaoinvésdeusaresseestranhoActionMapping:

publicclassAdicionaContato{publicvoidadiciona(ActionFormform)throwsException{

Contatocontato=((ContatoForm)form).getContato();

ContatoDaodao=newContatoDao();dao.adiciona(contato);

}}

Por fim, emvezde criarumaclassequeestendeActionForm, ou configurar toneladasdeXML,desejamosreceberumContatocomoparâmetrodométodo.

PortantonadamaisnaturalqueoparâmetrosejaContato,enãoContatoForm.

publicclassAdicionaContato{

publicvoidadiciona(Contatocontato)throwsException{

ContatoDaodao=newContatoDao();dao.adiciona(contato);

}}

Oresultadoéumcódigobemmaislegível,eumcontroladormenosintrusivonoseucódigo:nessecasonemusamosaAPIdeservlets!

.

Page 247: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.

CasadoCódigo,LivrosdeTecnologia.

Vocêdesconectao seuprogramada camadaweb, criandoaçõesoucomandosquenão trabalhamcomrequesteresponse.

Noteque,enquantoutilizávamosalógicadaquelamaneira,omesmoserviadeadaptadorparaaweb.Nãoprecisamosmaisdesseadaptador,nossapróprialógicaqueéumaclasseJavacomum,podeservirparaawebouaqualqueroutropropósito.

Alémdisso,vocêrecebetodososobjetosqueprecisaparatrabalhar,nãosepreocupandoembuscá-los. Isso é chamado de injeção de dependências. Por exemplo, se você precisa do usuário logado nosistemae, supondoqueele sejado tipoFuncionario, vocêpodecriarumconstrutorque requer talobjeto:

publicclassAdicionaContato{

publicAdicionaContato(Funcionariofuncionario){//oparametroéofuncionariologadonosistema}

publicvoidadiciona(Contatocontato)throwsException{

ContatoDaodao=newContatoDao();dao.adiciona(contato);

}}

Tudo o que faremos neste capítulo está baseado no framework opensource Vraptor 3. Sua

Seuslivrosdetecnologiaparecemdoséculopassado?

17.2 VANTAGENS DE UM CÓDIGO INDEPENDENTE DE REQUEST ERESPONSE

17.3VRAPTOR3

.

Page 248: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

documentaçãopodeserencontradaem:

http://www.vraptor.com.br/

Iniciativabrasileira,oVRaptorfoicriadoinicialmenteparaodesenvolvimentodeprojetosinternosdoInstitutodeMatemáticaeEstatísticadaUSP,pelosentãoalunosdocursodeciênciadacomputação.

OsitedoGUJ (www.guj.com.br), fundadoem2002pelosmesmoscriadoresdoVRaptor, teve suaversão nova escrita em VRaptor 2, e hoje em dia roda na versão 3. Este framework é utilizado emprojetosopensourceeporváriasempresasnoBrasiletambémpelomundo.

Consulte o site para tutoriais, depoimentos, screencasts e até palestras filmadas a respeito doframework.

ParaaprendermosmaisdoVRaptor,vamosutilizarseusrecursosbásicosemumpequenoprojeto,evalenotarasimplicidadecomqualocódigovaificar.

Oprojetojávemcomumaclassedemodelopronta,chamadaProduto,queutilizaremosemnossosexemplos,eéumaentidadedoHibernate:

@EntitypublicclassProduto{

@Id@GeneratedValueprivateLongid;

privateStringnome;

privateDoublepreco;

@Temporal(TemporalType.DATE)privateCalendardataInicioVenda;//gettersesetters

}

A classe ProdutoDAO também já existe e utiliza o hibernate para acessar um banco de dados(mysql).

publicclassProdutoDAO{

privateSessionsession;

publicProdutoDao(){this.session=newHibernateUtil().getSession();}

publicvoidadiciona(Produtop){Transactiontx=session.beginTransaction();session.save(p);

17.4ACLASSEDEMODELO

.

Page 249: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

tx.commit();}

publicvoidatualiza(Produtop){Transactiontx=session.beginTransaction();session.update(p);tx.commit();}

publicvoidremove(Produtop){Transactiontx=session.beginTransaction();session.delete(p);tx.commit();}

@SuppressWarnings("unchecked")publicList<Produto>lista(){returnsession.createCriteria(Produto.class).list();}}

OfocodessecapítulonãoestáemcomoconfiguraroHibernateouemboaspráticasdacamadadepersistência portanto o código do DAO pode não ser o ideal por utilizar uma transação para cadachamadademétodo,maséoidealparanossoexemplo.

Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende

Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!

ConheçaaAluraCursosOnline.

VamosescreverumaclassequeadicionaumProdutoaumbancodedadosatravésdoDAOedousodoVRaptor3:

@ResourcepublicclassProdutoController{

publicvoidadiciona(Produtoproduto){newProdutoDao().adiciona(produto);}}

Pronto!Éassimqueficaumaaçãodeadicionarprodutoutilizandoessecontrolador(e,futuramente,

Agoraéamelhorhoradeaprenderalgonovo

17.5MINHAPRIMEIRALÓGICADENEGÓCIOS

.

Page 250: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

vamosmelhorarmaisainda).

Esesurgiranecessidadedecriarummétodoatualiza?Poderíamosreutilizaramesmaclasseparaosdoismétodos:

@ResourcepublicclassProdutoController{

//aaçãoadicionapublicvoidadiciona(Produtoproduto){newProdutoDao().adiciona(produto);}

//aaçãoatualizapublicvoidatualiza(Produtoproduto){newProdutoDao().atualiza(produto);}}

O próprio controlador se encarrega de preencher o produto para chamar nosso método. O queestamosfazendoatravésdaanotação@ResourceédizerparaoVraptordisponibilizaressaclasseparaserinstanciadaeexpostaparaaweb.DessaformaserádisponibilizadoumaURIparaquesejapossívelinvocaralógicadesejada,sejadeadiçãodecontato,sejadeatualização.

Não existe nenhumXML doVRaptor que seja de preenchimento obrigatório. Só essa classe já ésuficiente.

E o JSP com o formulário? Para fazer com que a lógica seja invocada, basta configurarmoscorretamenteoscamposdoformuláriononossocódigohtml.Nãohásegredoalgum.

Note que nosso controller se chama ProdutoController e o nome do método que desejamosinvocar se chama adiciona . Com isso, o VRaptor invocará este método através da URI/produto/adiciona.Reparequeemnenhummomentovocêconfigurouesseendereço.Esseéumdospontos no qual o VRaptor usa diversas convenções dele, ao invés de esperar que você faça algumaconfiguraçãoobrigatória.

Precisamoscriarumapáginaquemostreumamensagemdesucesso,aproveitamoseconfirmamosainclusãomostrandoosdadosqueforamincluídos:

<html>Seuprodutofoiadicionadocomsucesso!<br/></html>

Masqualonomedessearquivo?Umavezqueonomedocontrolleréproduto,onomedalógicaé adiciona , o nome de seu arquivo de saída deve ser: WebContent/WEB-

INF/jsp/produto/adiciona.jsp.

17.6REDIRECIONANDOAPÓSAINCLUSÃO

.

Page 251: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Vocêpodealteraroredirecionamentopadrãodasualógica,enviandoousuárioparaumoutrojsp,para issobasta receberno construtordo seu controller umobjetodo tipoResult. Esse objeto serápassadoparaoseucontrolleratravésdeInjeçãodeDependências.

Dessaforma,umexemploderedirecionarparaoutrojspapósaexecuçãoseria:

@ResourcepublicclassProdutoController{privateResultresult;

publicProdutoController(Resultresult){this.result=result;}

//aaçãoadicionapublicvoidadiciona(Produtoproduto){newProdutoDao().adiciona(produto);result.forwardTo("/WEB-INF/jsp/outroLugar.jsp");}}

E a criação do arquivo WEB-INF/jsp/outroLugar.jsp. Dessa forma, você pode condicionar oretorno,deacordocomoqueacontecerdentrodométodoquerealizarátodaasualógica,controlandoparaondeousuárioseráredirecionadoatravésdeif's.

AlémdetermosapossibilidadederedirecionarparaoutroJSP,tambémpodemosredirecionarparaumaoutralógica.NovamentepodemosfazerissoatravésdoobjetoResult.Bastadizermosquevamosenviarousuárioparaoutra lógicae indicarmosdequalController seráessa lógicae tambémqualmétododeveráserchamado.

publicvoidremove(Produtoproduto){dao.remove(produto);result.redirectTo(ProdutoController.class).lista();}

Isso fará com que logo após a lógica de remoção seja executada, o usuário execute a lógica delistagemquedesenvolveremosaseguir.

Poderíamos criarnossos formulários como JSPsdiretosdentrodeWebContent, e acessarmososmesmosdiretamentenonavegador,masissonãoéumapráticaaconselhada,pois,futuramentepodemosquerer executar alguma lógica antes desse formulário e para isso ele teria que ser uma lógica doVRaptor e provavelmente teríamos que mudar sua URL, quebrando links dos usuários que já ospossuíamgravados,porexemplo.

Vamostomarumaabordagemdiferente,pensandodesdeocomeçoquefuturamenteprecisaremosdeumalógicaexecutandoantesdoformulário,vamoscriarumalógicavazia,quenadamaisfarádoquerepassaraexecuçãoaoformulárioatravésdaconvençãodoVRaptor.

17.7CRIANDOOFORMULÁRIO

.

Page 252: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

@ResourcepublicclassProdutoController{publicvoidformulario(){}}

PodemosacessaronossoformuláriopelonavegadoratravésdaURL:/produto/formulario.

Jáosparâmetrosdevemserenviadoscomonomedoparâmetroquedesejamospreencher,nonossocaso,produto,pois,éonomedoparâmetrodométodoadiciona:

<html><formaction="produto/adiciona">Nome:<inputname="produto.nome"/><br/>Descricao:<inputname="produto.descricao"/><br/>Preço:<inputname="produto.preco"/><br/>Datadeiníciodevenda:<inputname="produto.dataInicioVenda"/><br/><inputtype="submit"/></form></html>

Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.

CasadoCódigo,ebookcompreçodeebook.

EditoraCasadoCódigocomlivrosdeumaformadiferente

17.8ALISTADEPRODUTOS

.

Page 253: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Opróximopassoserácriara listagemde todososprodutosdosistema.Nossa lógicadenegócios,maisumavez,possuisomenteaquiloqueprecisa:

@ResourcepublicclassProdutoController{

publicvoidlista(){newProdutoDao().lista();}

}

Masdessavezprecisamosdisponibilizarestalistadeprodutosparaanossacamadadevisualização.Pensandoemcódigo java,qual é a formamais simplesque temosde retornarumvalor (objeto)paraalguém?Comumsimplesreturn, logo,nossométodo lista poderia retornar a própria lista que foidevolvidapeloDAO,daseguinteforma:

publicList<Produto>lista(){returnnewProdutoDao().lista();}

Dessaforma,oVRaptordisponibilizaránaviewumobjetochamadoprodutoList,quevocêpossuiacessoviaExpressionLanguage.

Reparequenossaclassepodesertestadafacilmente,bastainstanciarobeanProdutoController,chamar o método lista e verificar se ele retorna ou não a lista que esperávamos. Todas essasconvenções evitandoousode configurações ajudambastantenomomentode criar testesdeunidadeparaoseusistema.

Por fim, vamos criar o arquivo lista.jsp no diretório WebContent/WEB-INF/jsp/produto/utilizandoataglibcoredaJSTL:

<%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%><%@tagliburi="http://java.sun.com/jsp/jstl/fmt"prefix="fmt"%>

<h1>Produtos</h1><table><c:forEachvar="produto"items="${produtoList}"><tr><td>${produto.nome}</td><td>${produto.preco}</td><td>${produto.descricao}</td><td><fmt:formatDatepattern="dd/MM/yyyy"value="${produto.dataInicioVenda.time}"/></td></tr></c:forEach></table>

Echameoendereço:http://localhost:8080/controle-produtos/produto/lista,oresultadodeveseralgoparecidocomaimagemabaixo:

.

Page 254: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

VamoscriarumnovoprojetodoEclipse,usandoumprojetojácomeçadocomoVRaptor.

1. CrieumnovoDynamicWebProjectchamadocontrole-produtos.

2. Cliquedadireitanonomedoprojetocontrole-produtoseváemImport>ArchiveFile.ImporteoarquivoDesktop/caelum/21/controle-produtos.zip.

3. GereatabelaProduto.ProcureaclasseGeraTabelaeexecuteométodomain.4. AssocieoprojetocomoTomcateacessenoseunavegadoraURL:http://localhost:8080/controle-

produtos

5. Vamoscriarapartedelistagemdosprodutos.

CrieaclasseProdutoController nopacotebr.com.caelum.produtos.controller, comométodoparafazeralistagem(Nãoseesqueçadeanotaraclassecom@Resource):

@ResourcepublicclassProdutoController{

publicList<Produto>lista(){returnnewProdutoDao().lista();}

}

Crieoarquivolista.jspnodiretórioWebContent/WEB-INF/jsp/produto(criepastaejsp)

<%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%><%@tagliburi="http://java.sun.com/jsp/jstl/fmt"prefix="fmt"%>

<h1>Produtos</h1><table><c:forEachvar="produto"items="${produtoList}"><tr><td>${produto.nome}</td><td>${produto.preco}</td><td>${produto.descricao}</td><td><fmt:formatDatepattern="dd/MM/yyyy"value="${produto.dataInicioVenda.time}"/>

17.9EXERCÍCIOS

.

Page 255: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

</td></tr></c:forEach></table>

Testeasualógica:http://localhost:8080/controle-produtos/produto/lista.

6. Vamoscriarafuncionalidadedeadicionarprodutos.

NaclasseProdutoControllercrieométodoadiciona:

@ResourcepublicclassProdutoController{

//aaçãoadicionapublicvoidadiciona(Produtoproduto){newProdutoDao().adiciona(produto);}

}

Após o produto ser gravado, devemos retornar para a listagem dos produtos. Para isso vamosadicionar o redirecionamento no método adiciona . Para fazermos esse redirecionamentovamosprecisarreceberumobjetodotipoResultnoconstrutordonossoProdutoController:

@ResourcepublicclassProdutoController{privateResultresult;

publicProdutoController(Resultresult){this.result=result;}

//métodoparafazeralistagem

publicvoidadiciona(Produtoproduto){newProdutoDao().adiciona(produto);result.redirectTo(ProdutoController.class).lista();}

}

Vamoscriaralógicaparaoformulário

@ResourcepublicclassProdutoController{

publicvoidformulario(){}

}

Crieoarquivoformulario.jspnodiretórioWebContent/WEB-INF/jsp/produto

<%@taglibtagdir="/WEB-INF/tags"prefix="caelum"%><%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%><html>

.

Page 256: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

<head><scripttype="text/javascript"src="<c:urlvalue="/js/jquery.js"/>"></script><scripttype="text/javascript"src="<c:urlvalue="/js/jquery-ui.js"/>"></script><linktype="text/css"href="<c:urlvalue="/css/jquery.css"/>"rel="stylesheet"/></head><body><formaction="<c:urlvalue="/produto/adiciona"/>">Nome:<inputname="produto.nome"/><br/>Descricao:<inputname="produto.descricao"/><br/>Preço:<inputname="produto.preco"/><br/>Datadeiníciodavenda:<caelum:campoDataid="dataInicioVenda"name="produto.dataInicioVenda"/><br/><inputtype="submit"/></form></body></html>

Se achar conveniente, crie um arquivo para o cabecalho faça-o importar as bibliotecas emJavascripteoCSSeinclua-onoformulario.jsp

Você importoualgumaclassedopacotejavax.servlet?É importantepercebermosquenãoestamosatreladoscomnenhumaAPIestranha.ApenasescrevemoscódigoJavanormal.

Teste o seu formulário:http://localhost:8080/controle-produtos/produto/formulario.Adicionealgunsprodutosdiferentes.

7. Vamosfazeraexclusãodeprodutos.

Vamosprimeiramentecriarumanovacolunananossatabelanolista.jsp,adicionandoparacadaprodutoumlinkparafazermosaexclusão:

<c:forEachvar="produto"items="${produtoList}"><tr><td>${produto.nome}</td><td>${produto.preco}</td><td>${produto.descricao}</td><td><fmt:formatDatepattern="dd/MM/yyyy"value="${produto.dataInicioVenda.time}"/></td><td><ahref="<c:urlvalue="/produto/remove"/>?produto.id=${produto.id}">Remover</a></td></tr></c:forEach>

VamoscriaranossanovalógicaparaexclusãonoProdutoControllerqueredirecionaráparaalógicadelistaapósaremoçãodoproduto:

.

Page 257: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

publicvoidremove(Produtoproduto){newProdutoDao().remove(produto);result.redirectTo(ProdutoController.class).lista();}

Acesse a lista de produtos em http://localhost:8080/controle-produtos/produto/lista e removaalgunsprodutos.

8. (Opcional)Façaafuncionalidadedealteraçãodoprodutodaformaqueacharconveniente

O VRaptor utiliza bastante Injeção de Dependências e também permite que nós utilizemos emnossosControllers. O grande ganho que temos com isso é que nosso código fica muito menosacoplado com outras bibliotecas, aumentando a testabilidade da nossa aplicação através de testes deunidade,assuntocobertonocursoFJ-22.

Alémdisso, outra vantagemque sentimos ao utilizar Injeção deDependências é a legibilidade denossocódigo.Nóssabemosoqueelerecebe,mas lendoonossocódigo,nãoprecisamossaberdequallugaressadependênciaestávindo,apenascomoelaseráutilizada.OfatodenãosabermosmaiscomoanossadependênciaserácriadaéoquechamamosdeInversãodeControle.

OcódigoquedesenvolvemosnoProdutoController possuiumexemplomuitobomde códigoacoplado. Repare que todas as nossas lógicas (adiciona, remove, lista etc) sabem como oProdutoDaotemquesercriado,ouseja,queprecisamosinstanciá-losempassarnenhumargumentopro seuconstrutor.Seumdiamudássemosoconstrutorpara receberalgumparâmetro, teríamosquemudartodososmétodosdenossalógicaeissonãoéalgoquequeremosnospreocuparnodiaadia.

AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,

Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex-aluno daCaelumtem15%dedescontonestelink!

ConheçaoscursosonlineAlura.

17.10APROFUNDANDOEMINJEÇÃODEDEPENDÊNCIASEINVERSÃODECONTROLE

JáconheceoscursosonlineAlura?

.

Page 258: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

PodemosdesacoplarosnossosmétodosdeProdutoControllerfazendocomqueoControllerapenasrecebaemseuconstrutorumainstânciadeProdutoDao.EquandooVRaptorprecisarcriaroProdutoControlleracadarequisição,eletambémcriaráumainstânciadoProdutoDaoparapassaraoController.

publicclassProdutoController{privateResultresult;privateProdutoDaoprodutoDao;

publicProdutoController(Resultresult,ProdutoDaoprodutoDao){this.result=result;this.produtoDao=produtoDao;}

//métodosparaadicionar,excluirelistarprodutos}

No entanto, se executarmos qualquer lógica nossa aplicação vai parar de funcionar. Isso porqueprecisamosdizerparaoVRaptorqueProdutoDaoéumaclassequeelevaigerenciar.

Podemosfazerissoatravésdaanotação@ComponentnonossoProdutoDao.

Aqui, emumcasomaisusual,ProdutoDao seria uma interface, e nosso componente seria umaclasseconcretacomo,porexemplo,HibernateProdutoDao.OVRaptorvai saberdescobrirquedeveinjetarumHibernateProdutoDaoparaquemprecisaumProdutoDao.Dessa formadesacoplamosaindamaisnossocódigodocontroller,podendopassarmocksparaelequando formos testá-lo,comoveremosnocursoLaboratórioJava.

@ComponentpublicclassProdutoDao{

//construtoremétodosdoDao}

Por padrão, o VRaptor criará um ProdutoDao por requisição. Mas nem sempre é isso quequeremos. Portanto, podemosmudar esse comportamento através de anotações que determinam emqualescopoonossocomponenteficará:

@RequestScoped-ocomponenteseráomesmodurantearequisição@SessionScoped-ocomponenteseráomesmoduranteasessãodousuário@ApplicationScoped-ocomponenteseráomesmoparatodaaaplicação@PrototypeScoped-ocomponenteseráinstanciadosemprequerequisitado

Paradefinirmosumescopo,onossoContatoDaopoderiaficardaseguinteforma:

@Component

17.11INJEÇÃODEDEPENDÊNCIASCOMOVRAPTOR

17.12ESCOPOSDOSCOMPONENTES

.

Page 259: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

@RequestScopedpublicclassProdutoDao{

//construtoremétodosdoDao}

COMOOSCOMPONENTESSÃOGERENCIADOSPELOVRAPTOR?

Umadas boas ideias doVRaptor é o de não reinventar a roda e reutilizar funcionalidades eframeworksjáexistentesquandopossível.

UmadaspartesnaqualoVRaptorseutilizadeframeworksexternosénapartedeInjeçãodeDependências, naqual ele utiliza o frameworkSpring quepossui umcontainerde InjeçãodeDependências.

AprendemosSpringafundonocursoFJ-27quecobreemdetalhesoframework.

1. Vamos diminuir o acoplamento do ProdutoController com o ProdutoDao recebendo-o noconstrutor.

Precisamos fazercomqueoProdutoDao sejaumcomponentegerenciadopeloVRaptor.Paraisso,vamosanotá-locom@Componente@RequestScoped.

@Component@RequestScopedpublicclassProdutoDao{

//construtoremétodosdoDao}

BastaindicarmosquequeremosreceberProdutoDaonoconstrutordoProdutoControllereutilizarmos o DAO recebido para fazermos nossas operações com o banco de dados. Não seesqueçadealterarseusmétodos.

@ResourcepublicclassProdutoController{privateResultresult;privateProdutoDaoprodutoDao;

publicProdutoController(Resultresult,ProdutoDaoprodutoDao){this.result=result;this.produtoDao=produtoDao;}

publicList<Produto>lista(){returnprodutoDao.lista();}

17.13 EXERCÍCIOS: USANDO INJEÇÃO DE DEPENDÊNCIAS PARA ODAO

.

Page 260: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

publicvoidadiciona(Produtoproduto){produtoDao.adiciona(produto);//redirecionamento}

publicvoidremove(Produtoproduto){produtoDao.remove(produto);//redirecionamento}}

Reiniciesuaaplicaçãoeverifiquequetudocontinuafuncionandonormalmente.

Querendoaprenderaindamaissobre?Esclarecerdúvidasdosexercícios?Ouvirexplicaçõesdetalhadascomuminstrutor?ACaelum oferece o cursoFJ-21 presencial nas cidades de São Paulo, Rio deJaneiroeBrasília,alémdeturmasincompany.

ConsulteasvantagensdocursoJavaparaDesenvolvimentoWeb

Nossa aplicação de controle de produtos permite que qualquer pessoa modifique os dados deprodutos. Isso não é algo bom, pois, pessoas sem as devidas permissões poderão acessar essafuncionalidadeeguardardadosinconsistentesnobanco.

Precisamos fazer com que os usuários façam login em nossa aplicação e caso ele esteja logado,permitiremosacessoàsfuncionalidades.

Paraconstruirafuncionalidadedeautenticação,precisamosantesteromodelodeUsuarioeoseurespectivoDAOcomométodoparabuscaroUsuarioatravésdologinesenha.

@EntitypublicclassUsuario{@Id@GeneratedValueprivateLongid;

privateStringnome;

privateStringlogin;

privateStringsenha;

//gettersesetters

VocêpodetambémfazerocursoFJ-21dessaapostilanaCaelum

17.14ADICIONANDOSEGURANÇAEMNOSSAAPLICAÇÃO

.

Page 261: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

}

@Component@RequestScopedpublicclassUsuarioDao{privateSessionsession;

publicUsuarioDao(){this.session=newHibernateUtil().getSession();}

publicUsuariobuscaUsuarioPorLoginESenha(Usuariousuario){Queryquery=this.session.createQuery("fromUsuariowhere"+"login=:pLoginandsenha=:pSenha");query.setParameter("pLogin",usuario.getLogin());query.setParameter("pSenha",usuario.getSenha());return(Usuario)query.uniqueResult();}}

Comojápossuímosomodelodeusuário,precisamosguardarousuárionasessão.

Jáaprendemosquepodemoscriarumcomponente(@Component)queficaguardadonasessãodousuário.Portanto,vamosutilizaressafacilidadedoVRaptor.

@Component@SessionScopedpublicclassUsuarioLogado{privateUsuariousuarioLogado;

publicvoidefetuaLogin(Usuariousuario){this.usuarioLogado=usuario;}

//getterprousuarioLogado}

Basta construirmos o Controller que fará o login do nosso usuário. Vamos criar uma classechamadaLoginControllerquereceberáviaconstrutorumUsuarioLogadoeoUsuarioDao.ApósaverificaçãodequeousuárioinformadoestácadastradooguardaremosdentrodonossocomponenteUsuarioLogado.Seousuárioexistir,arequisiçãoseráredirecionadaparaalistagemdosprodutos.

@ControllerpublicclassLoginController{privateUsuarioDaousuarioDao;privateUsuarioLogadousuarioLogado;privateResultresult;

publicLoginController(UsuarioDaousuarioDao,UsuarioLogadousuarioLogado,Resultresult){this.usuarioDao=usuarioDao;this.usuarioLogado=usuarioLogado;this.result=result;}

publicvoidautentica(Usuariousuario){Usuarioautenticado=usuarioDao.buscaUsuarioPorLoginESenha(usuario);if(autenticado!=null){

.

Page 262: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

usuarioLogado.efetuaLogin(autenticado);result.redirectTo(ProdutoController.class).lista();}}}

Bastacriarmosoformulárioparafazermosologin.Vamosutilizaramesmaestratégiadoformuláriopara cadastro de produtos, criando um método no nosso Controller que redirecionará para oformulário.

@ControllerpublicclassLoginController{//atributos,construtoremétodosparaefetuarologin

publicvoidformulario(){}}

E o JSP contendo o formulário, que estará em WEB-INF/jsp/login e se chamaráformulario.jsp:

<html><body><h2>LoginnoControledeProdutos</h2><formaction="login/autentica">Login:<inputtype="text"name="usuario.login"/><br/>Senha:<inputtype="password"name="usuario.senha"/><inputtype="submit"value="Autenticar"/></form></body></html>

Aindaprecisamosfazercomqueseologinsejainválido,ousuáriovolteparaateladelogin:

publicvoidautentica(Usuariousuario){Usuarioautenticado=dao.buscaUsuarioPorLoginESenha(usuario);if(autenticado!=null){usuarioLogado.efetuaLogin(autenticado);result.redirectTo(ProdutoController.class).lista();return;}result.redirectTo(LoginController.class).formulario();}

Pronto,nossafuncionalidadedeLoginestápronta!

Mascomogarantirqueousuárioestámesmo logadonanossaaplicaçãonomomentoemqueeletenta,porexemplo,acessaroformuláriodegravaçãodeprodutos?

Oqueprecisamosfazeréverificar,antesdequalquerlógicaserexecutada,seousuárioestáguardadona sessão. Podemos fazer isso através deInterceptors, que funcionam de forma parecida com osFilters que aprendemos anteriormente. A vantagem é que os Interceptors nos fornecemfacilidadesamaisqueestãoligadasaoVRaptor,algoqueaAPIdeFilternãonosprovê.

17.15INTERCEPTANDOREQUISIÇÕES

.

Page 263: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Para criarmos um Interceptor basta criarmos uma classe que implementa a interfacebr.com.caelum.vraptor.Interceptoreanotá-lacom@Intercepts.

Aoimplementarmosainterface,devemosescreverdoismétodos:intercepteaccepts.

intercept: Possui o código que fará toda a lógica que desejamos executar antes e depois darequisiçãoserprocessada.accepts:Métodoque indicaatravésdeumretornoboolean quemdeverá ser interceptado equemnãodeveráserinterceptado.

OInterceptorcomoqualquercomponente,podereceberemseuconstrutoroutroscomponentesenonossocasoeleprecisarádoUsuarioLogadoparasaberseexistealguémlogadoounão.

Dessaforma,onossoInterceptorteráoseguintecódigo:

@InterceptspublicclassLoginInterceptorimplementsInterceptor{

privateUsuarioLogadousuarioLogado;privateResultresult;

publicLoginInterceptor(UsuarioLogadousuarioLogado,Resultresult){this.usuarioLogado=usuarioLogado;this.result=result;}

publicvoidintercept(InterceptorStackstack,ResourceMethodmethod,Objectinstance)throwsInterceptionException{if(usuarioLogado.getUsuario()!=null){stack.next(method,instance);}else{result.redirectTo(LoginController.class).formulario();}}

publicbooleanaccepts(ResourceMethodmethod){ResourceClassresource=method.getResource();

return!resource.getType().isAssignableFrom(LoginController.class);}}

Pronto,temosnossafuncionalidadedeautenticaçãoetambémapartedeautorizaçãofinalizadas.

1. VamospermitirquenossosusuáriospossamefetuarLoginnaaplicação.

CrieocomponenteUsuarioLogadonopacotebr.com.caelum.produtos.component comoseguintecódigo:

17.16 EXERCÍCIOS: CONSTRUINDO A AUTENTICAÇÃO E AAUTORIZAÇÃO

.

Page 264: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

@Component@SessionScopedpublicclassUsuarioLogado{privateUsuariousuarioLogado;

publicvoidefetuaLogin(Usuariousuario){this.usuarioLogado=usuario;}

publicUsuariogetUsuario(){returnthis.usuarioLogado;}}

FaçacomqueUsuarioDaosejaumcomponenteanotando-ocom@Componenteindiquequeeledeveráestarnoescopoderequisição(@RequestScoped).

@Component@RequestScopedpublicclassUsuarioDao{

//metodoseconstrutor}

CrieaclasseLoginControllerdentrodopacotebr.com.caelum.produtos.controller:

@ResourcepublicclassLoginController{privateUsuarioDaousuarioDao;privateUsuarioLogadousuarioLogado;privateResultresult;

publicLoginController(UsuarioDaousuarioDao,UsuarioLogadousuarioLogado,Resultresult){this.usuarioDao=usuarioDao;this.usuarioLogado=usuarioLogado;this.result=result;}

publicvoidautentica(Usuariousuario){Usuarioautenticado=usuarioDao.buscaUsuarioPorLoginESenha(usuario);if(autenticado!=null){usuarioLogado.efetuaLogin(autenticado);result.redirectTo(ProdutoController.class).lista();return;}result.redirectTo(LoginController.class).formulario();}

publicvoidformulario(){}}

Vamos criar a tela parapermitir comqueosusuários se loguemna aplicação, crie umarquivochamadoformulario.jspdentrodeWEB-INF/jsp/logincomoconteúdo:

<%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%><html><body>

.

Page 265: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

<h2>LoginnoControledeProdutos</h2><formaction="<c:urlvalue="/login/autentica"/>">Login:<inputtype="text"name="usuario.login"/><br/>Senha:<inputtype="password"name="usuario.senha"/><inputtype="submit"value="Autenticar"/></form></body></html>

Vamoscriarointerceptadorparanãodeixarousuárioacessarasfuncionalidadesdonossosistemasem ter logado antes. Crie a classe LoginInterceptor no pacotebr.com.caelum.produtos.interceptor:

@InterceptspublicclassLoginInterceptorimplementsInterceptor{

privateUsuarioLogadousuarioLogado;privateResultresult;

publicLoginInterceptor(UsuarioLogadousuarioLogado,Resultresult){this.usuarioLogado=usuarioLogado;this.result=result;}

publicvoidintercept(InterceptorStackstack,ResourceMethodmethod,Objectinstance)throwsInterceptionException{

if(usuarioLogado.getUsuario()!=null){stack.next(method,instance);}else{result.redirectTo(LoginController.class).formulario();}}

publicbooleanaccepts(ResourceMethodmethod){ResourceClassresource=method.getResource();

return!resource.getType().isAssignableFrom(LoginController.class);}}

Tente acessar http://localhost:8080/controle-produtos/produto/lista e como você não efetuou ologin,vocêéredirecionadoparaadevidateladelogin.

.

Page 266: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Efetueoseulogin.Verifiqueoseubancodedadosparaconseguirumloginválido.Casonãoexistaninguémcadastrado,insiraumusuárionobancocomocomandoabaixoetenteefetuarologin:

insertintoUsuario(nome,login,senha)values('Administrador','admin','admin123');

Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.

CasadoCódigo,LivrosdeTecnologia.

Sempreque clicamosno linkRemover na listagemdosprodutosuma requisição é enviadaparaoendereço/produto/remove, a exclusão é feita no banco de dados e em seguida toda a listagem érecriadanovamente.

A requisição ser enviada e a exclusão ser feita no banco de dados são passos obrigatórios nesseprocesso,masseráqueprecisamosrecriartodaalistagemoutravez?

Podemosdestacaralgunspontosnegativosnessaabordagem,porexemplo:

Tráfegonarede:RecebemoscomorespostatodooHTMLpararegeraratelainteira.Nãoseriamaisleveapenasremovermosa linhadatabelaqueacabamosdeexcluiraoinvésderecriarmostodaatabela?Demora na resposta: Se a requisição demorar para gerar uma resposta, toda a navegação ficarácomprometida.Dependendodopontoaondeestiveralentidãopoderáatéficarumatelaembrancoque não dirá nada ao usuário. Será que não é mais interessante para o usuário permanecer namesma tela emque ele estava e colocar na tela umamensagem indicando que está realizando aoperação? Como a tela continuará aberta sempre, ele pode continuar sua navegação e usonormalmente.

Seuslivrosdetecnologiaparecemdoséculopassado?

17.17MELHORANDOAUSABILIDADEDANOSSAAPLICAÇÃO

17.18PARASABERMAIS:REQUISIÇÕES:SÍNCRONOXASSÍNCRONO

.

Page 267: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Nóspodemosenviarrequisiçõesemnossasaplicaçõeswebquenão"travem"anavegaçãodousuárioemantenhaaaplicaçãodisponívelparacontinuar sendoutilizada.As requisições tradicionais, comasquaisestamosacostumadoséoquechamamosdeRequisiçõesSíncronas,naqualonavegadoraoenviararequisiçãointerrompeanavegaçãoereexibetodaarespostadevolvidapeloservidor.

Maspodemosutilizarumoutroestilo,quesãoasRequisiçõesAssíncronas.Nelas,quandoarequisiçãoé enviada, o navegador continua no estado em que estava antes, permitindo a navegação.Quando arespostaédadapelo servidorépossívelpegá-laeapenaseditaralgumpedaçodapáginaque jáestavaexibidaantesparamostrarumconteúdonovo(semrecarregartodaapágina).

Podemos fazer requisições assíncronas através de uma técnica conhecida como AJAX(Assynchronous JavascriptandXML). Essa técnicanadamais é doqueutilizar a linguagem Javascriptpara que em determinados eventos da sua página, por exemplo, o clique de um botão, seja possívelenviarasrequisiçõesdeformaassíncronaparaumdeterminadolugar,recuperaressarespostaeeditarnossapáginaparaalterarmosdinamicamenteoseuconteúdo.

UmdosgrandesproblemasdeAJAXquandoatécnicasurgiuéqueeramuitocomplicadoutilizá-la,principalmente porque haviam incompatibilidades entre os diversos navegadores existentes. Muitostratamentostinhamqueserfeitos,paraqueasfuncionalidadesfossemcompatíveiscomosnavegadores.Edessaforma,tínhamoscódigosmuitograndesededifícillegibilidade.

Hoje em dia temos muito mais facilidade para trabalhar com AJAX, através de bibliotecas deJavascript que encapsulam toda sua a complexidadenos fornecemumaAPI agradávelpara trabalhar,comoporexemplo,jQuery,YUI(YahooUserInterface),ExtJSeassimpordiante.

Se você está gostando dessa apostila, certamente vai aproveitar os cursosonlinequelançamosnaplataformaAlura.VocêestudaaqualquermomentocomaqualidadeCaelum.Programação,Mobile,Design, Infra,Front-Ende

Business!Ex-alunodaCaelumtem15%dedesconto,sigaolink!

ConheçaaAluraCursosOnline.

17.19PARASABERMAIS:AJAX

Agoraéamelhorhoradeaprenderalgonovo

17.20ADICIONANDOAJAXNANOSSAAPLICAÇÃO

.

Page 268: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Aqui no curso utilizaremos o jQuery,mas tudo o que fizermos também poderá ser feito com asoutrasbibliotecas.Paradetalhesdecomofazer,consultesuasdocumentações.

VamoscolocarAJAXnaremoçãodosprodutos.AoclicarmosnolinkRemover,vamosdispararumevento que estará associado com uma função em Javascript, que utilizará o jQuery para enviar arequisição,pegararespostaqueseráumamensagemindicandoqueoprodutofoiremovidoecolocaressamensagemlogoacimadalistagemdosprodutos.

Primeiramente, precisamos importar o jQuery na listagem de produtos, o arquivo WEB-

INF/jsp/produto/lista.jsp.Podemosfazerissoatravésadicionandoatag<head>importandoumarquivoJavascript,comoaseguir:

<%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%><html><head><scripttype="text/javascript"src="/controle-produtos/js/jquery.js"></script></head><body><!--continuaçãodapagina-->

Podemos alterar o link para disparar um evento ao ser clicado, e nãomais chamar umaURL.Onosso link não nos enviará para lugar nenhum, serámais um artifício visual para exibi-lo como tal,portanto,oseuatributohrefficarácomovalor#.Adicionaremostambémaolinkumeventodotipoonclickque faráumachamadaà funçãoremoveProdutoqueprecisarádoid doproduto, parasaberquemseráremovido:

<td><ahref="#"onclick="returnremoveProduto(${produto.id})">Remover</a></td>

Precisamos implementar anossa funçãoremoveProduto(). Para isso, dentro do body da nossapáginavamoscolocarafunçãoquereceberáoidparaenviararequisiçãoparaalógicadeexclusão.Arespostageradaporessalógica,nósvamoscolocaremumadivcujoidsechamarámensagem:

<scripttype="text/javascript">functionremoveProduto(id){$('#mensagem').load('/controle-produtos/produto/remove?produto.id='+id);}</script>

No jQuery a# serve para especificar qual elemento você deseja trabalhar através doid desseelemento.Vamoscriaradivantesdatabeladalistagemdosprodutos:

<html><head><scripttype="text/javascript"src="/controle-produtos/js/jquery.js"></script>

.

Page 269: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

</head><body><h1>Produtos</h1><divid="mensagem"></div><!--tabelaparamostraralistadosprodutos-->

Nossa remoção aindanão funcionará do jeito que queremos, pois, a resposta gerada está sendo aprópria página da listagem e não uma mensagem de confirmação. Isso tudo acontece devido aoredirecionamento que colocamos na lógica para a remoção. Vamos retirar o redirecionamento ecriarmosum.jspparamostraramensagemdeconfirmaçãodaexclusão.

OmétodoremovedoProdutoControllerdeverápossuirapenasocódigodaremoção:

publicvoidremove(Produtoproduto){produtoDao.remove(produto);}

Evamoscriarumnovo.jsp que será chamadoapós a execuçãoda remoção.Criaremos elenodiretórioWEB-INF/jsp/produtocomonomeremove.jspeoseguinteconteúdo:

Produtoremovidocomsucesso

Porfim,oúltimopassoqueprecisamosfazeréremoverdatabelaoprodutoquefoiexcluído.MaisumavezutilizaremosojQueryparanosauxiliar.Vamosprecisaridentificarquallinhavamosremoverdatabela.Paraisso,todasaslinhas(tr)terãoumaidentificaçãoúnicaqueserácompostopeloiddecadaprodutoprecedidapelapalavra"produto",porexemplo,produto1,produto2eassimpordiante.

<c:forEachvar="produto"items="${produtoList}"><trid="produto${produto.id}"><td>${produto.nome}</td><td>${produto.preco}</td><td>${produto.descricao}</td><td><fmt:formatDatepattern="dd/MM/yyyy"value="${produto.dataInicioVenda.time}"/></td><td><ahref="#"onclick="returnremoveProduto(${produto.id})">Remover</a></td></tr></c:forEach>

EmnossafunçãoJavascriptpararemoveroproduto,podemostambémremoveralinhadatabela:

$('#produto'+id).remove();

Vale lembrar que a forma que apresentamos é apenas uma das formas de fazer, existemmuitasoutrasformasdiferentesdeseatingiromesmocomportamento.

1.

17.21 EXERCÍCIOS OPCIONAIS: ADICIONANDO AJAX NA NOSSAAPLICAÇÃO

.

Page 270: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Nalista.jspnodiretórioWEB-INF/jsp/produto,façaaimportaçãodojQuery:

<%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%><html><head><scripttype="text/javascript"src="<c:urlvalue="/js/jquery.js"/>"></script></head><body><!--continuaçãodapagina-->

AltereoslinksparachamarumafunçãochamadaremoveProduto:

<td><ahref="#"onclick="returnremoveProduto(${produto.id})">Remover</a></td>

Vamos criar a nossa função que executará o AJAX e removerá o item da lista. Adicione asseguinteslinhasdentrodobodydasuapáginalista.jsp:

<!--iniciodapaginaeimportdojavascript--><body><scripttype="text/javascript">functionremoveProduto(id){$('#mensagem').load('<c:urlvalue="/produto/remove"/>'+'?produto.id='+id);$('#produto'+id).remove();}</script>

<!--continuaçãodapagina--></body>

Adicione uma div na sua página com o id mensagem, aonde será colocada a respostadevolvidapeloservidor:

<h1>Produtos</h1><divid="mensagem"></div><!--tabelaparamostraralistadosprodutos-->

Dêumidparaos<tr>,dessaformavocêpoderáapagá-los:

<trid="produto${produto.id}">

Remova o redirecionamento dométodoremove doProdutoController, de forma que elefiquecomoaseguir:

publicvoidremove(Produtoproduto){produtoDao.remove(produto);}

Por fim, crie no diretório WEB-INF/jsp/produto o arquivo remove.jsp com o seguinteconteúdo:

.

Page 271: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Produtoremovidocomsucesso

Acessenovamente a listagemdosprodutos e faça a remoçãodeles.Percebaque apáginanão érecarregadaquandovocêclicanolink.

.

Page 272: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO18

"Novepessoasnãofazemumbebêem1mês"--FredBrooks

OJavaEE,desde seu lançamento,éconsideradoumamaneiradedesenvolvermosaplicativos Javacom suporte a escalabilidade, flexibilidade e segurança.Em suaúltima versão, a 6, umdosprincipaisfocosfoisimplificarefacilitaracodificaçãodeaplicativosporpartedosdesenvolvedores.

Lançadaoficialmentenodia 10dedezembrode2009, anova especificação JavaEE6 foi liberadaparadownload juntamentecomoGlassfishv3,queéasua implementaçãodereferência.OJavaEE6vem com mudanças significativas que foram em parte baseadas na grande comunidade dedesenvolvedoresJava,equevisamfacilitardeverdadeousodasprincipaistecnologiasdoJavaEE.

Um dos principais problemas da antiga especificação Java EE era que, namaioria das vezes quedesenvolvíamosalgumaplicativo,nãoeranecessáriofazerusodetodasastecnologiasdisponíveisnela.Mesmo usando apenas parte dessas tecnologias, tínhamos que um lidar com todo o restante detecnologias da especificação. Por exemplo, quando desenvolvemosWeb Services, precisamos utilizarapenasasespecificaçõesJAX-WSeJAXB,masprecisamoslidarcomtodoorestantedasespecificaçõesmesmosemprecisarmosdelas.

Pararesolveresseproblema,noJavaEE6foiintroduzidooconceitodeprofiles.UmprofileéumaconfiguraçãoondepodemoscriarumsubconjuntodetecnologiaspresentesnasespecificaçõesJavaEE6ouatémesmoadicionarnovastecnologiasdefinidaspelaJCP(JavaCommunityProcess)quenãofazempartedaespecificação.AprópriaespecificaçãoJavaEEjáincluiuumprofilechamadoWebProfile.

OWebProfilereúneapenasastecnologiasusadaspelamaioriadosdesenvolvedoresWeb.Elaincluias principais tecnologias vista durante este curso (Servlets, JSP, JSTL) e outras tecnologias como, porexemplo,JPAeJSFquepodemservistasnocursoFJ-26daCaelum.

NoJavaEE5,foramfeitasmudançasquejáfacilitarammuitoavidadodesenvolvedor,como,porexemplo,ousodePOJOs(PlainOldJavaObject)eanotaçõesepreterindoousodeXML'scomoformade configuração. Além da criação da JPA (Java Persistence API) para facilitar omapeamento objetorelacionalemnossasaplicaçõescujaprincipalimplementaçãoéofamosoHibernate.

Seguindo a onda de melhorias, o Java EE 6 introduziu melhorias em praticamente todas as

APÊNDICE-JAVAEE6

18.1JAVAEE6EASNOVIDADES

.

Page 273: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

tecnologiasenvolvidasnodesenvolvimentodeaplicativosenterpriseouWeb.Porexemplo:

DI(DependencyInjection)-Usaranotaçõesparacriarmosclassesquepodemserinjetadascomodependênciaemoutrasclasses;

JPA2.0-MelhoriasnaJavaPersistenceQueryLanguageeanovaAPIdeCriteria;

EJB3.1-FacilidadesnodesenvolvimentodeEnterpriseJavaBeansusandoanovaAPIdeEJB3.1;

BeanValidation-ValidarnossosPOJOsdemaneirafácilutilizandoanotações;

JAX-RS-EspecificaçãosobrecomocriarWebServicesdemaneiraRESTful.

Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.

CasadoCódigo,ebookcompreçodeebook.

Muitasvezesemnossasaplicaçõestemosalgunsservletsque,parafinalizaremaescritadarespostaaocliente,dependemderecursosexternoscomo,porexemplo,umaconexãoJDBC,umWebServiceouuma mensagem JMS. Esses são exemplos de recurso que não temos controle quanto ao tempo deresposta.

NãotínhamosmuitasaídaanãoseresperarpelorecursoparaquenossoServlet terminassesuaexecução.Porém,essasoluçãonuncafoiamaisapropriada,poisbloqueávamosumathreadqueestavaàesperadeumrecursointermitente.

Na nova API de Servlets 3.0, esse problema foi resolvido. Podemos processar nossos servlets demaneiraassíncrona,demodoqueathreadnãoficamaisàesperaderecursos.Athreadéliberadaparaexecutaroutrastarefasemnossoservidordeaplicação.

Quando o recurso que estávamos esperando se torna disponível, outra thread pode escrever aresposta e enviá-la ao cliente ou podemos, como foi visto durante o curso e vimos que é uma ótima

EditoraCasadoCódigocomlivrosdeumaformadiferente

18.2PROCESSAMENTOASSÍNCRONO

.

Page 274: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

prática,delegaraescritadarespostaparaoutrastecnologiascomoJSP.

Tantoservletsquantofiltrospodemserescritosdemaneiraassíncrona.Paraisso,bastacolocarmosoatributoasyncSupportedcomotruenasanotações@[email protected] vemosumexemplodecomofazernossoservlettersuporteàrequisiçõesassíncronas:

@WebServlet(asyncSupported=true,urlPatterns={"/adiciona/contato"})publicclassAdicionaContatoServletextendsHttpServlet{publicvoiddoGet(HttpServletRequestreq,HttpServletResponseres){//AguardandoconexãoJDBCContatoDaodao=newContatoDao();}}

Noexemploacima,habilitamossuporteassíncronoemnossaservlet,porémaindanãotornamosocódigo realmente assíncrono. Na interface javax.servlet.ServletRequest , temos um métodochamadostartAsyncquerecebecomoparâmetrosoServletRequesteoServletResponsequerecebemos em nosso servlet. Uma chamada a estemétodo torna a requisição assíncrona. Agora simtornamosnossocódigoassíncrono:

@WebServlet(asyncSupported=true,urlPatterns={"/adiciona/contato"})publicclassAdicionaContatoServletextendsHttpServlet{publicvoiddoGet(HttpServletRequestreq,HttpServletResponseres){AsyncContextcontext=req.startAsync(req,res);

//AguardandoconexãoJDBCContatoDaodao=newContatoDao();}}

Note que, ao fazer uma chamada ao método startAsync , é retornado um objeto do tipo AsyncContext . Esse objeto guarda os objetos request e response passados ao métodostartAsync.Apartirdessachamadademétodo,athreadquetratavanossarequisiçãofoiliberadaparaexecutaroutrastarefas.NaclasseAsyncContext,temosométodocompleteparaconfirmaroenviodarespostaaocliente.

@WebServlet(asyncSupported=true,urlPatterns={"/adiciona/contato"})publicclassAdicionaContatoServletextendsHttpServlet{publicvoiddoGet(HttpServletRequestreq,HttpServletResponseres){finalAsyncContextcontext=req.startAsync(req,res);finalPrintWriterout=res.getWriter();

context.addListener(newAsyncListener(){@OverridepublicvoidonComplete(AsyncEventevent)throwsIOException{out.println("<html>");out.println("Olámundo!");out.println("</html>");}});

//AguardandoconexãoJDBCContatoDaodao=newContatoDao();//Nossalogica

.

Page 275: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

//Lógicacompleta,chamalisteneronCompletecontext.complete();}}

TambémpodemosdelegaraescritadarespostaparaumJSPporexemplo.Nestecaso,faremosusodométododispatch:

@WebServlet(asyncSupported=true,urlPatterns={"/adiciona/contato"})publicclassAdicionaContatoServletextendsHttpServlet{publicvoiddoGet(HttpServletRequestreq,HttpServletResponseres){finalAsyncContextcontext=req.startAsync(req,res);

context.addListener(newAsyncListener(){@OverridepublicvoidonComplete(AsyncEventevent)throwsIOException{context.dispatch("/adicionado.jsp");}});

//AguardandoconexãoJDBCContatoDaodao=newContatoDao();//Nossalogica

//Lógicacompleta,chamalisteneronCompletecontext.complete();}}

ASYNCLISTENERESEUSOUTROSMÉTODOS

AclasseAsyncListener suporta outros eventos.Quando a chamada assíncrona excedeu otempo máximo que ela tinha para ser executada sobrescrevemos o método onTimeout. ParatratarmosumerropodemossobrescreverométodoonError.

PodemosprosseguirconfigurandonossaServletseFiltrosnoarquivoweb.xml.Paraconfigurarmosum servlet ou filtro como possivelmente assíncrono devemos especificar a tag <async-

supported>true</async-supported>nomapeamentodaservletoudofiltro.

ComacriaçãodasnovasanotaçõesdisponíveisnaAPIServlets3.0,ousodoweb.xmlnãoémaisobrigatório. O web.xml é usado quando desejamos sobrescrever algumas configurações definidas emnossasanotações.

PercebemosqueagrandeideiadanovaAPIdeServletsécriaramenorquantidadedeXMLpossívele colocar nossas configurações em anotações. Se pensarmos nos frameworks que utilizamos para nosauxiliarnodesenvolvimentoWeb,porexemplo,oVRaptorouoStruts,sabemosqueeleexigeque

18.3PLUGABILIDADEEWEBFRAGMENTS

.

Page 276: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

sejafeitaaconfiguraçãodeumfiltronoarquivoweb.xmldenossaaplicação.TemosumfatoquevaicontraaspremissasdanovaAPIdeServlets,queécriarumarquivoweb.xmlquandoomesmodeveriaseropcional.

Com o intuito de resolver esse problema, foi introduzido o conceito deweb fragment, que sãomódulosdeumweb.xml.Podemostervárioswebfragmentque,emconjunto,podemservistocomosefossemumweb.xmlcompleto.Oframeworkqueutilizamospodecriarseuprópriowebfragmente colocarnele todas as configurações que teríamosque fazermanualmente emnossoweb.xml. Porexemplo,nocasodoVRaptor teríamosaconfiguraçãodo filtroobrigatóriodoVRaptor dentrodopróprio framework. Com isso, seríamos poupados de termos que colocar qualquer configuração emnossa aplicação.Opróprio container conseguirábuscarpor essas configurações e aplicá-las emnossaaplicação.

Noweb fragment podemos adicionar quase todos os elementos que estão disponíveis para oarquivoweb.xml.Asúnicasrestriçõesquedevemosseguirsão:

Arquivodeveserchamadodeweb-fragment.xmlRoottagdoarquivodeveser<web-fragment>

NocasodoVRaptoroarquivoweb-fragment.xmlficariaassim:

<web-fragment><filter><filter-name>vraptor</filter-name><filter-class>br.com.caelum.vraptor.VRaptor</filter-class></filter><filter-mapping><filter-name>vraptor</filter-name><url-pattern>/*</url-pattern><dispatcher>FORWARD</dispatcher><dispatcher>REQUEST</dispatcher></filter-mapping></web-fragment>

DepreferênciaoframeworkqueutilizamosdevemcolocarseuswebfragmentsnapastaMETA-INFdoarquivo.jar,queestánormalmentelocalizadonapastaWEB-INF/libdanossaaplicação.

OVRaptor3.1jápossuiessaconfiguraçãodeServlets3.0pronta.

TAGMETADATA-COMPLETE

Neste caso se a tagmetadata-complete for setada comotrue o container não analisaráqualquerwebfragmentpresenteemnossaaplicação,atémesmooswebfragmentsdealgumframeworkqueutilizamos.

.

Page 277: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Essa funcionalidadepermitemodularizarmosnossoweb.xml. Podemos ter o tradicional arquivodescritorweb.xml,oupodemosmodularizá-loemumoumaiswebfragment.

Devido a essapossívelmodularização,pode ser importante aordememque esses fragmentos sãoprocessados.Porexemplo,aordememqueestes fragmentossãoprocessadospodealteraraordemdeexecuçãodosfiltrosemnossaaplicação.

Servlets 3.0 nos permite configurar a ordem que estes fragmentos são processados de maneiraabsoluta ou relativa. Se quisermos configurar nossos fragmentos para serem processados em ordemabsoluta, devemos colocar a tag <absolute-ordering> em nosso web.xml . Também podemosconfigurarumaordemrelativacolocandoatag<ordering>noarquivoweb-fragment.xml.

Nossosfragmentospodemteridentificadores,nomesqueosdiferenciam.Sendoassim,sequisermosconfigurar uma ordem absoluta para nossos fragmentos, teríamos a seguinte configuração em nossoweb.xml:

<web-app><name>MinhaAplicação</name><absolute-ordering><name>Fragmento1</name><name>Fragmento2</name></absolute-ordering></web-app>

Nocódigoacima,elesseriamprocessadosnaseguinteordem:

web.xml-SempreseráprocessadoprimeiroFragmento1Fragmento2

AAPIdeServlets3.0temumanovainterfacechamadaServletContainerInitializerquenospermiteplugar frameworksemnossaaplicação.Para isso,bastaqueo frameworkcrieumaclassequeimplementeestainterface.

Porexemplo,naimplementaçãodaAPIJAX-WS(WebServicesRESTful,quevemosnocursoFJ-31)seriacriadoumaclassequeimplementeestainterface:

@HandlesTypes(WebService.class)publicclassJAXWSServletContainerInitializerimplementsServletContainerInitializer{publicvoidonStartup(Set<Class<?>>c,ServletContextctx)throwsServletException{ServletRegistrationreg=ctx.addServlet("JAXWSServlet","com.sun.webservice.JAXWSServlet");reg.addServletMapping("/jaxws");}}

Osframeworksqueimplementamestainterfacedevemcolocá-lasnapastaMETA-INF/servicesem

.

Page 278: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

um arquivo chamado javax.servlet.ServletContainerInitializer que faça referência para aclasse de implementação. Quando nosso container for iniciado, ele vai procurar por essasimplementaçõesquandoeleforiniciado.

A anotação @HandlesTypes serve para especificar quais classes podem ser manipuladas pelaimplementaçãodeServletContainerInitializer

NanovaAPIdeServlets3.0temosapossibilidadedeadicionarumservletemnossaaplicaçãode3maneiras.Duasdelasjáforamvistasduranteestecapítulo(XMLeanotações).Aterceiradelaspodeserfeitadeumamaneiraprogramáticaoudinâmica.

Dentro do Java EE podemos classificar os objetos principais que habitam nossa aplicação em 3escopos.Oescopoderequisiçãoquetemumaduraçãocurta,oescopodesessãoqueémuitoutilizadoquandoqueremosguardarinformaçõesreferentesaalgumusuárioespecíficoeoterceirodelesquenãoabordamosduranteocursoqueéoescopodeaplicação.

Sãoobjetosquepermanecememmemóriadesdeomomentoquenossa aplicaçãoé iniciadaatéomomento que amesma é finalizada.Os servidores de aplicação nos fornecem um objeto que é umaimplementaçãodainterfaceServletContextqueéumobjetodeescopodeaplicação.

Comesseobjetopodemosfazercoisasrelativasaaplicação,comoporexemplo,fazerlogsdeacesso,criaratributosquepodemsercompartilhadosportodaaaplicação,etc.

A interface ServletContext nos fornece algunsmétodos adicionais que nos permitem fazer oregistrodinâmicodeservletsefiltros.Aúnicarestriçãoparachamarmosessesmétodoséquedevemosfazerissonomomentoemquenossaaplicaçãoestásendoiniciadaemnossoservidordeaplicação.

Podemosfazerissodeduasmaneirasdistintas.Aprimeiradelaseamaisconhecida,seriacriarmosum listener do tipo ServletContextListener e adicionarmos o servlet no métodocontextInitializedcomonocódigoabaixo:

publicclassServletListenerimplementsServletContextListener{publicvoidcontextInitialized(ServletContextEventevent){ServletContextcontext=event.getServletContext();context.addServlet("MeuServlet",MeuServlet.class);}

publicvoidcontextDestroyed(ServletContextEventevent){

}}

Paraadicionarmosumfiltro,faríamosalgobemsimilar:sómudaríamosachamadadeaddServletparaaddFilterepassaríamoscomoparâmetroofiltroquedesejamosadicionar.

18.4REGISTRODINÂMICODESERVLETS

.

Page 279: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

A outra maneira de fazermos isso, seria criarmos uma implementação deServletContainerInitializerenométodoonStartup.Porexemplo:

publicclassMeuServletContainerInitializerimplementsServletContainerInitializer{publicvoidonStartup(Set<Class<?>>c,ServletContextcontext)throwsServletException{ServletRegistrationreg=context.addServlet("MeuServlet",MeuServlet.class);reg.addServletMapping("/jaxws");}}

Estesegundoexemploseriamaisusadosefossemosdistribuirnossaaplicaçãocomoumframeworkenosbeneficiarmosdaplugabilidadecomofoivistonaseçãoanterior.

AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,

Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex-aluno daCaelumtem15%dedescontonestelink!

ConheçaoscursosonlineAlura.

JáconheceoscursosonlineAlura?

.

Page 280: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

CAPÍTULO19

"Measuringprogrammingprogressbylinesofcodeislikemeasuringaircraftbuildingprogressbyweight."--BillGates

EstecapítuloabordaváriosoutrospequenosassuntosdaServletAPIaindanãotratados,muitosdelesimportantesparaacertificaçãoSCWCD.

Podemosconfigurarnoweb.xmlalgunsparâmetrosquedepoisvamosleremnossaaplicação.Umaforma é passarmos parâmetros especificamente para uma Servlet ou um filtro usando a tag <init-param>comonosexemplosabaixo:

<!--emservlet--><servlet><servlet-name>MinhaServlet</servlet-name><servlet-class>pacote.MinhaServlet</servlet-class><init-param><param-name>nome</param-name><param-value>valor</param-value></init-param></servlet>

<!--emfilter--><filter><filter-name>MeuFiltro</filter-name><filter-class>pacote.MeuFiltro</filter-class><init-param><param-name>nome</param-name><param-value>valor</param-value></init-param></filter>

Podemos, inclusive, ter vários parâmetros namesma servlet ou filtro. Depois, no código Java daServletoudofiltroespecífico,podemosrecuperaressesparâmetrosusando:

//emservletStringvalor=getServletConfig().getInitParameter("nome");

//emfiltro,noinitStringvalor=filterConfig.getInitParameter("nome")

Outra possibilidade é configurar parâmetros para o contexto inteiro e não apenas uma servletespecífica.Podemosfazerissocomatag<context-param>,comoabaixo:

APÊNDICE-TÓPICOSDASERVLETAPI

19.1INIT-PARAMSECONTEXT-PARAMS

.

Page 281: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

<context-param><param-name>nome</param-name><param-value>param</param-value></context-param>

E,nocódigoJavadeumaServlet,porexemplo:

Stringvalor=getServletContext().getInitParameter("nome");

Muitos frameworks usam parâmetros no web.xml para configurar. O VRaptor e o Spring sãoexemplosdeusodesse recurso.Maspodemosusar isso emnossas aplicações tambémpara retirardocódigoJavacertasconfiguraçõesparametrizáveis.

Editorastradicionaispoucoligamparaebooksenovastecnologias.Nãodominamtecnicamente o assunto para revisar os livros a fundo. Não têm anos deexperiênciaemdidáticascomcursos.ConheçaaCasadoCódigo,umaeditoradiferente,comcuradoriadaCaelum eobsessãoporlivrosdequalidadeapreçosjustos.

CasadoCódigo,ebookcompreçodeebook.

Épossívelconfigurarnoweb.xmlqualarquivodeveserchamadoquandoalguémacessarumaURLraiznoservidor,comoporexemplo:

http://localhost:8080/fj-21-agenda/http://localhost:8080/fj-21-agenda/uma-pasta/

Sãoosarquivos indexquenormalmenteusamosemoutrasplataformas.MasnoJavaEEpodemoslistar os nomes de arquivos que desejamos que sejam oswelcome files. Basta defini-los no XML e oservidorvaitentá-losnaordemdedeclaração:

<welcome-file-list><welcome-file>index.html</welcome-file><welcome-file>index.jsp</welcome-file><welcome-file>default.html</welcome-file><welcome-file>default.jsp</welcome-file></welcome-file-list>

EditoraCasadoCódigocomlivrosdeumaformadiferente

19.2WELCOME-FILE-LIST

19.3PROPRIEDADESDEPÁGINASJSP

.

Page 282: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Comodizerqualoencodingdenossosarquivosjspdeumamaneiraglobal?Comonosprotegerdeprogramadores iniciantes em nossa equipe e desabilitar o código scriptlet? Como adicionar umarquivo antes e/ou depois de todos os arquivos JSPs? Ou de todos os JSPs dentro de determinadodiretório?

Pararesponderessaseoutrasperguntas,aAPIde jspresolveupossibilitardefiniralgumastagsnonossoarquivoweb.xml.

Porexemplo,paradesativarscripting(osscriptlets):

<scripting-invalid>true</scripting-invalid>

Ativarexpressionlanguage(quejávemativado):

<el-ignored>false</el-ignored>

Determinaroencodingdosarquivosdeumamaneiragenérica:

<page-encoding>UTF-8</page-encoding>

IncluirarquivosestaticamenteantesedepoisdeseusJSPs:

<include-prelude>/antes.jspf</include-prelude><include-coda>/depois.jspf</include-coda>

OcódigoaseguirmostracomoaplicartaiscaracterísticasparatodososJSPs,reparequeatagurl-patterndeterminaogrupodearquivoscujosatributosserãoalterados:

<jsp-config><jsp-property-group><display-name>todososjsps</display-name><description>configuracoesdetodososjsps</description><url-pattern>*.jsp</url-pattern><page-encoding>UTF-8</page-encoding><scripting-invalid>true</scripting-invalid><el-ignored>false</el-ignored><include-prelude>/antes.jspf</include-prelude><include-coda>/depois.jspf</include-coda></jsp-property-group></jsp-config>

ExisteumamaneiraemumarquivoJSPdeincluirumoutroarquivoestaticamente.Istofazcomqueo arquivo a ser incluído seja literalmente copiado e colado dentro do seu arquivo antes da primeirainterpretação(compilação)doseujsp.

A vantagem é que como a inclusão é feita uma única vez antes do arquivo ser compilado, essainclusão é extremamente rápida, porém vale lembrar que o arquivo incluído pode ou não funcionarseparadamente.

<%@includefile="outra_pagina.jsp"%>

19.4INCLUSÃOESTÁTICADEARQUIVOS

.

Page 283: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

AAlura oferece centenasdecursosonline em suaplataforma exclusivadeensinoquefavoreceoaprendizadocomaqualidadereconhecidadaCaelum.VocêpodeescolherumcursonasáreasdeProgramação,Front-end,Mobile,

Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex-aluno daCaelumtem15%dedescontonestelink!

ConheçaoscursosonlineAlura.

Como tratarpossíveis exceptions emnossapágina JSP?Nossos exercíciosde listagemde contatostantocomscriptletsquantocomJSTLusamoContatoDaoquepodelançarumaexceçãoseobancodedadosestiverforadoar,porexemplo.Comotratar?

SenossoJSPéumimensoscriptletdecódigoJava,otratamentoéomesmodecódigosJavanormais:trycatch:

<html><%try{ContatoDaodao=newContatoDao();//...etc...}catch(Exceptionex){%>Ocorreualgumerroaoacessarobancodedados.<%}%></html>

Nãoparecemuitoelegante.Masequandousamostags,háumaformamelhor?Poderíamosusaratagc:catch,comomesmotipodeproblemadasoluçãoanterior:

<c:catchvar="error"><jsp:useBeanid="dao"class="br.com.caelum.jdbc.dao.ContatoDao"/><c:forEachvar="contato"items="${dao.lista}">....</c:forEach></c:catch><c:iftest="${notemptyerror}">Ocorreualgumerroaoacessarobancodedados.</c:if>

ReparequeaprópriaJSTLnosapresentaumasoluçãoquenãosemostraboaparaessetipodeerro

JáconheceoscursosonlineAlura?

19.5TRATAMENTODEERROEMJSP

.

Page 284: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

quequeremostratar.Éimportantedeixarclaroquedesejamostratarotipodeerroquenãotemvolta,devemosmostrarumamensagemdeerroparaoclienteepronto,porexemploquandoaconexãocomobancocaiouquandoocorrealgumerronoservidor.

Quando estávamos trabalhando comServlets, havia uma solução simples e elegante: não tratar asexceçõesde forma espalhadamas simcriarumapágina centralizadade tratamentode erros.Naquelecaso,conseguimosissocomo<error-page>.

ComJSPs,conseguimosomesmoresultadomassemXML.UsamosumadiretivanotopodoJSPqueindicaqualéapáginacentraldetratamentodeerro.Enessecasonãoprecisamosnemdetry/catchnemde<c:catch>:

<%@pageerrorPage="/erro.html"%>...<jsp:useBeanid="dao"class="br.com.caelum.jdbc.dao.ContatoDao"/>...

ParalertodososparâmetrosdorequestbastaacessarométodogetParameterMapdorequest.

Map<String,Object>parametros=request.getParameterMap();for(Stringparametro:parametros.keySet()){//facaalgocomoparametro}

Àsvezesnãoésimples trabalharcomlinkspois temosquepensarnaURLqueoclienteacessaaovisualizaranossapágina.

AJSTLresolveesseproblema:supondoqueasuaaplicaçãosechamejspteste,ocódigoabaixogeraastring/jspteste/imagem/banner.jpg.

<c:urlvalue="/imagem/banner.jpg"/>

Ébastanteútilaomontarmenusúnicosincluídosemváriaspáginasequeprecisamlidarcomlinksabsolutos.

19.6DESCOBRINDOTODOSOSPARÂMETROSDOREQUEST

19.7TRABALHANDOCOMLINKSCOMAC:URL

.

Page 285: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Querendoaprenderaindamaissobre?Esclarecerdúvidasdosexercícios?Ouvirexplicaçõesdetalhadascomuminstrutor?ACaelum oferece o cursoFJ-21 presencial nas cidades de São Paulo, Rio deJaneiroeBrasília,alémdeturmasincompany.

ConsulteasvantagensdocursoJavaparaDesenvolvimentoWeb

SabemosquepodemosexecutarcódigonomomentoqueumaServletouumfiltrosãoinicializadosatravésdosmétodosinitdecadaumdeles.MasesequisermosexecutaralgonoiníciodaaplicaçãoWeb(docontextoWeb),independentedetermosounãoServletefiltrosedonúmerodeles?

Paraissoexistemoscontextlisteners.VocêpodeescreverumaclasseJavacommétodosqueserãochamados automaticamente no momento que seu contexto for iniciado e depois desligado. Bastaimplementar a interface ServletContextListener e usar a tag <listener> no web.xml paraconfigurá-la.

Porexemplo:

publicclassMeuListenerimplementsServletContextAttributeListener{publicvoidcontextInitialized(ServletContextEventevent){System.out.println("Contextoiniciado...");}

publicvoidcontextDestroyed(ServletContextEventevent){System.out.println("Contextodesligado...");}}

EdepoisnoXML:

<listener><listener-class>pacote.MeuListener</listener-class></listener>

AsaplicaçõesWebemJavatêm3escopospossíveis.Jávimoseusamosdoisdeles:oderequesteodesessão. Podemos colocar um atributo no request com request.setAttribute(..,..) e ele estarádisponívelparatodoorequest(desdeaActionatéoJSP,osfiltrosetc).

VocêpodetambémfazerocursoFJ-21dessaapostilanaCaelum

19.8CONTEXTLISTENER

19.9OSERVLETCONTEXTEOESCOPODEAPLICAÇÃO

.

Page 286: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

Da mesma forma, podemos pegar a HttpSession e colocar um atributo comsession.setAttribute(..,..) e ela estará disponível na sessão daquele usuário através de váriosrequests.

Oterceiroescopoéumescopoglobal,ondeosobjetossãocompartilhadosnaaplicaçãointeira,portodos os usuários em todos os requests. É o chamado escopo de aplicação, acessível peloServletContext.

Podemos,emumaServlet,setaralgumatributousando:

getServletContext().setAttribute("nomeGlobal","valor");

Depois,podemosrecuperaressevalorcom:

Objectvalor=getServletContext().getAttribute("nomeGlobal");

Umbomusoécompartilharconfiguraçõesglobaisdaaplicação,comoporexemplousuárioesenhadeumbancodedados,oualgumobjetodecachecompartilhadoetc.Vocêpode,porexemplo,inicializaralgum objeto global usando um ServletContextListener e depois disponibilizá-lo noServletContextparaorestodaaplicaçãoacessar.

EcomofazemosparaacessaroescopodeaplicaçãononossoJSP?Simples,umadasvariáveisquejáexisteemumJSPsechamaapplication,algocomo:

ServletContextapplication=getServletContext();

Portantopodemosutilizá-laatravésdescriptlet:

<%=application.getAttribute("nomeGlobal")%><br/>

Como já vimos anteriormente, o código do tipo scriptlet pode sermaléfico para nossa aplicação,sendoassimvamosutilizarExpressionLanguageparaacessarumatributodoescopoaplicação:

AcessandocomEL:${nomeGlobal}<br/>

ReparequeaExpressionLanguageprocurarátalatributonãosónoescopodoapplication,comoveremosmaisafrente.Paradeixarclaroquevocêprocuraumavariáveldoescopodeaplicação,usamosavariávelimplícitachamadaapplicationScope:

Acessandoescopoapplication:${applicationScope['nomeGlobal']}<br/>

MÉTODOSNOSERVLETCONTEXT

AlémdacaracterísticadeescopoglobalcomosmétodosgetAttribute esetAttribute,outrosmétodosúteisexistemnaServletContext.ConsulteoJavadocparamaisinformações.

.

Page 287: uso comercial deste material, por favor, consulte a Caelum … · 9 MVC - Model View Controller 9.1 Servlet ou JSP? 114 9.2 Request Dispatcher 116 9.3 Exercícios: RequestDispatcher

HáaindaoutroslistenersdisponíveisnaAPIdeServletsparacapturaroutrostiposdeeventos:

HttpSessionListener - provê métodos que executam quando uma sessão é criada(sessionCreated),destruída(sessionDestroyed);

ServletContextAttributeListener-permitedescobrirquandoatributossãomanipuladosno ServletContext com os métodos attributeAdded , attributeRemoved eattributeReplaced;

ServletRequestAttributeListener - tem os mesmos métodos que o ServletContextAttributeListener mas executa quando os atributos do request sãomanipulados;

HttpSessionAttributeListener - tem os mesmos métodos que oServletContextAttributeListener mas executa quando os atributos da HttpSession sãomanipulados;

ServletRequestListener - permite executar códigos nosmomentos que um request chega equandoeleacabadeserprocessado(métodosrequestDestroyederequestInitialized);

Outrosmenosusados:HttpSessionActivationListenereHttpSessionBindingListener.

Aconfiguraçãodequalquerumdesseslistenerséfeitacomatag<listener>comovimosacima.Épossível inclusive que uma mesma classe implemente várias das interfaces de listeners mas sejaconfiguradaapenasumavezoweb.xml.

Conheça a Casa do Código, uma nova editora, com autores de destaque nomercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntosatuais.Com a curadoria daCaelum e excelentes autores, é uma abordagemdiferenteparalivrosdetecnologianoBrasil.

CasadoCódigo,LivrosdeTecnologia.

19.10OUTROSLISTENERS

Seuslivrosdetecnologiaparecemdoséculopassado?

.