Documente Academic
Documente Profesional
Documente Cultură
4 de setembro de 2012
Sumrio Sobre a K19 Seguro Treinamento Termo de Uso Cursos 1 Banco de dados 1.1 Sistemas Gerenciadores de Banco de Dados . . 1.2 MySQL Server . . . . . . . . . . . . . . . . . . . 1.3 Bases de dados (Databases) . . . . . . . . . . . 1.4 Criando uma base de dados no MySQL Server 1.5 Tabelas . . . . . . . . . . . . . . . . . . . . . . . 1.6 Criando tabelas no MySQL Server . . . . . . . . 1.7 Operaes Bsicas . . . . . . . . . . . . . . . . . 1.8 Chaves Primria e Estrangeira . . . . . . . . . . 1.9 Exerccios de Fixao . . . . . . . . . . . . . . . 1.10 Exerccios Complementares . . . . . . . . . . . JDBC 2.1 Driver . . . . . . . . . . . . . . . . . . . . . . 2.2 JDBC . . . . . . . . . . . . . . . . . . . . . . . 2.3 Instalando o Driver JDBC do MySQL Server 2.4 Criando uma conexo . . . . . . . . . . . . . 2.5 Inserindo registros . . . . . . . . . . . . . . . 2.6 Exerccios de Fixao . . . . . . . . . . . . . 2.7 Exerccios Complementares . . . . . . . . . 2.8 SQL Injection . . . . . . . . . . . . . . . . . . 2.9 Exerccios de Fixao . . . . . . . . . . . . . 2.10 Exerccios Complementares . . . . . . . . . 2.11 Listando registros . . . . . . . . . . . . . . .
www.facebook.com/k19treinamentos
i 1 2 3 4 1 1 2 2 2 3 3 4 5 5 9 25 26 27 28 28 29 29 31 31 32 33 33
i
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
S UMRIO
ii
Exerccios de Fixao . . . . Exerccios Complementares Connection Factory . . . . . Exerccios de Fixao . . . . Exerccios Complementares Desaos . . . . . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
34 35 35 36 37 38 39 39 39 40 41 41 42 42 44 44 46 48 49 50 53 53 55 55 55 56 57 57 57 58 58 61 61 61 62 63 63 67 69 75 75 75 76 76 78 79
JPA 2 e Hibernate 3.1 Mltiplas sintaxes da linguagem SQL . . . . 3.2 Orientao a Objetos VS Modelo Relacional 3.3 Ferramentas ORM . . . . . . . . . . . . . . . 3.4 O que JPA e Hibernate? . . . . . . . . . . . 3.5 Bibliotecas . . . . . . . . . . . . . . . . . . . 3.6 Congurao . . . . . . . . . . . . . . . . . . 3.7 Mapeamento . . . . . . . . . . . . . . . . . . 3.8 Gerando Tabelas . . . . . . . . . . . . . . . . 3.9 Exerccios de Fixao . . . . . . . . . . . . . 3.10 Manipulando entidades . . . . . . . . . . . 3.11 Exerccios de Fixao . . . . . . . . . . . . . 3.12 Repository . . . . . . . . . . . . . . . . . . . 3.13 Exerccios de Fixao . . . . . . . . . . . . . Web Container 4.1 Necessidades de uma aplicao web 4.2 Web Container . . . . . . . . . . . . . 4.3 Servlet e Java EE . . . . . . . . . . . . 4.4 Exerccios de Fixao . . . . . . . . . 4.5 Aplicao Web Java . . . . . . . . . . 4.6 Exerccios de Fixao . . . . . . . . . 4.7 Processando requisies . . . . . . . 4.8 Servlet . . . . . . . . . . . . . . . . . . 4.9 Exerccios de Fixao . . . . . . . . . 4.10 Frameworks . . . . . . . . . . . . . . Viso Geral do Struts 2 5.1 MVC e Front Controller . . . . . . . . 5.2 Bibliotecas . . . . . . . . . . . . . . . 5.3 Congurando uma aplicao Struts 5.4 Logging . . . . . . . . . . . . . . . . . 5.5 Actions . . . . . . . . . . . . . . . . . 5.6 Exemplo Prtico . . . . . . . . . . . . 5.7 Exerccios de Fixao . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
Integrao Struts e JPA 6.1 Bibliotecas . . . . . . . . . . . . . . . . . . . . 6.2 Congurao . . . . . . . . . . . . . . . . . . . 6.3 Mapeamento . . . . . . . . . . . . . . . . . . . 6.4 Inicializao e Finalizao . . . . . . . . . . . 6.5 Transaes . . . . . . . . . . . . . . . . . . . . 6.6 Recuperando o EntityManager da Requisio
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
ii
www.k19.com.br
iii
S UMRIO
6.7 7
Exerccios de Fixao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
79
Autenticao 85 7.1 Exerccios de Fixao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 Pginas de Erro 91 8.1 Exerccios de Fixao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 CRUD 95 9.1 Exerccios de Fixao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
www.facebook.com/k19treinamentos
iii
S UMRIO
iv
iv
www.k19.com.br
S UMRIO
Sobre a K19
A K19 uma empresa especializada na capacitao de desenvolvedores de software. Sua equipe composta por prossionais formados em Cincia da Computao pela Universidade de So Paulo (USP) e que possuem vasta experincia em treinamento de prossionais para rea de TI. O principal objetivo da K19 oferecer treinamentos de mxima qualidade e relacionados s principais tecnologias utilizadas pelas empresas. Atravs desses treinamentos, seus alunos se tornam capacitados para atuar no mercado de trabalho. Visando a mxima qualidade, a K19 mantm as suas apostilas em constante renovao e melhoria, oferece instalaes fsicas apropriadas para o ensino e seus instrutores esto sempre atualizados didtica e tecnicamente.
www.facebook.com/k19treinamentos
S UMRIO
Seguro Treinamento
Na K19 o aluno faz o curso quantas vezes quiser! Comprometida com o aprendizado e com a satisfao dos seus alunos, a K19 a nica que possui o Seguro Treinamento. Ao contratar um curso, o aluno poder refaz-lo quantas vezes desejar mediante a disponibilidade de vagas e pagamento da franquia do Seguro Treinamento. As vagas no preenchidas at um dia antes do incio de uma turma da K19 sero destinadas ao alunos que desejam utilizar o Seguro Treinamento. O valor da franquia para utilizar o Seguro Treinamento 10% do valor total do curso.
www.k19.com.br
S UMRIO
Termo de Uso
Termo de Uso
Todo o contedo desta apostila propriedade da K19 Treinamentos. A apostila pode ser utilizada livremente para estudo pessoal . Alm disso, este material didtico pode ser utilizado como material de apoio em cursos de ensino superior desde que a instituio correspondente seja reconhecida pelo MEC (Ministrio da Educao) e que a K19 seja citada explicitamente como proprietria do material. proibida qualquer utilizao desse material que no se enquadre nas condies acima sem o prvio consentimento formal, por escrito, da K19 Treinamentos. O uso indevido est sujeito s medidas legais cabveis.
www.facebook.com/k19treinamentos
S UMRIO
TR
www.k19.com.br/cursos
www.k19.com.br
CAPTULO
B ANCO DE DADOS
Em geral, as aplicaes necessitam armazenar dados de forma persistente para consult-los posteriormente. Por exemplo, a aplicao de uma livraria precisa armazenar os dados dos livros e dos autores de forma persistente. Suponha que esses dados sejam armazenados em arquivos do sistema operacional. Vrios fatores importantes nos levam a descartar tal opo. A seguir, apresentamos as principais diculdades a serem consideradas na persistncia de dados.
Segurana: O acesso s informaes potencialmente condenciais deve ser controlado de forma que apenas usurios e sistemas autorizados possam manipul-las. Integridade: Restries relacionadas aos dados armazenados devem ser respeitadas para que as informaes estejam sempre consistentes. Consulta: O tempo gasto para realizar as consultas aos dados armazenados deve ser o menor possvel. Concorrncia: Em geral, diversos sistemas e usurios acessaro concorrentemente as informaes armazenadas. Apesar disso, a integridade dos dados deve ser preservada.
Considerando todos esses aspectos, conclumos que um sistema complexo seria necessrio para persistir as informaes de uma aplicao de maneira adequada. Felizmente, tal tipo de sistema j existe e conhecido como Sistema Gerenciador de Banco de Dados (SGBD).
B ANCO DE DADOS
MySQL Server
Neste treinamento, utilizaremos o MySQL Server, que mantido pela Oracle e amplamente utilizado em aplicaes comerciais. Para instalar o MySQL Server, voc pode utilizar o artigo disponvel em nosso site: http://www.k19.com.br/artigos/instalando-mysql/
Podemos utilizar o comando SHOW DATABASES para listar as bases de dados existentes.
mysql > show databases ; + - - - - - - - - - - - - - - - - - - - -+ | Database | + - - - - - - - - - - - - - - - - - - - -+ | information_schema | | livraria | | mysql | | test | + - - - - - - - - - - - - - - - - - - - -+ 4 rows in set ( . 3 sec )
www.k19.com.br
B ANCO DE DADOS
Repare que, alm da base de dados livraria, h outras trs bases. Essas bases foram criadas automaticamente pelo prprio MySQL Server para teste ou para armazenar conguraes. Quando uma base de dados no mais necessria, ela pode ser removida atravs do comando DROP DATABASE.
mysql > DROP DATABASE livraria ; Query OK , rows affected ( . 8 sec )
Tabelas
Um servidor de banco de dados dividido em bases de dados com o intuito de separar as informaes de domnios diferentes. Nessa mesma linha de raciocnio, podemos dividir os dados de uma base a m de agrup-los segundo as suas correlaes. Essa separao feita atravs de tabelas. Por exemplo, no sistema de um banco, interessante separar o saldo e o limite de uma conta, do nome e CPF de um cliente. Ento, poderamos criar uma tabela para os dados relacionados s contas e outra para os dados relacionados aos clientes. Cliente idade cpf 27 31875638735 32 30045667856 Conta saldo 1000 2000
numero 1 2
Tabela 1.1: Tabelas para armazenar os dados relacionados aos clientes e s contas
Uma tabela formada por registros (linhas) e os registros so formados por campos (colunas). Por exemplo, considere uma tabela para armazenar as informaes dos clientes de um banco. Cada registro dessa tabela armazena em seus campos os dados de um determinado cliente.
As tabelas de uma base de dados podem ser listadas atravs do comando SHOW TABLES. Antes de utilizar esse comando, devemos selecionar uma base de dados atravs do comando USE.
mysql > USE livraria ; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed
www.facebook.com/k19treinamentos
B ANCO DE DADOS
mysql > SHOW TABLES ; + - - - - - - - - - - - - - - - - - - - -+ | Tables_in_livraria | + - - - - - - - - - - - - - - - - - - - -+ | Livro | + - - - - - - - - - - - - - - - - - - - -+ 1 row in set ( . sec )
Se uma tabela no for mais desejada, ela pode ser removida atravs do comando DROP TABLE.
mysql > DROP TABLE Livro ; Query OK , rows affected ( . sec )
Operaes Bsicas
As operaes bsicas para manipular os dados persistidos so: inserir, ler, alterar e remover. Essas operaes so realizadas atravs de uma linguagem de consulta denominada SQL (Structured Query Language). Essa linguagem oferece quatro comandos bsicos: INSERT, SELECT, UPDATE e DELETE. Esses comandos so utilizados para inserir, ler, alterar e remover registros, respectivamente.
mysql > INSERT INTO Livro ( titulo , preco ) VALUES ( Java , 98.75); Query OK , 1 row affected ( . sec )
mysql > SELECT * FROM Livro ; + - - - - - - - -+ - - - - - - -+ | titulo | preco | + - - - - - - - -+ - - - - - - -+ | Java | 98.75 | + - - - - - - - -+ - - - - - - -+ 1 row in set ( . sec )
mysql > UPDATE Livro SET preco = 115.9 WHERE titulo = Java ; Query OK , 1 row affected ( . sec ) Rows matched : 1 Changed : 1 Warnings :
mysql > SELECT * FROM Livro ; + - - - - - - - -+ - - - - - - -+ | titulo | preco | + - - - - - - - -+ - - - - - - -+ | Java | 115.9 | + - - - - - - - -+ - - - - - - -+ 1 row in set ( . sec )
mysql > DELETE FROM Livro WHERE titulo = Java ; Query OK , 1 row affected ( . sec )
www.k19.com.br
5
mysql > SELECT * FROM Livro ; Empty set ( . sec )
B ANCO DE DADOS
Exerccios de Fixao
5
www.facebook.com/k19treinamentos
B ANCO DE DADOS
Estando dentro da sua pasta, acesse o MySQL Server utilizando o usurio root e a senha root.
k19@k19 -11:~/ rafael$ mysql -u root -p Enter password :
Caso exista uma base de dados chamada livraria, remova-a. Utilize o comando SHOW DATABASES para listar as bases de dados existentes e o comando DROP DATABASE para remover a base livraria se ela existir.
3
mysql > SHOW DATABASES ; + - - - - - - - - - - - - - - - - - - - -+ | Database | + - - - - - - - - - - - - - - - - - - - -+ | information_schema | | livraria | | mysql | | test | + - - - - - - - - - - - - - - - - - - - -+ 4 rows in set ( . sec ) mysql > DROP DATABASE livraria ; Query OK , 1 row affected ( .12 sec )
4 Crie uma nova base de dados chamada livraria. Utilize o comando CREATE DATABASE. Voc vai utilizar esta base nos exerccios seguintes.
mysql > CREATE DATABASE livraria ; Query OK , 1 row affected ( . sec )
Abra um editor de texto e digite o cdigo abaixo para criar uma tabela com o nome Editora. Depois salve o arquivo com o nome create-table-editora.sql dentro da pasta com o seu nome.
5
1 2 3 4 5 6 7 8
USE livraria ; CREATE TABLE Editora ( id BIGINT NOT NULL AUTO_INCREMENT , nome VARCHAR (255) NOT NULL , email VARCHAR (255) NOT NULL , PRIMARY KEY ( id ) ) ENGINE = InnoDB ;
Cdigo SQL 1.1: Criando a tabela Editora
Dentro do terminal, use o comando source para executar o arquivo que voc acabou de criar.
mysql > source create - table - editora . sql Database changed
www.k19.com.br
7
Query OK , rows affected ( . 8 sec )
B ANCO DE DADOS
Abra um novo editor de texto e digite o cdigo abaixo para criar uma tabela com o nome Livro. Em seguida, salve o arquivo com o nome create-table-livro.sql dentro da pasta com o seu nome.
7
1 2 3 4 5 6 7 8 9 1 11 12 13
USE livraria ; CREATE TABLE Livro ( id BIGINT NOT NULL AUTO_INCREMENT , titulo VARCHAR (255) NOT NULL , preco DOUBLE NOT NULL , editora_id BIGINT NOT NULL , PRIMARY KEY ( id ) , CONSTRAINT fk_editora FOREIGN KEY fk_editora ( editora_id ) REFERENCES Editora ( id ) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB ;
Cdigo SQL 1.2: Criando a tabela Livro
Dentro do terminal, use o comando source para executar o cdigo do arquivo create-table-livro.sql.
mysql > source create - table - livro . sql Database changed Query OK , rows affected ( . 8 sec )
Abra um novo editor de texto e digite o cdigo abaixo para adicionar alguns registros na tabela Editora. Depois salve o arquivo com o nome adicionando-registros-editora.sql dentro da pasta com o seu nome.
9
1 2 3 4 5
INSERT INTO Editora ( nome , email ) VALUES ( Oreilly , oreilly@email . com ) ; INSERT INTO Editora ( nome , email ) VALUES ( Wrox , wrox@email . com ) ; INSERT INTO Editora ( nome , email ) VALUES ( Apress , apress@email . com ) ;
Cdigo SQL 1.3: Adicionando registros na tabela Editora
10 Dentro do terminal, execute o arquivo que voc acabou de criar para adicionar alguns registro na tabela Editora.
mysql > source adicionando - registros - editora . sql Query OK , 1 row affected ( . 3 sec ) Query OK , 1 row affected ( . 4 sec ) Query OK , 1 row affected ( . 4 sec )
Abra um novo editor de texto e digite o cdigo abaixo para adicionar alguns registros na tabela Livro. Depois salve o arquivo com o nome adicionando-registros-livro.sql dentro da pasta com o seu nome.
11
1 2
www.facebook.com/k19treinamentos
B ANCO DE DADOS
3 4 5 6 INSERT INTO Livro ( titulo , preco , editora_id ) VALUES ( Introduo ao JSF 2 , 122.9 , 3) ; INSERT INTO Livro ( titulo , preco , editora_id ) VALUES ( JSF 2 Avanado , 149.9 , 3) ;
Cdigo SQL 1.4: Adicionando alguns registros na tabela Livro
Dentro do terminal, execute o arquivo que voc acabou de criar para adicionar alguns registros na Livro.
12
mysql > source adicionando - registros - livro . sql Query OK , 1 row affected ( . 2 sec ) Query OK , 1 row affected ( . 4 sec ) Query OK , 1 row affected ( . 4 sec )
13
mysql > SELECT * FROM Livro ; + - - - -+ - - - - - - - - - - - - - - - - - - - - - - -+ - - - - - - -+ - - - - - - - - - - - -+ | id | titulo | preco | editora_id | + - - - -+ - - - - - - - - - - - - - - - - - - - - - - -+ - - - - - - -+ - - - - - - - - - - - -+ | 1 | Aprendendo C # | 89.9 | 1 | | 2 | Introduo ao JSF 2 | 122.9 | 3 | | 3 | JSF 2 Avanado | 149.9 | 3 | + - - - -+ - - - - - - - - - - - - - - - - - - - - - - -+ - - - - - - -+ - - - - - - - - - - - -+ 3 rows in set ( . sec )
14
15
16
www.k19.com.br
B ANCO DE DADOS
17 Remova alguns registros da tabela Editora. Preste ateno para no remover uma editora que tenha algum livro relacionado j adicionado no banco. Utilize o comando DELETE.
mysql > DELETE FROM Editora WHERE id =2; Query OK , 1 row affected ( . 5 sec )
18
Faa uma consulta para buscar todos os livros de uma determinada editora.
mysql > SELECT * FROM Livro as L , Editora as E WHERE L . editora_id = E . id and E . id = 1; + - - - -+ - - - - - - - - - - - - - - -+ - - - - - - -+ - - - - - - - - - - - -+ - - - -+ - - - - - - - - -+ - - - - - - - - - - - - - - - - - - -+ | id | titulo | preco | editora_id | id | nome | email | + - - - -+ - - - - - - - - - - - - - - -+ - - - - - - -+ - - - - - - - - - - - -+ - - - -+ - - - - - - - - -+ - - - - - - - - - - - - - - - - - - -+ | 1 | Aprendendo C # | 92.9 | 1 | 1 | OReilly | oreilly@email . com | + - - - -+ - - - - - - - - - - - - - - -+ - - - - - - -+ - - - - - - - - - - - -+ - - - -+ - - - - - - - - -+ - - - - - - - - - - - - - - - - - - -+ 1 row in set ( . sec )
Exerccios Complementares
Utilize o MySQL Query Browser para refazer os exerccios anteriores.
1 Abra o MySQL Query Browser utilizando localhost como Server Hostname, root como Username e root como Password.
Caso exista uma base de dados chamada livraria, remova-a conforme a gura abaixo.
www.facebook.com/k19treinamentos
B ANCO DE DADOS
10
Crie uma nova base de dados chamada livraria, conforme mostrado na gura abaixo. Voc vai utilizar esta base nos exerccios seguintes.
3
10
www.k19.com.br
11
B ANCO DE DADOS
11
B ANCO DE DADOS
12
12
www.k19.com.br
13
B ANCO DE DADOS
Crie os campos conforme a gura e no esquea de tornar todos os campos obrigatrios, marcando a opo NOT NULL. Alm disso, o campo id deve ser uma chave primria e automaticamente incrementada.
www.facebook.com/k19treinamentos
13
B ANCO DE DADOS
14
Aps clicar no boto Apply Changes, aparecer uma janela mostrando os comandos SQL gerados. Clique no boto Execute.
Crie uma tabela chamada Livro conforme as guras abaixo. Altere o modo de criao da tabela para InnoDB, conforme mostrado na gura.
6
14
www.k19.com.br
15
B ANCO DE DADOS
Novamente, adicione os campos conforme a gura abaixo, lembrando de marcar a opo NOT NULL. Alm disso, o campo id deve ser uma chave primria e automaticamente incrementada.
www.facebook.com/k19treinamentos
15
B ANCO DE DADOS
16
Voc precisa tornar o campo editora_id uma chave estrangeira. Selecione a aba Foreign Keys e clique no boto com o smbolo + para adicionar uma chave estrangeira. Depois, siga os procedimentos conforme mostrados na gura abaixo.
16
www.k19.com.br
17
B ANCO DE DADOS
17
B ANCO DE DADOS
18
18
19
B ANCO DE DADOS
Consulte os registros da tabela Editora e, em seguida, consulte a tabela Livro. Veja exemplos logo abaixo.
9
www.facebook.com/k19treinamentos
19
B ANCO DE DADOS
20
20
www.k19.com.br
21
10
B ANCO DE DADOS
11
21
B ANCO DE DADOS
22
12
22
www.k19.com.br
23
13
B ANCO DE DADOS
Remova alguns registros da tabela Editora. Preste ateno para no remover uma editora que tenha algum livro relacionado j adicionado no banco. Veja o exemplo abaixo:
Faa uma consulta para buscar todos os livros associados as suas respectivas editoras. Veja um exemplo na gura abaixo.
14
www.facebook.com/k19treinamentos
23
B ANCO DE DADOS
24
24
www.k19.com.br
CAPTULO
SELECT * FROM tbl_funcionarios WHERE nome LIKE %jonas%; INSERT INTO tbl_funcionarios (nome, codigo, salario) VALUES (Rafael, 1234, 1000);
JDBC
No captulo anterior, aprendemos que utilizar bancos de dados uma tima alternativa para armazenar os dados de uma aplicao. Entretanto, voc deve ter percebido que as interfaces disponveis para interagir com o MySQL Server no podem ser utilizadas por qualquer pessoa. Para utiliz-las, necessrio conhecer a linguagem SQL e os conceitos do modelo relacional. Em geral, as interfaces dos outros SGDBs exigem os mesmos conhecimentos.
Figura 2.1: Usurios comuns no possuem conhecimento sobre SQL ou sobre o modelo relacional
Para resolver esse problema, podemos desenvolver aplicaes com interfaces que no exijam conhecimentos tcnicos de SQL ou do modelo relacional para serem utilizadas. Dessa forma, usurios comuns poderiam manipular as informaes do banco de dados atravs dessas aplicaes. Nessa abordagem, os usurios interagem com as aplicaes e as aplicaes interagem com os SGDBs.
www.k19.com.br
www.facebook.com/k19treinamentos
25
JDBC
26
Driver
As aplicaes interagem com os SGDBs atravs de troca de mensagens. Os SGDBs denem o formato das mensagens. Para no sobrecarregar o canal de comunicao entre as aplicaes e os SGDBs, as mensagens trocadas devem ocupar o menor espao possvel. Geralmente, protocolos binrios so mais apropriados para reduzir o tamanho das mensagens e consequentemente diminuir a carga do canal de comunicao. Por isso, os SGDBs utilizam protocolos binrios.
nd
rollback
Figura 2.3: Diminuindo o tamanho das mensagens para no sobrecarregar o meio de comunicao
Mensagens binrias so facilmente interpretadas por computadores. Por outro lado, so complexas para um ser humano compreender. Dessa forma, o trabalho dos desenvolvedores seria muito complexo, aumentando o custo para o desenvolvimento e manuteno das aplicaes.
26
www.k19.com.br
27
JDBC
Para resolver esse problema e facilitar o desenvolvimento das aplicaes, as empresas proprietrias dos SGDBs, normalmente, desenvolvem e distribuem drivers de conexo. Um driver de conexo atua como um intermedirio entre as aplicaes e os SGDBs. Os drivers de conexo so tradutores de comandos escritos em uma determinada linguagem de programao para comandos denidos de acordo com o protocolo de um SGDB. Utilizando um driver de conexo, os desenvolvedores das aplicaes no manipulam diretamente as mensagens binrias trocadas entre as aplicaes e os SGDBs.
Mais Sobre
Em alguns casos, o protocolo binrio de um determinado SGDB fechado. Consequentemente, a nica maneira de se comunicar com ele atravs de um driver de conexo oferecido pelo fabricante desse SGDB.
JDBC
Suponha que os drivers de conexo fossem desenvolvidos sem nenhum padro. Cada driver teria sua prpria interface, ou seja, seu prprio conjunto de instrues. Consequentemente, os desenvolvedores teriam de conhecer a interface de cada um dos drivers dos respectivos SGDBs que fossem utilizar.
01110010101110011
00010011101110010
Para facilitar o trabalho do desenvolvedor da aplicao, a plataforma Java possui uma especicao que padroniza os drivers de conexo. A sigla dessa especicao JDBC (Java Database Connectivity ). Em geral, as empresas proprietrias dos SGBDs desenvolvem e distribuem drivers de conexo que seguem a especicao JDBC.
www.facebook.com/k19treinamentos
27
JDBC
28
getConnection()
01110010101110011
00010011101110010
http://www.mysql.com/downloads/connector/j/.
A instalao desse driver consiste em descompactar o arquivo obtido no site acima e depois incluir o arquivo jar com o driver no class path da aplicao.
28
www.k19.com.br
29
JDBC
A classe responsvel pela criao de uma conexo JDBC a DriverManager do pacote java.sql. A string de conexo, o usurio e a senha devem ser passados ao mtodo esttico getConnection() da classe DriverManager para que ela possa criar uma conexo JDBC.
1 2 3 4 5 6 7 8 String urlDeConexao = " jdbc : mysql :// localhost / livraria " ; String usuario = " root " ; String senha = " root " ; try { Connection conexao = DriverManager . getConnection ( urlDeConexao , usuario , senha ) ; } catch ( SQLException e ) { e . printStackTrace () ; }
Cdigo Java 2.2: Criando uma conexo JDBC
Inserindo registros
Aps estabelecer uma conexo JDBC, podemos executar operaes. A primeira operao que realizaremos a insero de registros em uma tabela. O primeiro passo para executar essa operao denir o cdigo SQL correspondente.
1 String sql = " INSERT INTO Editora ( nome , email ) VALUES ( K19 , contato@k19 . com . br ) ; " ;
Cdigo Java 2.3: Cdigo SQL correspondente operao de insero
O cdigo SQL correspondente operao que desejamos executar deve ser passado como parmetro para o mtodo prepareStatement() de uma conexo JDBC. Esse mtodo criar um objeto que representa a operao que ser executada. A operao poder ser executada posteriormente atravs do mtodo execute().
1 2 3 4 5 6 // criando um prepared statement PreparedStatement comando = conexao . prepareStatement ( sql ) ; // executando o prepared statement comando . execute () ; comando . close () ;
Cdigo Java 2.4: Criando um prepared statement
Importante
A mesma conexo pode ser reaproveitada para executar vrias operaes. Quando no houver mais operaes a serem executadas, devemos nalizar a conexo JDBC atravs do mtodo close(). Finalizar as conexes JDBC que no so mais necessrias importante pois libera recursos no SGBD.
1 conexao . close () ;
Cdigo Java 2.5: Finalizando uma conexo JDBC
Exerccios de Fixao
www.facebook.com/k19treinamentos
29
JDBC
30
1 2 3
No Eclipse, crie um projeto Java chamado JDBC. Crie uma pasta chamada lib no projeto JDBC.
Entre na pasta K19-Arquivos/MySQL-Connector-JDBC da rea de Trabalho e copie o arquivo mysql-connector-java-5.1.13-bin.jar para a pasta lib do projeto JDBC.
4
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19
public class InsereEditora { public static void main ( String [] args ) { String stringDeConexao = " jdbc : mysql :// localhost :33 6/ livraria " ; String usuario = " root " ; String senha = " root " ; Scanner entrada = new Scanner ( System . in ) ; try { System . out . println ( " Abrindo conexo ... " ) ; Connection conexao = DriverManager . getConnection ( stringDeConexao , usuario , senha ) ; System . out . println ( " Digite o nome da editora : " ) ;
30
www.k19.com.br
31
2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 String nome = entrada . nextLine () ; System . out . println ( " Digite o email da editora : " ) ; String email = entrada . nextLine () ; String sql = " INSERT INTO Editora ( nome , email ) " + " VALUES ( " + nome + " , " + email + " ) " ; PreparedStatement comando = conexao . prepareStatement ( sql ) ; System . out . println ( " Executando comando ... " ) ; comando . execute () ; System . out . println ( " Fechando conexo ... " ) ; conexao . close () ; } catch ( Exception e ) { e . printStackTrace () ; } } }
Cdigo Java 2.6: InsereEditora.java
JDBC
Exerccios Complementares
1
Crie uma classe chamada InsereLivros para cadastrar livros na base de dados.
SQL Injection
A implementao da insero de registros feita anteriormente possui uma falha grave. Os dados obtidos do usurio atravs do teclado no so tratados antes de serem enviados para o SGDB. Esses dados podem conter caracteres especiais. Se esses caracteres no so tratados, o comportamento esperado da operao afetado. Eventualmente, registros no so inseridos como deveriam ou brechas de segurana podem se abrir. Por exemplo, considere a classe InsereEditora do exerccio de xao. Se o usurio digitar OReilly e oreilly@email.com, o cdigo SQL gerado pela aplicao seria:
1 INSERT INTO Editora ( nome , email ) VALUES ( O Reilly , oreilly@email . com )
Observe que o caractere aspas simples aparece cinco vezes no cdigo SQL acima. O SGDB no saberia dizer onde de fato termina o nome da editora. Ao tentar executar esse cdigo, um erro de sintaxe lanado pelo MySQL Server. Para resolver esse problema manualmente, devemos adicionar o caractere \ antes do caractere aspas simples que faz parte do nome da editora. Na sintaxe do MySQL Server, o caractere \ deve ser acrescentado imediatamente antes de todo caractere especial que deve ser tratado como um caractere comum.
1 INSERT INTO Editora ( nome , email ) VALUES ( O \ Reilly , oreilly@email . com )
Os valores recebidos dos usurios devem ser analisados e os caracteres especiais contidos nesses
www.facebook.com/k19treinamentos
31
JDBC
32
valores devem ser tratados. Esse processo extremamente trabalhoso, pois o conjunto de caracteres especiais e a forma de trat-los diferente em cada SGDB. A responsabilidade do tratamento dos caracteres especiais contidos nos valores de entrada dos usurios pode ser repassada para os drivers JDBC. Dessa forma, o cdigo das aplicaes se torna independente das particularidades desse processo para cada SGDB.
Mais Sobre
O processo de tratamento dos caracteres especiais das entradas dos usurios denominado sanitize.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17
// lendo as entradas do usurio System . out . println ( " Digite o nome da editora : " ) ; String nome = entrada . nextLine () ; System . out . println ( " Digite o email da editora : " ) ; String email = entrada . nextLine () ; // cdigo sql com marcadores para as entradas do usurio String sql = " INSERT INTO Editora ( nome , email ) VALUES (? , ?) " ; // criando um comando a partir do cdigo SQL PreparedStatement comando = conexao . prepareStatement ( sql ) ; // adicionando as entradas do usurios no comando // o processo de sanitizao ocorre aqui comando . setString (1 , nome ) ; comando . setString (2 , email ) ;
Cdigo Java 2.10: Sanitizando as entradas dos usurios
Observe que o cdigo SQL foi denido com parmetros atravs do caractere ?. Antes de executar o comando, necessrio determinar os valores dos parmetros. Essa tarefa pode ser realizada atravs do mtodo setString(), que recebe o ndice (posio) do parmetro no cdigo SQL e o valor correspondente. Esse mtodo faz o tratamento dos caracteres especiais contidos nos valores de entrada do usurio de acordo com as regras do SGDB utilizado.
Exerccios de Fixao
Provoque um erro de SQL Injection na classe InsereEditoras. (Dica: tente entradas com aspas simples.)
6 7
1 2 3 4 5 6 7 8 9 1 11
public class InsereEditora { public static void main ( String [] args ) { String stringDeConexao = " jdbc : mysql :// localhost :33 6/ livraria " ; String usuario = " root " ; String senha = " root " ;
32
www.k19.com.br
33
12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41
JDBC
Scanner entrada = new Scanner ( System . in ) ; try { System . out . println ( " Abrindo conexo ... " ) ; Connection conexao = DriverManager . getConnection ( stringDeConexao , usuario , senha ) ; System . out . println ( " Digite o nome da editora : " ) ; String nome = entrada . nextLine () ; System . out . println ( " Digite o email da editora : " ) ; String email = entrada . nextLine () ; String sql = " INSERT INTO Editora ( nome , email ) VALUES (? , ?) " ; PreparedStatement comando = conexao . prepareStatement ( sql ) ; comando . setString (1 , nome ) ; comando . setString (2 , email ) ; System . out . println ( " Executando comando ... " ) ; comando . execute () ; System . out . println ( " Fechando conexo ... " ) ; conexao . close () ; } catch ( Exception e ) { e . printStackTrace () ; } } }
Cdigo Java 2.11: InsereEditora.java
Exerccios Complementares
Provoque um erro de SQL Injection na classe InsereLivros. (Dica: tente entradas com aspas simples.)
2 3 4
Altere o cdigo para eliminar o problema do SQL Injection. Agora tente causar novamente o problema de SQL Injection ao inserir novos livros.
Listando registros
O processo para executar um comando de consulta bem parecido com o processo de inserir registros. O primeiro passo denir a consulta em SQL.
1 2 3 4 5 6 String sql = " SELECT * FROM Editora ; " ; PreparedStatement comando = conexao . prepareStatement ( sql ) ; System . out . println ( " Executando comando ... " ) ; ResultSet resultado = comando . executeQuery () ;
Cdigo Java 2.13: Realizando uma consulta.
A diferena que para executar um comando de consulta necessrio utilizar o mtodo executeQuery() ao invs do execute(). Esse mtodo devolve um objeto da interface java.sql.Resultwww.facebook.com/k19treinamentos
33
JDBC
34
O cdigo acima mostra como os campos do primeiro registro da consulta so recuperados. Para recuperar os dados dos outros registros necessrio avanar o ResultSet atravs do mtodo next().
1 2 3 4 5 6 7 8 9 int id1 = resultado . getInt ( " id " ) , String nome1 = resultado . getString ( " nome " ) , String email1 = resultado . getString ( " email " ) ; resultado . next () ; int id2 = resultado . getInt ( " id " ) , String nome2 = resultado . getString ( " nome " ) , String email2 = resultado . getString ( " email " ) ;
Cdigo Java 2.15: Avanando o ResultSet
O prprio mtodo next() devolve um valor booleano para indicar se o ResultSet conseguiu avanar para o prximo registro. Quando esse mtodo devolver false signica que no h mais registros para serem consultados.
1 2 3 4 5 while ( resultado . next () ) { int id = resultado . getInt ( " id " ) , String nome = resultado . getString ( " nome " ) , String email = resultado . getString ( " email " ) ; }
Cdigo Java 2.16: Iterando os registros do ResultSet
Exerccios de Fixao
8
Insira algumas editoras utilizando a classe InsereEditora que voc criou anteriormente.
9 Adicione uma nova classe ao projeto chamada ListaEditoras. O objetivo listar as editoras que foram salvas no banco.
1 2 3 4 5 6 7 8 9 1 11 12
java . sql . Connection ; java . sql . DriverManager ; java . sql . PreparedStatement ; java . sql . ResultSet ;
public class ListaEditoras { public static void main ( String [] args ) { String stringDeConexao = " jdbc : mysql :// localhost :33 6/ livraria " ; String usuario = " root " ; String senha = " root " ; try {
34
www.k19.com.br
35
13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38
Exerccios Complementares
5
Connection Factory
Voc deve ter percebido que em diversos pontos diferentes da nossa aplicao precisamos de uma conexo JDBC. Se a url de conexo for denida em cada um desses pontos, teremos um problema de manuteno. Imagine que o driver do banco seja atualizado ou que o IP do SGBD seja alterado. Teramos que alterar o cdigo da nossa aplicao em muitos lugares. Mais precisamente, cada ocorrncia da url de conexo precisaria ser modicada. A probabilidade de algum ponto no ser corrigido grande. Para diminuir o trabalho de manuteno, podemos implementar uma classe responsvel pela criao e distribuio de conexes. A url de conexo deve ser denida nessa classe e somente nela. Consequentemente, alteraes nas informaes contidas na url de conexo afetariam apenas uma classe da aplicao.
1 2 3 4 5 6 7 8 9 import java . sql . Connection ; import java . sql . DriverManager ; import java . sql . SQLException ; public class ConnectionFactory { public static Connection createConnection () { String stringDeConexao = " jdbc : mysql :// localhost :33 6/ livraria " ; String usuario = " root " ; String senha = " root " ;
www.facebook.com/k19treinamentos
35
JDBC
1 11 12 13 14 15 16 17 18 19 2
36
Connection conexao = null ; try { conexao = DriverManager . getConnection ( stringDeConexao , usuario , senha ) ; } catch ( SQLException e ) { e . printStackTrace () ; } return conexao ; } }
Cdigo Java 2.19: ConnectionFactory.java
Agora, podemos obter uma nova conexo apenas chamando o mtodo createConnection(). O resto do sistema no precisa mais conhecer os detalhes sobre a criao das conexes com o banco de dados, diminuindo o acoplamento da aplicao.
Exerccios de Fixao
10
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2
Altere as classes InsereEditora e ListaEditoras para que elas utilizem a fbrica de conexo. Depois, execute-as novamente.
11
1 2 3 4 5 6 7 8 9 1 11 12 13 14
import java . sql . Connection ; import java . sql . PreparedStatement ; import java . util . Scanner ; public class InsereEditora { public static void main ( String [] args ) { Scanner entrada = new Scanner ( System . in ) ; try { System . out . println ( " Abrindo conexo ... " ) ; Connection conexao = ConnectionFactory . createConnection () ; System . out . println ( " Digite o nome da editora : " ) ; String nome = entrada . nextLine () ;
36
www.k19.com.br
37
15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35
System . out . println ( " Digite o email da editora : " ) ; String email = entrada . nextLine () ; String sql = " INSERT INTO Editora ( nome , email ) " + " VALUES (? , ?) " ; PreparedStatement comando = conexao . prepareStatement ( sql ) ; comando . setString (1 , nome ) ; comando . setString (2 , email ) ; System . out . println ( " Executando comando ... " ) ; comando . execute () ; System . out . println ( " Fechando conexo ... " ) ; conexao . close () ; } catch ( Exception e ) { e . printStackTrace () ; } } }
Cdigo Java 2.21: InsereEditora.java
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32
import java . sql . Connection ; import java . sql . PreparedStatement ; import java . sql . ResultSet ; public class ListaEditoras { public static void main ( String [] args ) { try { System . out . println ( " Abrindo conexo ... " ) ; Connection conexao = ConnectionFactory . createConnection () ; String sql = " SELECT * FROM Editora ; " ; PreparedStatement comando = conexao . prepareStatement ( sql ) ; System . out . println ( " Executando comando ... " ) ; ResultSet resultado = comando . executeQuery () ; System . out . println ( " Resultados encontrados : \ n " ) ; while ( resultado . next () ) { System . out . printf ( " % d : % s - % s \ n " , resultado . getInt ( " id " ) , resultado . getString ( " nome " ) , resultado . getString ( " email " ) ) ; } System . out . println ( " \ nFechando conexo ... " ) ; conexao . close () ; } catch ( Exception e ) { e . printStackTrace () ; } } }
Cdigo Java 2.22: ListaEditoras.java
Exerccios Complementares
Altere as classes InsereLivro e ListaLivros para que elas utilizem a fbrica de conexo. Depois, execute-as novamente.
6
www.facebook.com/k19treinamentos
37
JDBC
38
Desaos
1 2
Implemente a remoo de editoras pelo id. Implemente a alterao dos dados das editoras pelo id.
38
www.k19.com.br
CAPTULO
Driver Oracle JDBC Driver MySQL JDBC
JPA 2 E H IBERNATE
SELECT * FROM ( SELECT ROW_NUMBER() OVER (ORDER BY autor ASC) AS rownumber, id, titulo, autor FROM livros ) WHERE rownumber <= 100
39
JPA 2 E H IBERNATE
40
utilizam o modelo orientado a objetos. A transio de dados entre o modelo relacional e o modelo orientado a objetos no simples. Para realizar essa transio, necessrio denir um mapeamento entre os conceitos desses dois paradigmas. Por exemplo, classes podem ser mapeadas para tabelas, objetos para registros, atributos para campos e referncia entre objetos para chaves estrangeiras.
tbl_editoras Livro id = 1 titulo = Os Lusadas autor = Lus Vaz de Cames editora = 1 Editora id = 1 nome = Livraria Cultura Livro id = 2 titulo = Vidas Secas autor = Graciliano Ramos editora = 1 tbl_livros id 1 2 3 4 titulo Os Lusadas Vidas Secas Dom Casmurro O Cortio autor Lus Vaz de Cames Graciliano Ramos Machado de Assis Alusio Azevedo editora_id 1 1 3 2 id 1 2 3 4 nome Cultura FTDA Globo Scipione
ORIENTAO A OBJETOS
MODELO RELACIONAL
Ferramentas ORM
Para facilitar a comunicao entre aplicaes Java que seguem o modelo orientado a objetos e os SGDBs que seguem o modelo relacional, podemos utilizar ferramentas que automatizam a transio de dados entre as aplicaes e os SGDBs. Essas ferramentas so conhecidas como ferramentas ORM (Object Relational Mapper ). As ferramentas ORM oferecem mecanismos de consultas independentes da linguagem SQL. Dessa forma, o acoplamento entre as aplicaes e os SGDBs diminui drasticamente. A principal ferramenta ORM para Java utilizada no mercado o Hibernate. Mas, existem outras que possuem o mesmo objetivo.
40
www.k19.com.br
41
JPA 2 E H IBERNATE
tbl_livros id 1 2 3 4 titulo Os Lusadas Vidas Secas Dom Casmurro O Cortio autor Lus Vaz de Cames Graciliano Ramos Machado de Assis Alusio Azevedo editora_id 1 1 3 2
Livro
Figura 3.3: Transformao dos dados do Modelo Relacional para o Modelo Orientado a Objetos
tbl_livros
id
titulo
autor Lus Vaz de Cames Graciliano Ramos Machado de Assis Alusio Azevedo
editora_id 1 1 3 2
Figura 3.4: Transformao dos dados do Modelo Orientado a Objetos para o Modelo Relacional
Bibliotecas
Antes de comear a utilizar o Hibernate, necessrio baixar do site ocial o bundle que inclui os
www.facebook.com/k19treinamentos
41
JPA 2 E H IBERNATE
42
jars do hibernate e todas as suas dependncias. Neste curso, utilizaremos a verso 3.5.1. A url do site ocial do Hibernate http://www.hibernate.org/.
Congurao
Para congurar o Hibernate em uma aplicao, devemos criar um arquivo chamado persistence.xml. O contedo desse arquivo possuir informaes sobre o banco de dados, como a url de conexo, usurio e senha, alm de dados sobre a implementao de JPA que ser utilizada. O arquivo persistence.xml deve estar em uma pasta chamada META-INF, que deve estar no classpath da aplicao. Veja abaixo um exemplo de congurao para o persistence.xml.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 <? xml version = " 1. " encoding = " UTF -8 " ? > < persistence version = " 2. " xmlns = " http: // java . sun . com / xml / ns / persistence " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance " xsi:schemaLocation = " http: // java . sun . com / xml / ns / persistence http: // java . sun . com / xml / ns / persistence / persistence_2_ . xsd " > < persistence - unit name = " K19 - PU " transaction - type = " RESOURCE_LOCAL " > < provider > org . hibernate . ejb . HibernatePersistence </ provider > < properties > < property name = " hibernate . dialect " value = " org . hibernate . dialect . MySQL5InnoDBDialect " / > < property name = " hibernate . hbm2ddl . auto " value = " create " / > < property name = " javax . persistence . jdbc . driver " value = " com . mysql . jdbc . Driver " / > < property name = " javax . persistence . jdbc . user " value = " usuario " / > < property name = " javax . persistence . jdbc . password " value = " senha " / > < property name = " javax . persistence . jdbc . url " value = " jdbc:mysql: // localhost:33 6 / K19 - DB " / > </ properties > </ persistence - unit > </ persistence >
Cdigo XML 3.1: persistence.xml
A propriedade hibernate.dialect permite que a aplicao escolha qual sintaxe de SQL deve ser utilizada pelo Hibernate.
Mais Sobre
Consulte o artigo da K19 sobre congurao do Hibernate e MySQL na seguinte url: http://www.k19.com.br/artigos/configurando-hibernate-com-mysql/.
Mapeamento
Um dos principais objetivos das ferramentas ORM estabelecer o mapeamento entre os conceitos do modelo orientado a objetos e os conceitos do modelo relacional. Esse mapeamento pode ser denido atravs de XML ou de maneira mais prtica com anotaes Java.
42
www.k19.com.br
43
JPA 2 E H IBERNATE
A seguir, veremos as principais anotaes Java de mapeamento do JPA. Essas anotaes esto no pacote javax.persistence.
@Entity a principal anotao do JPA. Ela deve aparecer antes do nome de uma classe e deve ser denida em todas as classes que tero objetos persistidos no banco de dados. As classes anotadas com @Entity so mapeadas para tabelas. Por conveno, as tabelas possuem os mesmos nomes das classes. Mas, podemos alterar esse comportamento utilizando a anotao @Table. Os atributos declarados em uma classe anotada com @Entity so mapeados para colunas na tabela correspondente classe. Outra vez, por conveno, as colunas possuem os mesmos nomes dos atributos. Novamente, podemos alterar esse padro utilizando a anotao @Column. @Id Utilizada para indicar qual atributo de uma classe anotada com @Entity ser mapeado para a chave primria da tabela correspondente classe. Geralmente o atributo anotado com @Id do tipo Long. @GeneratedValue Geralmente vem acompanhado da anotao @Id. Serve para indicar que o atributo gerado pelo banco, no momento em que um novo registro inserido. @Table Utilizada para alterar o nome padro da tabela. Ela recebe o parmetro name para indicar qual nome deve ser utilizado na tabela. Veja o exemplo:
1 2 3 4 5 @Table ( name = " Publisher " ) @Entity public class Editora { // ... }
Cdigo Java 3.1: Editora.java
@Column Utilizado para alterar o nome da coluna que ser usado na tabela. Caso voc esteja utilizando um banco de dados legado, no qual os nomes das colunas j foram denidos, voc pode mudar atravs dessa anotao. Alm disso, podemos estabelecer certas restries, como determinar se o campo pode ou no ser nulo.
1 2 3 4 5 6 @Entity public class Editora { @Column ( name = " publisher_name " , nullable = false ) private String nome ; }
Cdigo Java 3.2: Editora.java
@Transient Serve para indicar que um atributo no deve ser persistido, ou seja, os atributos anotados com @Transient no so mapeados para colunas. @Lob Utilizado para atributos que armazenam textos muito grandes, ou arquivos binrios contendo imagens ou sons que sero persistidos no banco de dados. O tipo do atributo deve ser String, Byte[], byte[] ou java.sql.Blob. @Temporal Utilizado para atributos do tipo Calendar ou Date. Por padro, tanto data quanto hora so armazenados no banco de dados. Mas, com a anotao @Temporal, podemos mandar persistir somente a data ou somente a hora.
www.facebook.com/k19treinamentos
43
JPA 2 E H IBERNATE
1 2 3 4 5 6 7 @Entity public class Livro { @Temporal ( TemporalType . DATE ) private Calendar publicacao ; // ... }
Cdigo Java 3.3: Livro.java
44
Gerando Tabelas
Uma das vantagens de se utilizar o Hibernate que ele capaz de gerar as tabelas do banco para a nossa aplicao. Ele faz isso de acordo com as anotaes colocadas nas classes e as informaes presentes no persistence.xml. As tabelas so geradas atravs de um mtodo da classe Persistence, o createEntityManagerFactory(String entityUnit). O parmetro entityUnit permite escolher, pelo nome, uma unidade de persistncia denida no persistence.xml. A poltica de criao das tabelas pode ser alterada modicando o valor a propriedade hibernate.hbm2ddl.auto no arquivo persistence.xml. Podemos, por exemplo, fazer com que o Hibernate sempre sobrescreva as tabelas existentes, bastando denir a propriedade hibernate.hbm2ddl.auto com o valor create-drop.
1 < property name = " hibernate . hbm2ddl . auto " value = " create - drop " / >
Uma outra opo congurar o Hibernate para simplesmente atualizar as tabelas de acordo com as mudanas nas anotaes sem remov-las. Nesse caso, o valor da propriedade hibernate.hbm2ddl.auto deve ser update.
1 < property name = " hibernate . hbm2ddl . auto " value = " update " / >
Exerccios de Fixao
Crie um projeto no Eclipse chamado JPA2-Hibernate e feche o projeto JDBC para no gerar confuso na hora de manipular os arquivos.
1 2 3
Entre na pasta K19-Arquivos/Hibernate da rea de Trabalho e copie os jars do Hibernate para a pasta lib do projeto JPA2-Hibernate.
4 Entre na pasta K19-Arquivos/MySQL-Connector-JDBC da rea de Trabalho e copie o arquivo mysql-connector-java-5.1.13-bin.jar para pasta lib do projeto JPA2-Hibernate. 5
Entre na pasta K19-Arquivos/SLF4J da rea de Trabalho e copie os jars para pasta lib do
www.k19.com.br
44
45
JPA 2 E H IBERNATE
projeto JPA2-Hibernate.
6 Entre na pasta K19-Arquivos/Log4J da rea de Trabalho e copie o arquivo log4j-1.2.16.jar para pasta lib do projeto JPA2-Hibernate.
Adicione os jars da pasta lib ao build path do projeto JPA2-Hibernate. Voc deve selecionar os arquivos e adicion-los no build path.
7 8 9
Crie uma pasta chamada META-INF na pasta src no projeto JPA2-Hibernate. Crie o arquivo de conguraes persistence.xml na pasta META-INF.
<? xml version = " 1. " encoding = " UTF -8 " ? > < persistence version = " 2. " xmlns = " http: // java . sun . com / xml / ns / persistence " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance " xsi:schemaLocation = " http: // java . sun . com / xml / ns / persistence http: // java . sun . com / xml / ns / persistence / persistence_2_ . xsd " > < persistence - unit name = " livraria - pu " transaction - type = " RESOURCE_LOCAL " > < provider > org . hibernate . ejb . HibernatePersistence </ provider > < properties > < property name = " hibernate . dialect " value = " org . hibernate . dialect . MySQL5InnoDBDialect " / > < property name = " hibernate . hbm2ddl . auto " value = " create " / > < property name = " javax . persistence . jdbc . driver " value = " com . mysql . jdbc . Driver " / > < property name = " javax . persistence . jdbc . user " value = " root " / > < property name = " javax . persistence . jdbc . password " value = " root " / > < property name = " javax . persistence . jdbc . url " value = " jdbc:mysql: // localhost:33 6 / livraria " / > </ properties > </ persistence - unit > </ persistence >
Cdigo XML 3.4: persistence.xml
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23
Crie uma classe para modelar as editoras da nossa livraria e acrescente as anotaes necessrias para fazer o mapeamento. Obs: As anotaes devem ser importadas do pacote javax.persistence.
10
1 2 3 4 5 6 7 8 9 1 11
@Entity public class Editora { @Id @GeneratedValue private Long id ; private String nome ; private String email ; // GETTERS AND SETTERS }
Cdigo Java 3.4: Editora.java
11 12
Congure o Log4J criando um arquivo chamado log4j.properties na pasta src do projeto JPA2-Hibernate.
www.facebook.com/k19treinamentos
45
JPA 2 E H IBERNATE
1 2 3 4 log4j . rootCategory = INFO , CONSOLE log4j . appender . CONSOLE = org . apache . log4j . ConsoleAppender log4j . appender . CONSOLE . layout = org . apache . log4j . PatternLayout log4j . appender . CONSOLE . layout . ConversionPattern =% r [% t ] % -5 p % c - % m % n
Arquivo de Propriedades 3.1: log4j.properties
46
Gere as tabelas atravs da classe Persistence. Para isso, crie uma classe com mtodo main. Obs: As classes devem ser importadas do pacote javax.persistence.
13
1 2 3 4 5 6 7 8
public class GeraTabelas { public static void main ( String [] args ) { EntityManagerFactory factory = Persistence . createEntityManagerFactory ( " livraria - pu " ) ; factory . close () ; } }
Cdigo Java 3.5: GeraTabelas.java
Atravs do MySQL Query Browser, verique se a tabela Editora foi criada corretamente.
Manipulando entidades
Para manipular as entidades da nossa aplicao, devemos utilizar um EntityManager que obtido atravs de uma EntityManagerFactory.
1 2 3 4 EntityManagerFactory factory = Persistence . createEntityManagerFactory ( " K19 " ) ; EntityManager manager = factory . createEntityManager () ;
Cdigo Java 3.6: Obtendo um EntityManager
Persistindo
Para armazenar as informaes de um objeto no banco de dados, o primeiro passo utilizar o mtodo persist() do EntityManager.
1 2 3 4 5 Editora novaEditora = new Editora () ; novaEditora . setNome ( " K19 - Livros " ) novaEditora . setEmail ( " contato@k19 . com . br " ) ; manager . persist ( novaEditora ) ;
Cdigo Java 3.7: Marcando um objeto para ser persistido
importante destacar que o mtodo persist() apenas marca os objetos que devem ser armazenados no banco de dados. Os objetos sero armazenados aps a chamada do mtodo commit(), como veremos adiante.
46
www.k19.com.br
47
JPA 2 E H IBERNATE
Buscando
Para obter um objeto que contenha informaes do banco de dados, podemos utilizar o mtodo find() ou o mtodo getReference() do EntityManager.
1 2 Editora editora1 = manager . find ( Editora . class , 1 L ) ; Editora editora2 = manager . getReference ( Editora . class , 2 L ) ;
Cdigo Java 3.8: Obtendo objetos com informaes do banco de dados
H uma diferena entre os dois mtodos bsicos de busca find() e getReference(). O mtodo find() recupera os dados desejados imediatamente. J o mtodo getReference() posterga essa tarefa at a primeira chamada de um mtodo get do objeto.
Removendo
Para remover o registro correspondente a um objeto, devemos utilizar o mtodo remove() do EntityManager.
1 2 Editora editora1 = manager . find ( Editora . class , 1 L ) ; manager . remove ( editora1 ) ;
Cdigo Java 3.9: Marcando um objeto para ser removido
Atualizando
Para alterar os dados do registro correspondente a um objeto, basta utilizar os prprios mtodos setters desse objeto.
1 2 Editora editora = manager . find ( Editora . class , 1 L ) ; editora . setNome ( " K19 - Livros e Publicaes " ) ;
Cdigo Java 3.10: Alterando os dados de um registro
Listando
Para obter uma listagem com todos os objetos referentes aos registros de uma tabela, podemos utilizar a linguagem de consulta do JPA, a JPQL, que muito parecida com a linguagem SQL. A principal vantagem do JPQL em relao ao SQL que a sintaxe do JPQL no depende do SGDB utilizado.
1 2 Query query = manager . createQuery ( " SELECT e FROM Editora e " ) ; List < Editora > editoras = query . getResultList () ;
Cdigo Java 3.11: Obtendo uma lista de objetos com informaes do banco de dados
www.facebook.com/k19treinamentos
47
JPA 2 E H IBERNATE
48
Transaes
As modicaes realizadas nos objetos administrados por um EntityManager so mantidas em memria. Em certos momentos, necessrio sincronizar os dados da memria com os dados do banco de dados. Essa sincronizao deve ser realizada atravs de uma transao JPA criada pelo EntityManager que administra os objetos que desejamos sincronizar. Para abrir uma transao, utilizamos o mtodo begin().
1 manager . getTransaction () . begin () ;
Cdigo Java 3.12: Abrindo uma transao
Com uma transao aberta, podemos sincronizar os dados da memria com os dados do banco atravs do mtodo commit().
1 2 3 4 5 Editora editora = manager . find ( Editora . class , 1 L ) ; editora . setNome ( " K19 - Livros e Publicaes " ) ; manager . getTransaction () . begin () ; manager . getTransaction () . commit () ;
Cdigo Java 3.13: Sincronizando com o mtodo commit()
Exerccios de Fixao
No arquivo de conguraes persistence.xml, altere o valor da propriedade hibernate.hbm2ddl.auto para update. Assim, as tabelas no sero recriadas a cada execuo e sim apenas atualizadas.
14 15
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27
48
www.k19.com.br
49
JPA 2 E H IBERNATE
16
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19
Repository
A interface EntityManager do JPA oferece recursos sucientes para que os objetos do domnio sejam recuperados ou persistidos no banco de dados. Porm, em aplicaes com alta complexidade e grande quantidade de cdigo, espalhar as chamadas aos mtodos do EntityManager pode gerar diculdades na manuteno e no entendimento do sistema. Para melhorar a organizao das nossas aplicaes, diminuindo o custo de manuteno e aumentando a legibilidade do cdigo, podemos aplicar o padro Repository do DDD (Domain Driven Design). Conceitualmente, um repositrio representa o conjunto de todos os objetos de um determinado tipo. Ele deve oferecer mtodos para recuperar e para adicionar elementos. Os repositrios podem trabalhar com objetos prontos na memria ou reconstrui-los com dados obtidos de um banco de dados. O acesso ao banco de dados pode ser realizado atravs de ferramentas ORM como o Hibernate.
Mais Sobre
O padro Repository semelhante ao padro DAO - Data Access Object.
1 2 3 4 5 6
class EditoraRepository { private EntityManager manager ; public EditoraRepository ( EntityManager manager ) { this . manager = manager ; }
www.facebook.com/k19treinamentos
49
JPA 2 E H IBERNATE
7 8 9 1 11 12 13 14 15 16 17 18
50
public void adiciona ( Editora e ) { this . manager . persist ( e ) ; } public Editora busca ( Long id ) { return this . manager . find ( Editora . class , id ) ; } public List < Editora > buscaTodas () { Query query = this . manager . createQuery ( " SELECT e FROM Editora e " ) ; return query . getResultList () ; } }
Cdigo Java 3.16: EditoraRepository.java
1 2 3 4 5 6 7
EntityManagerFactory factory =
EntityManager manager = factory . createEntityManager () ; EditoraRepository editoraRepository = new EditoraRepository ( manager ) ; List < Editora > editoras = editoraRepository . buscaTodas () ;
Cdigo Java 3.17: Utilizando um repositrio
Exerccios de Fixao
17
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18
18
1 2 3 4 5 6 7 8 9 1
50
www.k19.com.br
51
11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 Editora novaEditora = new Editora () ; Scanner entrada = new Scanner ( System . in ) ; System . out . println ( " Digite o nome da editora : " ) ; novaEditora . setNome ( entrada . nextLine () ) ; System . out . println ( " Digite o email da editora : " ) ; novaEditora . setEmail ( entrada . nextLine () ) ; editoraRepository . adiciona ( novaEditora ) ; manager . getTransaction () . begin () ; manager . getTransaction () . commit () ; manager . close () ; factory . close () ; } }
Cdigo Java 3.19: InsereEditoraComJPA.java
JPA 2 E H IBERNATE
19
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2
www.facebook.com/k19treinamentos
51
JPA 2 E H IBERNATE
52
52
www.k19.com.br
CAPTULO
W EB C ONTAINER
HTTP
Os usurios de uma aplicao web utilizam navegadores (browsers) para interagir com essa aplicao. A comunicao entre navegadores e uma aplicao web realizada atravs de requisies e respostas denidas pelo protocolo HTTP . Dessa forma, os desenvolvedores de aplicao web devem estar preparados para trabalhar com o protocolo HTTP.
Acesso simultneo
Alm disso, na grande maioria dos casos, as aplicaes web devem ser acessadas por diversos usurios ao mesmo tempo. Consequentemente, os desenvolvedores web devem criar ou utilizar algum mecanismo eciente que permita esse tipo de acesso.
Contedo dinmico
As pginas de uma aplicao web devem ser geradas dinamicamente. Por exemplo, quando um usurio de uma aplicao de email acessa a sua caixa de entrada, ele deseja ver todos os emails enviados at aquele momento. A pgina contendo a lista de emails deve ser gerada novamente toda vez que essa pgina for requisitada. Consequentemente, os desenvolvedores web devem criar ou utilizar algum mecanismo eciente que permita que o contedo das pginas das aplicaes web seja gerado dinamicamente.
www.facebook.com/k19treinamentos
53
W EB C ONTAINER
54
Aplicao Web
Requisio HTTP
TP
HT
qu
isi
Re
www.k19.com.br
www.k19.com.br
Cursos
Artigos
Apostilas
Soluo
Resolver os trs problemas apresentados tomaria boa parte do tempo de desenvolvimento, alm de exigir conhecimentos tcnicos extremamente especcos por parte dos desenvolvedores. Para facilitar o desenvolvimento de aplicaes web, a plataforma Java oferece uma soluo genrica que pode ser utilizada para desenvolver aplicaes web. Conheceremos essa soluo a seguir.
Aplicao Web
Web Container
Requisio HTTP
TP
HT
qu
isi
www.k19.com.br
Re
www.k19.com.br
Cursos
Artigos
Apostilas
54
www.k19.com.br
q Re P TT
www.k19.com.br
ui sp Re os H ta
o i
HT
TP
qu Re aH st TT P
www.k19.com.br
isi Re o sp
HT
TP
Resposta HTTP Resposta HTTP
Re sp o st a HT TP Re s po st a HT TP
55
W EB C ONTAINER
Web Container
Uma aplicao web Java deve ser implantada em um Web Container para obter os recursos fundamentais que ela necessita. Um Web Container responsvel: Pelo envio e recebimento de mensagens HTTP. Por permitir que as aplicaes sejam acessadas simultaneamente por vrios usurios de uma maneira eciente. Por permitir que as pginas de uma aplicao web sejam geradas dinamicamente. Os dois Web Containers mais importantes do mercado so Tomcat e Jetty. Tambm podemos utilizar um servidor de aplicao Java EE como o JBoss, Glasssh ou WebSphere, pois eles possuem um Web Container internamente.
Servlet e Java EE
Como comum na plataforma Java, foi denida uma especicao para padronizar a interface dos recursos oferecidos pelos Web Containers. Essa especicao chamada Servlet e atualmente est na verso 3. Para consult-la, acesse http://jcp.org/en/jsr/detail?id=315. A especicao Servlet faz parte do Java EE. O Java EE uma especicao que agrupa diversas outras especicaes. Para consult-la, acesse http://jcp.org/en/jsr/detail?id=316. Apesar das especicaes, os Web Containers possuem algumas diferenas nas conguraes que devem ser realizadas pelos desenvolvedores. Dessa forma, no h 100% de portabilidade. Contudo, a maior parte das conguraes e do modelo de programao padronizado. Sendo assim, se voc conhece bem um dos Web Containers, tambm conhece bastante dos outros. Neste treinamento, optamos pela utilizao do servidor de aplicao Glasssh 3.0. Esse servidor segue a especicao Java EE 6 e portanto contm um Web Container. Mostraremos, a seguir, a sua instalao e congurao.
Mais Sobre
Consulte os artigos da K19 sobre instalao e congurao do Glasssh para mais detalhes.
http://www.k19.com.br/artigos/instalando-glassfish/ http://www.k19.com.br/artigos/configurando-o-gassfish-no-ide-eclipse/
Exerccios de Fixao
1
55
W EB C ONTAINER
56
Finalize o Glasssh executando o script stopserv, que est na mesma pasta do script startserv.
5 No Eclipse, abra a view Servers e clique com o boto direito no corpo dela. Escolha a opo new e congure o Glasssh.
Inicialize o Glasssh pela view Servers e verique se ele est funcionando, acessando http: //localhost:8 8 .
6 7
Mais Sobre
Consulte o artigo da K19 sobre criao de projetos web utilizando o Eclipse.
http://www.k19.com.br/artigos/criando-um-dynamic-web-project/
56
www.k19.com.br
57
W EB C ONTAINER
Exerccios de Fixao
No Eclipse, crie um projeto do tipo Dynamic Web Project chamado K19-App. Escolha Glasssh como opo para Target runtime. Na ltima tela de criao do projeto, selecione a opo Generate web.xml deployment descriptor.
8
Adicione o projeto K19-App no Glasssh atravs da view Servers. Clique com o boto direito do mouse no Glasssh e selecione Add and Remove. . . .
9
Inicialize o Glasssh atravs da view Servers. Clique com o boto direito do mouse sobre o Glasssh e escolha a opo Start.
10
Processando requisies
Aps implantar a nossa aplicao web Java em um Web Container, as requisies e respostas HTTP j esto sendo processadas pelo Web Container, que tambm j permite o acesso de mltiplos usurios nossa aplicao. Em seguida, devemos denir como o contedo das pginas da aplicao gerado. Para isso, podemos criar uma Servlet.
Servlet
Para criar uma Servlet, podemos seguir os seguintes passos: 1. Criar uma classe. 2. Herdar da classe javax.servlet.http.HttpServlet. 3. Reescrever o mtodo service(). 4. Utilizar a anotao @WebServlet para denir a url que ser utilizada para acessar a Servlet. Essa anotao existe aps a especicao Servlet 3.0. Antes, essa congurao era realizada atravs do arquivo web.xml.
1 2 3 4 5 6 7 8 9
@WebServlet ( " / OlaMundo " ) public class OlaMundo extends HttpServlet { @Override protected void service ( HttpServletRequest req , HttpServletResponse resp ) throws ServletException , IOException { // Lgica para processar as regras de negcio e gerar contedo } }
Cdigo Java 4.1: OlaMundo.java
www.facebook.com/k19treinamentos
57
W EB C ONTAINER
58
O mtodo service() executado toda vez que uma requisio HTTP realizada para a url denida na anotao @WebServlet. Esse mtodo recebe dois parmetros. O primeiro a referncia do objeto da classe HttpServletRequest que armazena todos os dados da requisio. O segundo parmetro a referncia do objeto da classe HttpServletResponse que armazenar o contedo gerado pela Servlet.
Exerccios de Fixao
12 13
Crie um pacote chamado servlets no projeto K19-App. Crie uma classe chamada OlaMundo no pacote servlets.
@WebServlet ( " / OlaMundo " ) public class OlaMundo extends HttpServlet { @Override protected void service ( HttpServletRequest req , HttpServletResponse resp ) throws ServletException , IOException { PrintWriter writer = resp . getWriter () ; writer . println ( " < html > < body > < h1 > Ol Mundo </ h1 > </ body > </ html > " ) ; } }
Cdigo Java 4.3: OlaMundo.java
1 2 3 4 5 6 7 8 9 1
14
http://localhost:8 8 /K19-App/OlaMundo
Frameworks
Hoje em dia, improvvel que uma empresa decida comear um projeto utilizando diretamente Servlets, pois a produtividade seria pequena e a manuteno muito custosa. Vrios frameworks fo58
www.k19.com.br
59
W EB C ONTAINER
ram criados para facilitar o desenvolvimento e a manuteno de aplicaes web. Apesar de serem baseados em Servlets, esses frameworks oferecem diversos recursos adicionais para as aplicaes. Eis uma lista dos principais frameworks para aplicaes web Java: JSF Struts 1.x Struts 2.x Spring MVC
TP
HT
isi
qu
www.k19.com.br
Re
www.k19.com.br
Cursos
Artigos
Apostilas
Nos prximos captulos, mostraremos o funcionamento e explicaremos os conceitos relacionados ao framework Struts 2.
Re HT TP
www.k19.com.br
qu Re sp ta os
o isi
HT
TP
Resposta HTTP
Re sp os ta
www.facebook.com/k19treinamentos
HT TP
59
W EB C ONTAINER
60
60
www.k19.com.br
CAPTULO
Struts 2 um framework para desenvolvimento de aplicaes web em Java. A documentao desse framework pode ser obtida em http://struts.apache.org/2.x/. O Struts 2 fortemente baseado nos padres MVC e Front Controller.
Modelo: encapsula os dados e as funcionalidades da aplicao. Viso: responsvel pela exibio de informaes, cujos dados so obtidos do modelo. Controlador: recebe as requisies do usurio e aciona o modelo e/ou a viso.
Para mais detalhes sobre o padro MVC, uma boa referncia o livro Pattern-Oriented Software Architecture Volume 1: A System of Patterns (editora Wiley, 1996) dos autores Frank Buschmann, Regine Meunier, Hans Rohnert, Peter Sommerlad, Michael Stal e Michael Stal. No padro Front Controller, todas as requisies do usurio so recebidas pelo mesmo componente. Dessa forma, tarefas que devem ser realizadas em todas as requisies podem ser implementadas por esse componente. Isso evita a repetio de cdigo e facilita a manuteno do sistema. Para mais informaes sobre esse padro, consulte, por exemplo, o livro Core J2EE Patterns: Best Practices and Design Strategies (editora Prentice Hall, 2003, segunda edio) dos autores Deepak Alur, Dan Malks e John Crupi.
Bibliotecas
As bibliotecas do Struts podem ser obtidas na pgina de download desse framework (http:// struts.apache.org/download.cgi). Neste treinamento, utilizaremos a verso 2.3.1.2 do Struts. Fazendo download do arquivo struts-2.3.1.2-all.zip e descompactando-o, voc obter as bibliotecas, o cdigo fonte, alguns exemplos e a documentao do Struts 2.3.1.2.
www.facebook.com/k19treinamentos
61
62
A pasta struts-2.3.1.2/lib contm 82 arquivos .jar. Esses arquivos so as dependncias do Struts 2.3.1.2. Desses arquivos, apenas 10 so obrigatrios. Os outros podem ser adicionados conforme a necessidade. Eis a lista dos 10 jars obrigatrios: commons-leupload-1.2.2.jar commons-io-2.0.1.jar commons-lang-2.5.jar commons-logging-1.1.1.jar commons-logging-api.1.1.jar freemarker-2.3.18.jar ognl-3.0.4.jar struts2-core-2.3.1.2.jar xwork-core-2.3.1.2.jar javassist-3.11.0.GA.jar Os arquivos .jar devem ser adicionadas na pasta WEB-INF/lib da aplicao.
web.xml
O ltro do Struts deve ser congurado no arquivo WEB-INF/web.xml, indicando a classe que o implementa e o padro de url que ser associado a esse ltro. Por exemplo, na congurao abaixo, todas as requisies que correspondem ao padro de url /* sero processadas pelo ltro do Struts.
1 2 3 4 5 6 7 8 9 1 11 < filter > < filter - name > struts2 </ filter - name > < filter - class > org . apache . struts2 . dispatcher . ng . filter . StrutsPrepareAndExecuteFilter </ filter - class > </ filter > < filter - mapping > < filter - name > struts2 </ filter - name > <url - pattern > /* </ url - pattern > </ filter - mapping >
Cdigo XML 5.1: web.xml
63
struts.xml
Diversas conguraes especcas do Struts podem ser realizadas atravs do arquivo struts.xml. Esse arquivo deve estar na raiz do class path da aplicao web. Utilizando a IDE eclipse, podemos deni-lo em uma source folder.
1 2 3 4 5 6 7 8 9 1 11 12 13 <? xml version = " 1. " encoding = " UTF -8 " ? > <! DOCTYPE struts PUBLIC " -// Apache Software Foundation // DTD Struts Configuration 2. // EN " " http: // struts . apache . org / dtds / struts -2. . dtd " > < struts > < constant name = " struts . devMode " value = " true " / > < package name = " default " extends = " struts - default " > < action name = " index " > < result >/ Index </ result > </ action > </ package > </ struts >
Cdigo XML 5.2: struts.xml
Logging
Com intuito de encontrar mais facilmente os erros nas nossas aplicaes, podemos ativar o logging do Struts. Para isso, devemos adicionar o arquivo log4j-1.2.14.jar na pasta WEB-INF/lib da aplicao. Esse arquivo pode ser obtido em http://archive.apache.org/dist/logging/log4j/ 1.2.14/. Alm disso, devemos denir as conguraes de logging atravs do arquivo log4j.xml. Esse arquivo deve estar no class path da aplicao. Utilizando a IDE eclipse, podemos deni-lo em uma source folder.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 <? xml version = " 1. " encoding = " UTF -8 " ? > <! DOCTYPE log4j:configuration PUBLIC " -// log4j / log4j Configuration // EN " " log4j . dtd " > < log4j:configuration xmlns:log4j = " http: // jakarta . apache . org / log4j / " > < appender name = " STDOUT " class = " org . apache . log4j . ConsoleAppender " > < layout class = " org . apache . log4j . PatternLayout " > < param name = " ConversionPattern " value = " % d % -5 p % c .% M: % L - % m % n " / > </ layout > </ appender > < logger name = " org . apache . struts2 " > < level value = " DEBUG " / > </ logger > < root > < priority value = " INFO " / > < appender - ref ref = " STDOUT " / > </ root > </ log4j:configuration >
Cdigo XML 5.3: log4j.xml
Actions
www.facebook.com/k19treinamentos
63
64
As actions so componentes fundamentais de uma aplicao Struts. Suas principais tarefas so:
1. Fornecer dados que sero exibidos nas telas. 2. Receber os dados enviados nas requisies. 3. Executar tarefas de acordo com as aes dos usurios.
1 2 3 4 5
... < action name = " Teste " class = " br . com . k19 . actions . TesteAction " > ... </ action > ...
Cdigo XML 5.4: struts.xml
No registro de uma action, devemos denir o seu nome e a sua classe. O nome ser utilizado para acess-la atravs de um navegador.
Mtodos de Ao
Podemos denir, na classe de uma action, o mtodo que dever ser executado toda vez que a action for acionada. Por padro, esse mtodo possui a seguinte estrutura:
1 2 3 4 5 6 7 package br . com . k19 . actions ; public class TesteAction extends ActionSupport { public String execute () throws Exception { ... } }
Cdigo Java 5.2: TesteAction.java
O resultado do mtodo execute() pode ser utilizado para denir a prxima pgina a ser construda. Os resultados devem ser mapeados no arquivo struts.xml.
1 2 ... < action name = " Teste " class = " br . com . k19 . actions . TesteAction " >
64
www.k19.com.br
65
3 4 5 < result name = " success " >/ Teste . jsp </ result > </ action > ...
Cdigo XML 5.5: struts.xml
Podemos escolher um nome diferente para o mtodo que ser executado quando a action for acionada. Para isso, necessrio congurar o nome desse mtodo no arquivo struts.xml.
1 2 3 4 5 6 7 package br . com . k19 . actions ; public class TesteAction extends ActionSupport { public String teste () throws Exception { ... } }
Cdigo Java 5.3: TesteAction.java
1 2 3 4 5
... < action name = " Teste " method = " teste " class = " br . com . k19 . actions . TesteAction " > < result name = " success " >/ Teste . jsp </ result > </ action > ...
Cdigo XML 5.6: struts.xml
Para evitar erros de digitao e padronizar as possveis respostas de uma action, a interface
Action dene um conjunto de resultados padro atravs de algumas constantes. A classe ActionSupport implementa a interface Action.
SUCCESS NONE ERROR INPUT LOGIN Podemos utilizar essas constantes nos mtodos de ao.
1 2 3 4 5 6 7 8 package br . com . k19 . actions ; public class TesteAction extends ActionSupport { public String teste () throws Exception { ... return TesteAction . SUCCESS ; } }
Cdigo Java 5.4: TesteAction.java
Propriedades
Considere a seguinte action.
www.facebook.com/k19treinamentos
65
66
Para acessar o valor do atributo numero em uma pgina, precisamos denir um mtodo de leitura. Esse mtodo deve seguir a conveno de nomenclatura do Java. Veja o exemplo abaixo:
1 2 3 4 5 6 7 8 9 1 11 12 13 14 package br . com . k19 . actions ; public class TesteAction extends ActionSupport { private int numero ; public String execute () throws Exception { ... } public int getNumero () { return numero ; } }
Cdigo Java 5.6: TesteAction.java
Note que o nome do mtodo comea com get e seguido pelo nome do atributo com a primeira letra em caixa alta. Para alterar o valor do atributo numero com valores obtidos atravs de uma pgina, precisamos denir um mtodo de escrita.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 package br . com . k19 . actions ; public class TesteAction extends ActionSupport { private int numero ; public String execute () throws Exception { ... } public int getNumero () { return numero ; } public int setNumero ( int numero ) { this . numero = numero ; } }
Cdigo Java 5.7: TesteAction.java
O nome do mtodo de escrita deve, necessariamente, comear com a palavra set e terminar com o nome do atributo com a primeira letra em caixa alta.
66
www.k19.com.br
67
Com os mtodos de acesso j implementados, podemos exibir o valor do atributo nas pginas de resultado da action TesteAction atravs da tag <s:property>. Para utilizar essa tag, devemos adicionar a diretiva taglib nas pginas. Veja o exemplo a seguir.
1 2 3 4 5 6 7 8 9 1 <% @ taglib prefix = " s " uri = " / struts - tags " % > < html > < head > < title > Teste </ title > </ head > < body > < h1 > Teste </ h1 > < s:property value = " numero " / > </ body > </ html >
Cdigo JSP 5.1: Exibindo o valor do atributo numero
Para alterar o valor do atributo numero da action testeBean, podemos vincul-lo, por exemplo, a uma caixa de texto em um formulrio. Observe o cdigo abaixo.
1 2 3 4 5 6 7 8 9 1 11 12 <% @ taglib prefix = " s " uri = " / struts - tags " % > < html > < head > < title > Formulrio </ title > </ head > < body > < s:form action = " Teste " > < s:textfield name = " numero " / > < s:submit value = " Enviar " / > </ s:form > </ body > </ html >
Cdigo JSP 5.2: Alterando o valor do atributo numero
Importante
importante destacar que o vnculo com uma propriedade de uma action d-se por meio dos nomes dos mtodos getters e setters, e no pelo nome do atributo. Nos exemplos acima, se mantivssemos o nome do atributo da action mas substitussemos os nomes dos mtodos getNumero() e setNumero() por getValor() e setValor(), respectivamente, ento o valor do atributo value da tag <s:property> e valor do atributo name da tag <s:textfield> devem ser alterados.
1 < s:property value = " valor " / >
Exemplo Prtico
Com as conguraes j realizadas, implementaremos uma aplicao que mostra o funcionamento bsico do Struts. Essa aplicao dever receber um texto do usurio e exibi-lo em letras maisculas.
www.facebook.com/k19treinamentos
67
68
Action
Vamos comear criando uma action para armazenar o texto enviado pelo usurio e a lgica para transform-lo.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 package br . com . k19 . actions ; import com . opensymphony . xwork2 . ActionSupport ; @SuppressWarnings ( " serial " ) public class TextoAction extends ActionSupport { private String texto ; @Override public String execute () throws Exception { this . texto = this . texto . toUpperCase () ; return TextoAction . SUCCESS ; } public String getTexto () { return texto ; } public void setTexto ( String texto ) { this . texto = texto ; } }
Cdigo Java 5.8: TextoBean.java
A classe que implementa a action deve herdar de ActionSupport. O atributo texto armazenar o texto enviado pelo usurio e esse texto ser modicado pelo mtodo execute(). Esse mtodo devolve uma string para indicar qual deve ser a prxima pgina a ser enviada para o usurio. O Struts utilizar o mtodo setTexto() para armazenar o texto enviado pelo usurio na action. Por outro lado, utilizar o mtodo getTexto() para recuperar o texto e exibi-lo aps a sua modicao. No arquivo struts.xml, devemos registrar a action TextoAction.
1 2 3 4 5 ... < action name = " Texto " class = " br . com . k19 . actions . TextoAction " > < result name = " success " >/ Texto . jsp </ result > </ action > ...
Cdigo XML 5.7: struts.xml
Telas
Aps a criao da action, podemos associ-la a um formulrio que receber o texto do usurio.
1 2 3 4 5 6 7 <% @ taglib prefix = " s " uri = " / struts - tags " % > < html > < head > < title > K19 Treinamentos </ title > </ head > < body > < s:form action = " Texto " >
68
www.k19.com.br
69
8 9 1 11 12 < s:textfield name = " texto " / > < s:submit value = " Enviar " / > </ s:form > </ body > </ html >
Observe nas linhas em destaque a ligao entre essa tela e a action. A caixa de entrada de texto foi associada propriedade texto da action TextoAction. O formulrio, por sua vez, foi associado action TextoAction. A tela de resultado deve apresentar o texto alterado.
1 2 3 4 5 6 7 8 9 1 11 <% @ taglib prefix = " s " uri = " / struts - tags " % > < html > < head > < title > K19 Treinamentos </ title > </ head > < body > < h1 > Texto em Caixa Alta </ h1 > < s:property value = " texto " / > </ body > </ html > </ html >
Exerccios de Fixao
Como exerccio, desenvolva uma aplicao Struts que (i) receba um nmero inteiro do usurio, (ii) produza um nmero aleatrio entre zero e o nmero recebido, e (iii) exiba esse nmero na tela do navegador do usurio. No Eclipse, crie um Dynamic Web Project chamado K19-Visao-Geral. Na primeira tela, devemos denir o nome do projeto e selecionar o target runtime.
1
www.facebook.com/k19treinamentos
69
70
Na prxima tela, selecione a opo para gerar o arquivo web.xml e depois clique no boto Finish.
70
www.k19.com.br
71
Adicione as bibliotecas do Struts na pasta WEB-INF/lib. Lembre-se que os arquivos das bibliotecas podem ser obtidos na pgina de download do Struts, http://struts.apache.org/download. cgi, baixando o arquivo struts-2.3.1.2-all.zip. Adicione apenas os jars obrigatrios na pasta WEB-INF/lib.
2
commons-leupload-1.2.2.jar commons-io-2.0.1.jar commons-lang-2.5.jar commons-logging-1.1.1.jar commons-logging-api.1.1.jar freemarker-2.3.18.jar ognl-3.0.4.jar struts2-core-2.3.1.2.jar xwork-core-2.3.1.2.jar javassist-3.11.0.GA.jar
3
1 2 3 4 5 6 7 8
www.facebook.com/k19treinamentos
71
72
1 2 3 4 5 6 7 8 9 1 11
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2
Crie um pacote chamado br.com.k19.actions. Nesse pacote, crie uma action para armazenar o nmero inteiro n enviado pelo usurio, gerar um nmero aleatrio entre zero e n e armazen-lo
6
72
www.k19.com.br
73
numa propriedade.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 package br . com . k19 . actions ; import com . opensymphony . xwork2 . ActionSupport ; @SuppressWarnings ( " serial " ) public class NumeroAleatorioAction extends ActionSupport { private int maximo ; private int numeroAleatorio ; public String execute () throws Exception { this . numeroAleatorio = ( int ) ( Math . random () * this . maximo ) ; return NumeroAleatorioAction . SUCCESS ; } // GETTERS E SETTERS }
Cdigo Java 5.9: NumeroAleatorioAction.java
1 2 3 4 5 6 7 8 9 1 11 12 13 14
Agora, na pasta WebContent, crie um formulrio para que o usurio possa enviar o dado de entrada.
8
1 2 3 4 5 6 7 8 9 1 11 12 13 14
<% @ taglib prefix = " s " uri = " / struts - tags " % > < html > < head > < title > K19 Viso Geral </ title > </ head > < body > < s:form action = " NumeroAleatorio " > < s:label value = " Nmero Mximo " / > < s:textfield name = " maximo " / > < s:submit value = " Gera nmero aleatrio " / > </ s:form > </ body > </ html >
Cdigo JSP 5.7: Formulario.jsp
Tambm na pasta WebContent, dena uma tela para exibir o nmero gerado aleatoriamente.
<% @ taglib prefix = " s " uri = " / struts - tags " % >
www.facebook.com/k19treinamentos
73
74
10
1. Abra a aba Servers. Para isso, pressione Ctrl+3. Na janela que abrir, digite Servers e pressione Enter. 2. Na aba Servers, clique com o boto direito do mouse no GlassFish e selecione a opo Add and Remove. . . . 3. Selecione o projeto K19-Visao-Geral e clique em Add >. Em seguida, clique em Finish. 4. Inicialize o servidor. Para isso, clique mais uma vez no GlassFish com o boto direito e selecione Start. 5. Acesse a aplicao no endereo
http://localhost:8 8 /K19-Visao-Geral/Formulario.jsp.
74
www.k19.com.br
CAPTULO
Como vimos nos primeiros captulos, os SGDBs so utilizados para armazenar os dados manipulados pelas aplicaes. At agora, no discutimos como aplicaes Struts podem armazenar dados em um SGDB atravs dos recursos denidos pelo JPA. Adicionaremos essa capacidade s aplicaes Struts neste captulo. Para isso, mostraremos uma maneira de integrar os recursos do Struts e do JPA.
Bibliotecas
Para utilizar os recursos do JPA em uma aplicao Struts, os jars do provedor JPA e do driver JDBC que sero utilizados devem estar no classpath da aplicao. No captulo anterior, a aplicao Struts desenvolvida nos exerccios foi implantadas no Glasssh 3.0.1 que um servidor de aplicao Java EE 6. Por padro, a verso 3.0.1 do Glasssh possui os jars do provedor JPA EclipseLink. Dessa forma, as aplicaes Struts implantadas nessa verso do Glasssh utilizaro o EclipseLink como implementao do JPA. Contudo, queremos utilizar o provedor JPA Hibernate. Podemos facilmente substituir os jars do EclipseLink pelos jars do Hibernate atravs da interface de administrao do Glasssh.
Mais Sobre
Consulte o artigo da K19 sobre a substituio dos jars do provedor JPA EclipseLink pelos jars do provedor JPA Hibernate.
http://www.k19.com.br/artigos/configurando-hibernate-no-glassfish-3-1/
Utilizaremos o MySQL Server como SGDB. Dessa forma, devemos adicionar o driver JDBC do MySQL Server no classpath das aplicaes Struts. O Glasssh 3.0.1 no possui os jars desse driver JDBC. Contudo, podemos adicion-los manualmente. Para isso, basta acrescentar os jars do driver JDBC do MySQL em uma pasta apropriada do Glasssh. Nos exerccios deste captulo, mostraremos como realizar tal tarefa.
Congurao
Como vimos no Captulo 3, devemos congurar as unidades de persistncia utilizadas atravs do arquivo persistence.xml da pasta META-INF do classpath da aplicao.
1 2 3 4 <? xml version = " 1. " encoding = " UTF -8 " ? > < persistence version = " 2. " xmlns = " http: // java . sun . com / xml / ns / persistence " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance "
www.facebook.com/k19treinamentos
75
76
Mapeamento
Tambm devemos denir o mapeamento das entidades. No Captulo 3, vimos como utilizar as anotaes do JPA para estabelecer esse mapeamento.
1 2 3 4 5 6 7 8 9 1 11 @Entity public class Produto { @Id @GeneratedValue private Long id ; private String nome ; private Double preco ; // GETTERS e SETTERS }
Cdigo Java 6.1: Produto.java
Inicializao e Finalizao
As unidades de persistncia devem ser inicializadas antes de serem utilizadas, e nalizadas quando no forem mais necessrias. A inicializao e a nalizao de uma unidade de persistncia devem ser realizadas apenas uma vez durante a execuo da aplicao. Para implementar essa caracterstica em aplicaes web Java, podemos utilizar um ltro. Os ltros de uma aplicao web Java so inicializados automaticamente depois que a aplicao implantada no Web Container e antes da primeira requisio HTTP. Alm disso, eles so nalizados ao trmino da execuo da aplicao. Para adicionar um ltro em uma aplicao web Java, necessrio criar uma classe que implemente a interface javax.servlet.Filter.
76
www.k19.com.br
77
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 public class JPAFilter implements Filter { private EntityManagerFactory factory ;
@Override public void init ( FilterConfig filterConfig ) throws ServletException { this . factory = Persistence . createEntityManagerFactory ( " K19 - PU " ) ; } @Override public void destroy () { this . factory . close () ; } @Override public void doFilter ( ServletRequest request , ServletResponse response , FilterChain chain ) throws IOException , ServletException { // por enquanto vazio } }
Cdigo Java 6.2: JPAFilter.java
Um ltro pode ser registrado no Web Container atravs do arquivo web.xml. Nesse registro, podemos denir a ordem na qual os ltros devem ser executados. No exemplo abaixo, o ltro denido pela classe JPAFilter executar antes do ltro do Struts. Alm disso, ele est mapeado para o mesmo padro de url.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 <? xml version = " 1. " encoding = " UTF -8 " ? > <web - app xmlns:xsi = " http: // www . w3 . org /2 1/ 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 / javaee http: // java . sun . com / xml / ns / javaee / web - app_3_ . xsd " id = " WebApp_ID " version = " 3. " > < display - name >K19 - Visao - Geral - Struts </ 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 > < filter > < filter - name > JPAFilter </ filter - name > < filter - class > br . com . k19 . filtros . JPAFilter </ filter - class > </ filter > < filter - mapping > < filter - name > JPAFilter </ filter - name > <url - pattern > /* </ url - pattern > </ filter - mapping > < filter > < filter - name > struts2 </ filter - name > < filter - class > org . apache . struts2 . dispatcher . ng . filter . StrutsPrepareAndExecuteFilter </ filter - class > </ filter > < filter - mapping > < filter - name > struts2 </ filter - name > <url - pattern > /* </ url - pattern >
www.facebook.com/k19treinamentos
77
78
O mtodo init() chamado automaticamente na inicializao do ltro. No exemplo acima, esse mtodo inicializa a unidade de persistncia K19-PU. O mtodo destroy() chamado automaticamente para desativar o ltro no encerramento da aplicao. No exemplo acima, nalizamos a unidade de persistncia K19-PU.
Transaes
Como vimos no Captulo 3, para atualizar as informaes armazenadas no SGDB de acordo com os dados da memria da aplicao, devemos abrir uma transao e conrm-la atravs do mtodo commit(). O ltro criado anteriormente para controlar a inicializao e nalizao das unidades de persistncia pode tambm gerenciar a abertura e a conrmao das transaes da aplicao. Para isso, utilizaremos o mtodo doFilter() desse ltro.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 public class JPAFilter implements Filter { private EntityManagerFactory factory ; @Override public void init ( FilterConfig filterConfig ) throws ServletException { this . factory = Persistence . createEntityManagerFactory ( " K19 - PU " ) ; } @Override public void destroy () { this . factory . close () ; } @Override public void doFilter ( ServletRequest request , ServletResponse response , FilterChain chain ) throws IOException , ServletException { // CHEGADA EntityManager manager = this . factory . createEntityManager () ; request . setAttribute ( " EntityManager " , manager ) ; entityManager . getTransaction () . begin () ; // CHEGADA // FILTRO DO STRUTS chain . doFilter ( request , response ) ; // FILTRO DO STRUTS // SADA try { entityManager . getTransaction () . commit () ; } catch ( Exception e ) { entityManager . getTransaction () . rollback () ; } finally { entityManager . close () ; } // SADA } }
Cdigo Java 6.3: JPAFilter.java
78
www.k19.com.br
79
No exemplo acima, o mtodo doFilter() chamado quando uma requisio com o padro de url /* realizada. Antes de repassar a requisio para o ltro do Struts, o mtodo doFilter() cria um EntityManager, armazena-o na requisio e abre uma transao. Depois que o ltro do Struts terminar o seu processamento, o mtodo doFilter() tenta conrmar a transao atravs do mtodo commit(). Se um erro ocorrer nessa tentativa, o mtodo rollback() chamado para cancelar a transao.
Exerccios de Fixao
Entre na pasta K19-Arquivos/MySQL-Connector-JDBC da rea de Trabalho e copie o arquivo mysql-connector-java-5.1.13-bin.jar para pasta glassfishv3/glassfish/lib tambm da sua rea de Trabalho. OBS: O Glasssh deve ser reiniciado para reconhecer o driver JDBC do MySQL.
1
Crie um projeto do tipo Dynamic Web Project chamado K19-Integracao-Struts-JPA seguindo os passos vistos nos exerccios 1 ao 5 do Captulo 5.
2 3 4
Adicione uma pasta chamada META-INF na pasta src do projeto K19-Integracao-Struts-JPA. Congure o JPA adicionando o arquivo persistence.xml na pasta src/META-INF.
<? xml version = " 1. " encoding = " UTF -8 " ? > < persistence version = " 2. " xmlns = " http: // java . sun . com / xml / ns / persistence " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance " xsi:schemaLocation = " http: // java . sun . com / xml / ns / persistence http: // java . sun . com / xml / ns / persistence / persistence_2_ . xsd " > < persistence - unit name = " K19 - PU " transaction - type = " RESOURCE_LOCAL " > < provider > org . hibernate . ejb . HibernatePersistence </ provider > < properties > < property name = " hibernate . dialect " value = " org . hibernate . dialect . MySQL5InnoDBDialect " / > < property name = " hibernate . hbm2ddl . auto " value = " update " / > < property name = " javax . persistence . jdbc . driver " value = " com . mysql . jdbc . Driver " / > < property name = " javax . persistence . jdbc . user " value = " root " / > < property name = " javax . persistence . jdbc . password " value = " root " / > < property name = " javax . persistence . jdbc . url " value = " jdbc:mysql: // localhost:33 6 / K19_DB " / >
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2
www.facebook.com/k19treinamentos
79
80
Abra um terminal; entre no cliente do MySQL Server; apague se existir a base de dados K19-DB; e crie uma base de dados nova chamada K19-DB.
5
k19@k19 -11:~/ rafael$ mysql -u root -p Enter password : Welcome to the MySQL monitor . Commands end with ; or \ g . Your MySQL connection id is 36 Server version : 5.1.58 -1 ubuntu1 ( Ubuntu ) Copyright ( c ) 2 , 2 1 , Oracle and / or its affiliates . All rights reserved . This software comes with ABSOLUTELY NO WARRANTY . This is free software , and you are welcome to modify and redistribute it under the GPL v2 license Type help ; or \h for help . Type \c to clear the current input statement . mysql > DROP DATABASE IF EXISTS K19_DB ; Query OK , rows affected , 1 warning ( . mysql > CREATE DATABASE K19_DB ; Query OK , 1 row affected ( . 2 sec )
sec )
Crie um pacote chamado br.com.k19.filters na pasta src do projeto K19-Integracao-StruNo pacote br.com.k19.filters, crie uma classe chamada JPAFilter com o seguinte contedo:
package br . com . k19 . filters ; import java . io . IOException ; import javax . persistence .*; import javax . servlet .*; public class JPAFilter implements Filter { private EntityManagerFactory factory ; @Override public void init ( FilterConfig filterConfig ) throws ServletException { this . factory = Persistence . createEntityManagerFactory ( " K19 - PU " ) ; } @Override public void destroy () { this . factory . close () ; } @Override public void doFilter ( ServletRequest request , ServletResponse response , FilterChain chain ) throws IOException , ServletException { // CHEGADA EntityManager manager = this . factory . createEntityManager () ; request . setAttribute ( " EntityManager " , manager ) ; manager . getTransaction () . begin () ; // CHEGADA // FILTRO DO STRUTS chain . doFilter ( request , response ) ; // FILTRO DO STRUTS // SADA try { manager . getTransaction () . commit () ;
ts-JPA.
7
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37
80
www.k19.com.br
81
38 39 4 41 42 43 44 45 } catch ( Exception e ) { manager . getTransaction () . rollback () ; } finally { manager . close () ; } // SADA } }
Cdigo Java 6.5: JPAFilter.java
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35
Crie um pacote chamado br.com.k19.model na pasta src do projeto K19-Integracao-StruNo pacote br.com.k19.model, crie uma classe chamada Carro com o seguinte contedo:
package br . com . k19 . model ; // IMPORTS @Entity public class Carro {
ts-JPA.
10
1 2 3 4 5 6 7
www.facebook.com/k19treinamentos
81
82
Tambm no pacote br.com.k19.model, crie uma classe chamada CarroRepository com o seguinte contedo:
11
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23
package br . com . k19 . model ; import java . util . List ; import javax . persistence . EntityManager ; import javax . persistence . Query ; public class CarroRepository { private EntityManager manager ; public CarroRepository ( EntityManager manager ) { this . manager = manager ; } public void adiciona ( Carro carro ) { this . manager . persist ( carro ) ; } public List < Carro > buscaTodos () { Query query = this . manager . createQuery ( " select x from Carro x " ) ; return query . getResultList () ; } }
Cdigo Java 6.7: CarroRepository.java
12
ts-JPA.
No pacote br.com.k19.actions, crie uma classe chamada AdicionaCarroAction com o seguinte cdigo:
13
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21
package br . com . k19 . actions ; import import import import import import import java . util . List ; javax . persistence . EntityManager ; javax . servlet . http . HttpServletRequest ; org . apache . struts2 . ServletActionContext ; br . com . k19 . model . Carro ; br . com . k19 . model . CarroRepository ; com . opensymphony . xwork2 . ActionSupport ;
@SuppressWarnings ( " serial " ) public class AdicionaCarroAction extends ActionSupport { private Carro carro = new Carro () ; public String execute () throws Exception { EntityManager manager = this . getEntityManager () ; CarroRepository repository = new CarroRepository ( manager ) ; repository . adiciona ( this . carro ) ; this . carro = new Carro () ;
82
www.k19.com.br
83
22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 return AdicionaCarroAction . SUCCESS ; } public List < Carro > getCarros () { EntityManager manager = this . getEntityManager () ; CarroRepository repository = new CarroRepository ( manager ) ; return repository . buscaTodos () ; }
private EntityManager getEntityManager () { HttpServletRequest request = ServletActionContext . getRequest () ; EntityManager manager = ( EntityManager ) request . getAttribute ( " EntityManager " ) ; return manager ; } public Carro getCarro () { return carro ; } public void setCarro ( Carro carro ) { this . carro = carro ; } }
Cdigo Java 6.8: AdicionaCarroAction.java
14
tent/META-INF.
1 2 3 4 5 6 7 8 9 1 11 12 13 <? xml version = " 1. " encoding = " UTF -8 " ? > <! DOCTYPE struts PUBLIC " -// Apache Software Foundation // DTD Struts Configuration 2. // EN " " http: // struts . apache . org / dtds / struts -2. . dtd " > < struts > < constant name = " struts . devMode " value = " true " / > < package name = " default " extends = " struts - default " > < action name = " AdicionaCarro " class = " br . com . k19 . actions . AdicionaCarroAction " > < result name = " success " >/ Lista . jsp </ result > </ action > </ package > </ struts >
Cdigo XML 6.5: struts.xml
15 No diretrio WebContent, crie um arquivo JSP chamado Formulario.jsp com o seguinte contedo:
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15
<% @ taglib prefix = " s " uri = " / struts - tags " % > < html > < head > < title > K19 Treinamentos </ title > </ head > < body > < s:form action = " AdicionaCarro " > < s:label value = " Marca: " / > < s:textfield name = " carro . marca " / > < s:label value = " Modelo: " / > < s:textfield name = " carro . modelo " / > < s:submit value = " Enviar " / > </ s:form > </ body > </ html >
Cdigo JSP 6.1: Formulario.jsp
www.facebook.com/k19treinamentos
83
84
Crie o arquivo de resposta, o Lista.jsp, na pasta WebContent, para apresentar os carros adicionados.
1 2 3 4 5 6 7 8 9 1 11 12 13 <% @ taglib prefix = " s " uri = " / struts - tags " % > < html > < head > < title > K19 Treinamentos </ title > </ head > < body > < ul > < s:iterator value = " carros " > < li > < s:property value = " marca " / > - < s:property value = " modelo " / > </ li > </ s:iterator > </ ul > </ body > </ html >
Cdigo JSP 6.2: Lista.jsp
Note que utilizamos a tag <s:iterator> para percorrer todos os elementos da lista de carros. No corpo dessa tag, podemos acessar as propriedades de cada elemento simplesmente com os nomes dessas propriedades. Por exemplo, para acessar a propriedade marca, usamos o identicador "marca" com a tag <s:property>.
17
http://localhost:8 8 /K19-Integracao-Struts-JPA/Formulario.jsp
Adicione alguns carros e verique se eles foram adicionados no SGDB.
84
www.k19.com.br
CAPTULO
Cdigo Java 7.1: LoginAction.java
AUTENTICAO
Neste captulo, apresentaremos uma maneira de implementar o processo de autenticao dos usurios de uma aplicao Struts.
Exerccios de Fixao
Crie um projeto do tipo Dynamic Web Project chamado K19-Autenticacao seguindo os passos vistos nos exerccios do 1 ao 5 no Captulo 5.
1
Por simplicidade, utilizaremos um atributo esttico de uma action para armazenar os usurios da aplicao e suas respectivas senhas. A implementao que ser apresentada a seguir pode ser alterada para que esses dados sejam armazenadas em um arquivo ou em um banco de dados.
2
Importante
Por motivos de segurana, as senhas dos usurios no devem ser armazenadas literalmente. Ao invs disso, as senhas dos usurios devem passar por um processo de transformao (criptograa) antes de serem armazenadas. Quando um usurio tenta logar no sistema, ele digita o seu nome de usurio e sua senha. Para garantir que o usurio tenha acesso ao sistema, precisamos vericar se o nome de usurio digitado est cadastrado no sistema e se sua senha est correta. Como ns no armazenamos a senha do usurio, o que fazemos aplicar a mesma transformao feita anteriormente e comparar o valor obtido com aquele armazenado no servidor. Se esses valores forem iguais, ento permitimos que o usurio acesse o sistema. Caso contrrio, o acesso ao sistema negado.
Crie uma classe chamada LoginAction em um pacote chamado br.com.k19.actions no projeto K19-Autenticacao com o seguinte contedo:
1 2 3 4 5 6 7 8 9 1 package br . com . k19 . actions ; import java . util . HashMap ; import java . util . Map ; import com . opensymphony . xwork2 . ActionSupport ; @SuppressWarnings ( " serial " ) public class LoginAction extends ActionSupport { private static Map < String , String > mapa = new HashMap < String , String >() ; }
85
AUTENTICAO
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 package br . com . k19 . actions ; import java . util . HashMap ; import java . util . Map ; import com . opensymphony . xwork2 . ActionSupport ; @SuppressWarnings ( " serial " ) public class LoginAction extends ActionSupport { private static Map < String , String > mapa = new HashMap < String , String >() ; static { LoginAction . mapa . put ( " k19 " , " k19 " ) ; LoginAction . mapa . put ( " jonas . hirata " , " jonas . hirata " ) ; LoginAction . mapa . put ( " marcelo . martins " , " marcelo . martins " ) ; LoginAction . mapa . put ( " rafael . cosentino " , " rafael . cosentino " ) ; } }
Cdigo Java 7.2: LoginAction.java
86
4 Crie propriedades para armazenar os dados enviados atravs do formulrio de identicao e um mtodo para implementar o processo de autenticao.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43
package br . com . k19 . actions ; import import import import import java . util . HashMap ; java . util . Map ; javax . servlet . http . HttpSession ; org . apache . struts2 . ServletActionContext ; com . opensymphony . xwork2 . ActionSupport ;
@SuppressWarnings ( " serial " ) public class LoginAction extends ActionSupport { private static Map < String , String > mapa = new HashMap < String , String >() ; private String usuario ; private String senha ; private String mensagem ; static { LoginAction . mapa . put ( " k19 " , " k19 " ) ; LoginAction . mapa . put ( " jonas . hirata " , " jonas . hirata " ) ; LoginAction . mapa . put ( " marcelo . martins " , " marcelo . martins " ) ; LoginAction . mapa . put ( " rafael . cosentino " , " rafael . cosentino " ) ; } public String execute () throws Exception { if ( LoginAction . mapa . containsKey ( this . usuario ) && LoginAction . mapa . get ( this . usuario ) . equals ( this . senha ) ) { HttpSession session = ServletActionContext . getRequest () . getSession ( true ) ; session . setAttribute ( " usuario " , this . usuario ) ; this . mensagem = " Autenticao realizada com sucesso . " ; return LoginAction . SUCCESS ; } else { this . mensagem = " Usurio e / ou senha incorretos . " ; return LoginAction . INPUT ; } } // GETTERS E SETTERS }
Cdigo Java 7.3: LoginAction.java
86
www.k19.com.br
87
5
AUTENTICAO
Crie uma classe chamada LogoutAction no pacote br.com.k19.actions no projeto K19-Autenticacao com o seguinte contedo:
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 package br . com . k19 . actions ; import javax . servlet . http . HttpSession ; import org . apache . struts2 . ServletActionContext ; import com . opensymphony . xwork2 . ActionSupport ; @SuppressWarnings ( " serial " ) public class LogoutAction extends ActionSupport { private String mensagem ; public String execute () throws Exception { HttpSession session = ServletActionContext . getRequest () . getSession ( true ) ; session . removeAttribute ( " usuario " ) ; this . mensagem = " At logo ! " ; return LogoutAction . SUCCESS ; } // GETTERS E SETTERS }
Cdigo Java 7.4: LogoutAction.java
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17
1 2 3 4 5 6 7 8 9 1 11 12
www.facebook.com/k19treinamentos
87
AUTENTICAO
13 14 15 16 17 18 19 < s:textfield name = " usuario " / > < s:label value = " Senha: " / > < s:password name = " senha " / > < s:submit value = " Enviar " / > </ s:form > </ body > </ html >
Cdigo JSP 7.1: Login.jsp
88
1 2 3 4 5 6 7 8 9 1 11 12 13 14
<% @ taglib prefix = " s " uri = " / struts - tags " % > < html > < head > < title > K19 Treinamentos </ title > </ head > < body > < div style = " color: red " > < s:property value = " mensagem " / > </ div > < s:url action = " Logout " var = " url " / > < s:a href = " %{ url } " > Logout </ s:a > </ body > </ html >
Cdigo JSP 7.2: Home.jsp
9 Aps fazer logout, tente acessar a pgina http://localhost:8 8 /K19-Autenticacao/Home. jsp. Note que voc capaz de acess-la. No entanto, somente usurios autenticados podem acessar
a pgina principal da aplicao. Para controlar o acesso s pginas da aplicao, implemente um ltro para interceptar todas as requisies HTTP direcionadas ao ltro do Struts. Crie uma classe chamada ControleDeAcesso em um pacote chamado br.com.k19.filters no projeto K19-Autenticacao com o seguinte contedo:
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 package br . com . k19 . filters ; import java . io . IOException ; import import import import import import import import import javax . servlet . Filter ; javax . servlet . FilterChain ; javax . servlet . FilterConfig ; javax . servlet . ServletException ; javax . servlet . ServletRequest ; javax . servlet . ServletResponse ; javax . servlet . http . HttpServletRequest ; javax . servlet . http . HttpServletResponse ; javax . servlet . http . HttpSession ;
public class ControleDeAcesso implements Filter { @Override public void doFilter ( ServletRequest request , ServletResponse response , FilterChain chain ) throws IOException , ServletException { HttpServletRequest req = ( HttpServletRequest ) request ; HttpSession session = req . getSession () ; if ( session . getAttribute ( " usuario " ) != null || req . getRequestURI () . endsWith ( " Login . jsp " ) || req . getRequestURI () . endsWith ( " Login . action " ) ) { chain . doFilter ( request , response ) ; } else {
88
www.k19.com.br
89
29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 HttpServletResponse res = ( HttpServletResponse ) response ; res . sendRedirect ( " Login . jsp " ) ; } } @Override public void init ( FilterConfig filterConfig ) throws ServletException { } @Override public void destroy () { } }
Cdigo Java 7.5: ControleDeAcesso.java
AUTENTICAO
10
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36
Reinicie a aplicao e tente acessar diretamente a pgina principal da aplicao acessando http://localhost:8 8 /K19-Autenticacao/Home.jsp. Observe que a aplicao redireciona o navegador para a pgina do formulrio de autenticao.
11
www.facebook.com/k19treinamentos
89
AUTENTICAO
90
90
www.k19.com.br
CAPTULO
Cdigo JSP 8.1: Pagina-De-Erro.jsp
PGINAS DE E RRO
Por padro, quando determinados erros ocorrem no processamento de uma requisio, pginas com informaes tcnicas sobre o problema que ocorreu so geradas e enviadas para os usurios. Na fase de desenvolvimento, essas pginas so teis para os desenvolvedores. Por outro lado, na fase de produo, essas pginas podem confundir os usurios da aplicao e revelar a estrutura do sistema, expondo possveis falhas de segurana.
Hi Hi Hi!!
Caused by: java.lang.IllegalArgumentException: id to load is required for loading at org.hibernate.event.LoadEvent.<init>(LoadEvent.java:89) at org.hibernate.event.LoadEvent.<init>(LoadEvent.java:61) at org.hibernate.impl.SessionImpl.get(SessionImpl.java:994) at org.hibernate.impl.SessionImpl.get(SessionImpl.java:990) at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:554) at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:529) at model.repositories.TimeRepository.procura(TimeRepository.java:38) at managedbeans.JogadorBean.adiciona(JogadorBean.java:30) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.sun.el.parser.AstValue.invoke(AstValue.java:234) at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:297) at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105) ... 41 more
Exerccios de Fixao
Crie um projeto do tipo Dynamic Web Project chamado K19-Paginas-De-Erro seguindo os passos vistos nos exerccios 1 ao 5 do Captulo 5.
1
Criaremos uma pgina de erro padro. Adicione na pasta WebContent um arquivo JSP com o seguinte contedo.
2
1 2 3 4 5 6 7 8 9 1
< html > < head > < title > K19 Treinamentos </ title > < head > < body > < h1 > Ocorreu um erro interno no sistema . </ h1 > < h3 > Tente novamente em alguns instantes . </ h3 > < body > </ html >
www.facebook.com/k19treinamentos
91
PGINAS DE E RRO
3
92
Criaremos uma pgina com um boto que sempre produzir um erro ao ser clicado. Adicione na pasta WebContent um arquivo JSP com o seguinte contedo.
1 2 3 4 5 6 7 8 9 1 11 <% @ taglib prefix = " s " uri = " / struts - tags " % > < html > < head > < title > K19 Treinamentos </ title > </ head > < body > < s:form action = " Erro " > < s:submit value = " Gera Erro " / > </ s:form > </ body > </ html >
Cdigo JSP 8.2: Erro.jsp
Crie uma action que provoque propositalmente um erro. Adicione em um pacote chamado br.com.k19.actions uma classe com o seguinte cdigo:
4
1 2 3 4 5 6 7 8 9 1 11 12 13
package br . com . k19 . actions ; import com . opensymphony . xwork2 . ActionSupport ; @SuppressWarnings ( " serial " ) public class ErroAction extends ActionSupport { @Override public String execute () throws Exception { System . out . println (1 / ) ; return ErroAction . SUCCESS ; } }
Cdigo Java 8.1: ErroAction.java
1 2 3 4 5 6 7 8 9 1 11 12 13
http://localhost:8 8 /K19-Paginas-De-Erro/Erro.jsp
Congure o Struts para direcionar todas as exceptions para a pgina de erro padro. Altere o cdigo do arquivo struts.xml.
7
1 2
<? xml version = " 1. " encoding = " UTF -8 " ? > <! DOCTYPE struts PUBLIC
92
www.k19.com.br
93
3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 " -// Apache Software Foundation // DTD Struts Configuration 2. // EN " " http: // struts . apache . org / dtds / struts -2. . dtd " > < struts > < constant name = " struts . devMode " value = " true " / > < package name = " default " extends = " struts - default " > < global - results > < result name = " error " >/ Pagina - De - Erro . jsp </ result > </ global - results > < global - exception - mappings > < exception - mapping result = " error " exception = " java . lang . Exception " / > </ global - exception - mappings > < action name = " Erro " class = " br . com . k19 . actions . ErroAction " > < result name = " success " >/ Erro . jsp </ result > </ action > </ package > </ struts >
Cdigo XML 8.2: struts.xml
PGINAS DE E RRO
A tag <global-exception-mappings> acima dene que qualquer action que lanar uma java.lang.Exception produzir o resultado error. A tag <global-results> acima determina que toda vez que uma action gerar o resultado error, a pgina a ser apresentada ao usurio ser /Pagina-De-Erro.jsp.
8
http://localhost:8 8 /K19-Paginas-De-Erro/Erro.jsp
www.facebook.com/k19treinamentos
93
PGINAS DE E RRO
94
94
www.k19.com.br
CAPTULO
Cdigo Java 9.1: Usuario.java
CRUD
Neste captulo, criaremos uma pequena aplicao CRUD com Struts para exemplicar o funcionamento desse framework.
Exerccios de Fixao
Crie um projeto do tipo Dynamic Web Project chamado K19-CRUD seguindo os passos vistos nos exerccios 1 ao 5 do Captulo 5.
1
Crie um pacote chamado br.com.k19.model e adicione nele uma classe para modelar os usurios da nossa aplicao.
2
1 2 3 4 5 6 7 8 9 1 11 12 13
package br . com . k19 . model ; public class Usuario { private Integer id ; private String nome ; private String username ; private String password ; // GETTERS E SETTERS }
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22
www.facebook.com/k19treinamentos
95
CRUD
23 24 25 26 27 28 29 UsuarioRepository . usuarios . set ( usuario . getId () - 1 , usuario ) ; } public List < Usuario > lista () { return new ArrayList < Usuario >( UsuarioRepository . usuarios ) ; } }
Cdigo Java 9.2: UsuarioRepository.java
96
4 Crie um pacote chamado br.com.k19.actions e adicione nele uma classe para implementar as aes da nossa aplicao.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52
package br . com . k19 . actions ; import import import import java . util . List ; br . com . k19 . model . Usuario ; br . com . k19 . model . UsuarioRepository ; com . opensymphony . xwork2 . ActionSupport ;
@SuppressWarnings ( " serial " ) public class UsuarioAction extends ActionSupport { private Usuario usuario = new Usuario () ; private List < Usuario > usuarios ; public String adicionaOuAltera () { UsuarioRepository repository = new UsuarioRepository () ; if ( this . usuario . getId () == null ) { repository . adiciona ( this . usuario ) ; } else { repository . altera ( this . usuario ) ; } this . usuario = new Usuario () ; return UsuarioAction . SUCCESS ; } public String remove () { UsuarioRepository repository = new UsuarioRepository () ; repository . remove ( this . usuario . getId () ) ; this . usuario = new Usuario () ; return UsuarioAction . SUCCESS ; } public String preparaAlteracao () { UsuarioRepository repository = new UsuarioRepository () ; this . usuario = repository . busca ( this . usuario . getId () ) ; return UsuarioAction . SUCCESS ; } public String lista () { UsuarioRepository repository = new UsuarioRepository () ; this . usuarios = repository . lista () ; return UsuarioAction . SUCCESS ; } public Usuario getUsuario () { return usuario ; } public List < Usuario > getUsuarios () { return usuarios ; } }
Cdigo Java 9.3: UsuarioAction.java
96
www.k19.com.br
97
5
CRUD
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3
Implemente a pgina inicial da nossa aplicao, adicionando o arquivo especicado abaixo na pasta WebContent.
6
1 2 3 4 5 6 7 8
<% @ taglib prefix = " s " uri = " / struts - tags " % > < html > < head > < title > K19 Treinamentos </ title > </ head > < s:a action = " UsuarioLista " > Usurios </ s:a > </ html >
Cdigo JSP 9.1: Index.jsp
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15
www.facebook.com/k19treinamentos
97
CRUD
16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52 < table > < tr > < th > ID </ th > < th > Nome </ th > < th > Username </ th > < th > Password </ th > < th > Alterar </ th > < th > Remover </ th > </ tr > < s:iterator value = " usuarios " status = " status " > < tr style = " background - color: ${ status . even ? # EEEEEE : # FFFFFF } " > < td > < s:property value = " id " / > </ td > < td > < s:property value = " nome " / > </ td > < td > < s:property value = " username " / > </ td > < td > < s:property value = " password " / > </ td > < td > < s:a action = " UsuarioPreparaAlteracao " > alterar < s:param name = " usuario . id " value = " id " / > </ s:a > </ td > < td > < s:a action = " UsuarioRemove " > remover < s:param name = " usuario . id " value = " id " / > </ s:a > </ td > </ tr > </ s:iterator > </ table > </ c:if > < c:if test = " ${ empty usuarios } " > < h1 > Sem usurios cadastrados . </ h1 > </ c:if > </ html >
Cdigo JSP 9.2: Lista.jsp
98
Nas linhas em destaque, note que utilizamos a biblioteca de tags JSTL (JavaServer Pages Standard Tag Library). As tags dessa biblioteca no dependem de nenhum framework web em particular. Para saber mais sobre essa biblioteca, acesse http://java.sun.com/jsp/jstl/. Na pgina denida pelo arquivo acima, a tabela contendo os dados dos usurios s exibida se a lista de usurios no for vazia. Para vericar se a lista de usurios no est vazia, utilizamos a tag <c:if> da JSTL. Alternativamente, poderamos utilizar a tag <s:if> do Struts.
8
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17
98
www.k19.com.br
99
18 19 2 21 < s:textfield label = " Password: " name = " usuario . password " / > < s:submit value = " Salvar " / > </ s:form > </ html >
Cdigo JSP 9.3: UsuarioFormulario.jsp
CRUD
http://localhost:8 8 /K19-CRUD/Index.jsp
Teste as funcionalidades implementadas. Adicione algumas regras de validao associadas ao cadastro e alterao de usurios. Crie um arquivo chamado UsuarioAction-UsuarioAdicionaOuAltera-validation.xml no pacote br.com.k19.actions. O nome desse arquivo denido da seguinte forma:
10
[NomeDaClasse]-[NomeDaAction]-validation.xml [NomeDaClasse] o nome da classe que dene as actions. [NomeDaAction] o nome da action registrado no arquivo struts.xml.
Acrescente o seguinte contedo a esse arquivo:
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 <! DOCTYPE validators PUBLIC " -// OpenSymphony Group // XWork Validator 1. .2// EN " " http: // www . opensymphony . com / xwork / xwork - validator -1. .2. dtd " > < validators > < field name = " usuario . nome " > < field - validator type = " requiredstring " > < message >O nome do usurio obrigatrio </ message > </ field - validator > < field - validator type = " stringlength " > < param name = " maxLength " > 3 </ param > < message >O nome no pode possuir mais do que ${ maxLength } letras . </ message > </ field - validator > </ field > < field name = " usuario . username " > < field - validator type = " requiredstring " > < message >O username do usurio obrigatrio </ message > </ field - validator > < field - validator type = " stringlength " > < param name = " maxLength " > 1 </ param > < param name = " minLength " >5 </ param > < message >O usurio deve possuir no mnimo ${ minLength } e no mximo ${ maxLength } letras . </ message > </ field - validator > </ field > < field name = " usuario . password " > < field - validator type = " requiredstring " > < message >A senha do usurio obrigatria </ message > </ field - validator > </ field > </ validators >
Cdigo XML 9.2: UsuarioAction-UsuarioAdicionaOuAltera-validation.xml
Observe que as validaes so denidas individualmente para cada campo por meio da tag <field>. Associamos aos campos usuario.nome, usuario.username e usuario.password o validador
www.facebook.com/k19treinamentos
99
CRUD
100
requiredstring, tornando o preenchimento desses campos obrigatrio. Tambm foram denidas mensagens de erro para essas validaes atravs da tag <message>. O validador stringlength foi aplicado aos campos usuario.nome e usuario.username. Esse validador permite limitar o tamanho
do texto desses campos.
11
http://localhost:8 8 /K19-CRUD/Index.jsp
Teste as validaes no cadastro e na alterao de usurios.
100
www.k19.com.br
APNDICE
Cdigo XML A.1: persistence.xml
P ROJETO
Neste captulo, criaremos uma aplicao que agrupa todos os recursos vistos nos captulos anteriores.
Exerccios de Fixao
Crie um projeto do tipo Dynamic Web Project chamado K19-Projeto seguindo os passos vistos nos exerccios 1 ao 5 do Captulo 5.
1 2 3
Adicione uma pasta chamada META-INF na pasta src do projeto K19-Projeto. Congure o JPA adicionando o arquivo persistence.xml na pasta src/META-INF.
<? xml version = " 1. " encoding = " UTF -8 " ? > < persistence version = " 2. " xmlns = " http: // java . sun . com / xml / ns / persistence " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance " xsi:schemaLocation = " http: // java . sun . com / xml / ns / persistence http: // java . sun . com / xml / ns / persistence / persistence_2_ . xsd " > < persistence - unit name = " K19 - PU " transaction - type = " RESOURCE_LOCAL " > < provider > org . hibernate . ejb . HibernatePersistence </ provider > < properties > < property name = " hibernate . dialect " value = " org . hibernate . dialect . MySQL5InnoDBDialect " / > < property name = " hibernate . hbm2ddl . auto " value = " update " / > < property name = " javax . persistence . jdbc . driver " value = " com . mysql . jdbc . Driver " / > < property name = " javax . persistence . jdbc . user " value = " root " / > < property name = " javax . persistence . jdbc . password " value = " root " / > < property name = " javax . persistence . jdbc . url " value = " jdbc:mysql: // localhost:33 6 / K19_DB " / > </ properties > </ persistence - unit > </ persistence >
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23
Abra um terminal; entre no cliente do MySQL Server; apague se existir a base de dados K19_DB; e crie uma base de dados nova chamada K19_DB.
4
k19@k19 -11:~/ rafael$ mysql -u root -p Enter password : Welcome to the MySQL monitor . Commands end with ; or \ g . Your MySQL connection id is 36 Server version : 5.1.58 -1 ubuntu1 ( Ubuntu ) Copyright ( c ) 2 , 2 1 , Oracle and / or its affiliates . All rights reserved . This software comes with ABSOLUTELY NO WARRANTY . This is free software ,
www.facebook.com/k19treinamentos
101
P ROJETO
and you are welcome to modify and redistribute it under the GPL v2 license Type help ; or \h for help . Type \c to clear the current input statement . mysql > DROP DATABASE IF EXISTS K19_DB ; Query OK , rows affected , 1 warning ( . mysql > CREATE DATABASE K19_DB ; Query OK , 1 row affected ( . 2 sec )
102
sec )
5 6
Crie um pacote chamado br.com.k19.filters na pasta src do projeto K19-Projeto. No pacote br.com.k19.filters, crie uma classe chamada JPAFilter com o seguinte contedo:
package br . com . k19 . filters ; import java . io . IOException ; import javax . persistence .*; import javax . servlet .*; public class JPAFilter implements Filter { private EntityManagerFactory factory ; @Override public void init ( FilterConfig filterConfig ) throws ServletException { this . factory = Persistence . createEntityManagerFactory ( " K19 - PU " ) ; } @Override public void destroy () { this . factory . close () ; } @Override public void doFilter ( ServletRequest request , ServletResponse response , FilterChain chain ) throws IOException , ServletException { // CHEGADA EntityManager manager = this . factory . createEntityManager () ; request . setAttribute ( " EntityManager " , manager ) ; manager . getTransaction () . begin () ; // CHEGADA // FILTRO DO STRUTS chain . doFilter ( request , response ) ; // FILTRO DO STRUTS // SADA try { manager . getTransaction () . commit () ; } catch ( Exception e ) { manager . getTransaction () . rollback () ; } finally { manager . close () ; } // SADA } }
Cdigo Java A.1: JPAFilter.java
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45
1 2 3
102
www.k19.com.br
103
4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38
P ROJETO
xsi:schemaLocation = " http: // java . sun . com / xml / ns / javaee http: // java . sun . com / xml / ns / javaee / web - app_3_ . xsd " id = " WebApp_ID " version = " 3. " > < display - name >K19 - Projeto </ 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 > < filter > < filter - name > JPAFilter </ filter - name > < filter - class > br . com . k19 . filters . JPAFilter </ filter - class > </ filter > < filter - mapping > < filter - name > JPAFilter </ filter - name > <url - pattern > /* </ url - pattern > </ filter - mapping > < filter > < filter - name > struts2 </ filter - name > < filter - class > org . apache . struts2 . dispatcher . ng . filter . StrutsPrepareAndExecuteFilter </ filter - class > </ filter > < filter - mapping > < filter - name > struts2 </ filter - name > <url - pattern > /* </ url - pattern > </ filter - mapping > </ web - app >
Cdigo XML A.2: web.xml
Crie uma classe chamada ControleDeAcesso no pacote br.com.k19.filters no projeto K19-Projeto com o seguinte contedo:
8
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26
package br . com . k19 . filters ; import java . io . IOException ; import import import import import import import import import javax . servlet . Filter ; javax . servlet . FilterChain ; javax . servlet . FilterConfig ; javax . servlet . ServletException ; javax . servlet . ServletRequest ; javax . servlet . ServletResponse ; javax . servlet . http . HttpServletRequest ; javax . servlet . http . HttpServletResponse ; javax . servlet . http . HttpSession ;
public class ControleDeAcesso implements Filter { @Override public void doFilter ( ServletRequest request , ServletResponse response , FilterChain chain ) throws IOException , ServletException { HttpServletRequest req = ( HttpServletRequest ) request ; HttpSession session = req . getSession () ; if ( session . getAttribute ( " usuario " ) != null || req . getRequestURI () . endsWith ( " Login . jsp " ) || req . getRequestURI () . endsWith ( " Login . action " ) ) {
www.facebook.com/k19treinamentos
103
P ROJETO
27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 chain . doFilter ( request , response ) ; } else { HttpServletResponse res = ( HttpServletResponse ) response ; res . sendRedirect ( " Login . jsp " ) ; } } @Override public void init ( FilterConfig filterConfig ) throws ServletException { } @Override public void destroy () { } }
Cdigo Java A.2: ControleDeAcesso.java
104
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46
104
www.k19.com.br
105
47 48 49 <url - pattern > /* </ url - pattern > </ filter - mapping > </ web - app >
Cdigo XML A.3: web.xml
P ROJETO
Crie um pacote chamado br.com.k19.model e adicione nele uma classe para modelar os usurios da nossa aplicao.
10
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16
package br . com . k19 . model ; @Entity public class Usuario { @Id @GeneratedValue private Integer id ; private String nome ; @Column ( unique = true ) private String username ; private String password ; // GETTERS E SETTERS }
Cdigo Java A.3: Usuario.java
11
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36
www.facebook.com/k19treinamentos
105
P ROJETO
37 38 39 4 return ! query . getResultList () . isEmpty () ; } }
Cdigo Java A.4: UsuarioRepository.java
106
Crie uma classe chamada AutenticacaoAction em um pacote chamado br.com.k19.actions no projeto K19-Projeto com o seguinte contedo:
12
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49
package br . com . k19 . actions ; // IMPORTS @SuppressWarnings ( " serial " ) public class AutenticacaoAction extends ActionSupport { private Usuario usuario = new Usuario () ; private String mensagem ; public String login () { EntityManager manager = this . getEntityManager () ; UsuarioRepository repository = new UsuarioRepository ( manager ) ; if ( repository . existeUsernameEPassword ( this . usuario . getUsername () , this . usuario . getPassword () ) ) { HttpSession session = ServletActionContext . getRequest () . getSession ( true ) ; session . setAttribute ( " usuario " , this . usuario ) ; this . mensagem = " Autenticao realizada com sucesso . " ; return AutenticacaoAction . SUCCESS ; } else { this . mensagem = " Usurio e / ou senha incorretos . " ; return AutenticacaoAction . INPUT ; } } public String logout () { HttpSession session = ServletActionContext . getRequest () . getSession () ; session . removeAttribute ( " usuario " ) ; this . mensagem = " At logo ! " ; return AutenticacaoAction . SUCCESS ; } private EntityManager getEntityManager () { HttpServletRequest request = ServletActionContext . getRequest () ; EntityManager manager = ( EntityManager ) request . getAttribute ( " EntityManager " ) ; return manager ; } // GETTERS E SETTERS }
Cdigo Java A.5: AutenticacaoAction.java
13
1 2 3
106
www.k19.com.br
107
4 5 6 7 8 9 1 11 12 13 14 15 16 17 " http: // struts . apache . org / dtds / struts -2. . dtd " >
P ROJETO
< struts > < constant name = " struts . devMode " value = " true " / > < package name = " default " extends = " struts - default " > < action name = " Login " class = " br . com . k19 . actions . AutenticacaoAction " method = " login " > < result name = " success " >/ Home . jsp </ result > < result name = " input " >/ Login . jsp </ result > </ action > < action name = " Logout " class = " br . com . k19 . actions . AutenticacaoAction " method = " logout "> < result name = " success " >/ Login . jsp </ result > </ action > </ package > </ struts >
Cdigo XML A.4: struts.xml
Para testar, crie a tela do formulrio de autenticao e a tela principal da aplicao na pasta WebContent.
14
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17
<% @ taglib prefix = " s " uri = " / struts - tags " % > < html > < head > < title > K19 Treinamentos </ title > </ head > < body > < div style = " color: red " > < s:property value = " mensagem " / > </ div > < s:form action = " Login " > < s:textfield name = " usuario . username " label = " Usurio: " / > < s:password name = " usuario . password " label = " Senha: " / > < s:submit value = " Enviar " / > </ s:form > </ body > </ html >
Cdigo JSP A.1: Login.jsp
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15
<% @ taglib prefix = " s " uri = " / struts - tags " % > < html > < head > < title > K19 Treinamentos </ title > </ head > < body > < div style = " color: red " > < s:property value = " mensagem " / > </ div > < s:a href = " Home . jsp " > Home </ s:a > < br / > < s:a action = " Logout " > Logout </ s:a > </ body > </ html >
Cdigo JSP A.2: Home.jsp
Adicione a aplicao no Glasssh e inicialize-o. Acesse o terminal do MySQL e cadastre o primeiro usurio da aplicao. Siga os passos abaixo.
15
k19@k19 -11:~/ rafael$ mysql -u root -p Enter password : Welcome to the MySQL monitor . Commands end with ; or \ g .
www.facebook.com/k19treinamentos
107
P ROJETO
Your MySQL connection id is 43 Server version : 5.1.58 -1 ubuntu1 ( Ubuntu ) Copyright ( c ) 2 , 2 1 , Oracle and / or its affiliates . All rights reserved . This software comes with ABSOLUTELY NO WARRANTY . This is free software , and you are welcome to modify and redistribute it under the GPL v2 license Type help ; or \h for help . Type \c to clear the current input statement . mysql > USE K19_DB ; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql > INSERT INTO Usuario ( nome , username , password ) VALUES ( admin , admin , admin ); Query OK , 1 row affected ( . 3 sec )
108
16
http://localhost:8 8 /K19-Projeto/Home.jsp
17 No pacote br.com.k19.actions, adicione uma classe para implementar o cadastro, edio, remoo e visualizao dos usurios.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46
package br . com . k19 . actions ; import java . util . List ; import br . com . k19 . model . Usuario ; import br . com . k19 . model . UsuarioRepository ; import com . opensymphony . xwork2 . ActionSupport ; @SuppressWarnings ( " serial " ) public class UsuarioAction extends ActionSupport { private Usuario usuario = new Usuario () ; private List < Usuario > usuarios ; public String adicionaOuAltera () { EntityManager manager = this . getEntityManager () ; UsuarioRepository repository = new UsuarioRepository ( manager ) ; if ( this . usuario . getId () == null ) { repository . adiciona ( this . usuario ) ; } else { repository . altera ( this . usuario ) ; } this . usuario = new Usuario () ; return UsuarioAction . SUCCESS ; } public String remove () { EntityManager manager = this . getEntityManager () ; UsuarioRepository repository = new UsuarioRepository ( manager ) ; repository . remove ( this . usuario . getId () ) ; this . usuario = new Usuario () ; return UsuarioAction . SUCCESS ; } public String preparaAlteracao () { EntityManager manager = this . getEntityManager () ; UsuarioRepository repository = new UsuarioRepository ( manager ) ; this . usuario = repository . busca ( this . usuario . getId () ) ; return UsuarioAction . SUCCESS ; } public String lista () { EntityManager manager = this . getEntityManager () ; UsuarioRepository repository = new UsuarioRepository ( manager ) ;
108
www.k19.com.br
109
47 48 49 5 51 52 53 54 55 56 57 58 59 6 61 62 63 64 65 this . usuarios = repository . lista () ; return UsuarioAction . SUCCESS ; } private EntityManager getEntityManager () { HttpServletRequest request = ServletActionContext . getRequest () ; EntityManager manager = ( EntityManager ) request . getAttribute ( " EntityManager " ) ; return manager ; } public Usuario getUsuario () { return usuario ; } public List < Usuario > getUsuarios () { return usuarios ; } }
Cdigo Java A.6: UsuarioAction.java
P ROJETO
18
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35
www.facebook.com/k19treinamentos
109
P ROJETO
19
110
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17
20
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44
110
www.k19.com.br
111
45 46 47 48 49 5 51 52 53 54 </ td > </ tr > </ s:iterator > </ table > </ c:if > < c:if test = " ${ empty usuarios } " > < h1 > Sem usurios cadastrados . </ h1 > </ c:if > </ html >
Cdigo JSP A.4: Lista.jsp
P ROJETO
21
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23
22
http://localhost:8 8 /K19-Projeto/Home.jsp
Cadastre, altere, remova alguns usurios. Adicione algumas regras de validao associadas ao cadastro e alterao de usurios. Crie um arquivo chamado UsuarioAction-UsuarioAdicionaOuAltera-validation.xml no pacote br.com.k19.actions com o seguinte contedo.
23
1 2 3 4 5 6 7 8 9 1 11 12 13 14
<! DOCTYPE validators PUBLIC " -// OpenSymphony Group // XWork Validator 1. .2// EN " " http: // www . opensymphony . com / xwork / xwork - validator -1. .2. dtd " > < validators > < field name = " usuario . nome " > < field - validator type = " requiredstring " > < message >O nome do usurio obrigatrio </ message > </ field - validator > < field - validator type = " stringlength " > < param name = " maxLength " > 3 </ param > < message >O nome no pode possuir mais do que ${ maxLength } letras . </ message > </ field - validator > </ field > < field name = " usuario . username " > < field - validator type = " requiredstring " >
www.facebook.com/k19treinamentos
111
P ROJETO
15 16 17 18 19 2 21 22 23 24 25 26 27 28 29
112
< message >O username do usurio obrigatrio </ message > </ field - validator > < field - validator type = " stringlength " > < param name = " maxLength " > 1 </ param > < param name = " minLength " >5 </ param > < message >O usurio deve possuir no mnimo ${ minLength } e no mximo ${ maxLength } letras . </ message > </ field - validator > </ field > < field name = " usuario . password " > < field - validator type = " requiredstring " > < message >A senha do usurio obrigatria </ message > </ field - validator > </ field > </ validators >
Cdigo XML A.6: UsuarioAction-UsuarioAdicionaOuAltera-validation.xml
24
http://localhost:8 8 /K19-Projeto/Home.jsp
Teste as validaes no cadastro e na alterao de usurios.
25 Analogamente ao que foi feito at agora, crie telas para cadastrar, editar, remover e consultar deputados estaduais. Para cada deputado, o sistema deve armazenar o seu nome, partido, telefone e e-mail.
112
www.k19.com.br