fj27 caelum spring
TRANSCRIPT
-
7/18/2019 FJ27 Caelum Spring
1/98
FJ-27
Spring Framework
n
Ensino e Inovao
C
aelum www.caelum.com.br
-
7/18/2019 FJ27 Caelum Spring
2/98
ri
Caelum
Ensino e inovao
A Caelum atua no mercado com consultoria, desenvolvimento e ensino em computao. Sua equipe
participou do desenvolvimento de projetos em vrios clientes e, aps apresentar os cursos de vero de Java
na Universidade de So Paulo, passou a oferecer treinamentos para o mercado. Toda a equipe tem uma
forte presena na comunidade atravs de eventos, artigos em diversas revistas, participao em muitos
projetos open source
como o VRaptor e o Stella e atuao nos fruns e listas de discusso como o GUJ.
Com uma equipe de mais de 80 profissionais altamente qualificados e de destaque do mercado, oferece
treinamentos em Java, Ruby on Rails e Scrum em suas trs unidades - So Paulo, Rio de Janeiro e
Braslia. Mais de 8 mil alunos j buscaram qualificao nos treinamentos da Caelum tanto em nas unidades
como nas prprias empresas com os cursos
incompany.
O compromisso da Caelum oferecer um treinamento de qualidade, com material constantemente
atualizado, uma metodologia de ensino cuidadosamente desenvolvida e instrutores capacitados
tecnicamente e didaticamente. E oferecer ainda servios de consultoria gil, mentoring e desenvolvimento
de projetos sob medida para empresas.
Comunidade
Nossa equipe escreve constantemente artigos no
Blog da Caelum
que j conta
com 150 artigos sobre vrios assuntos de Java, Rails e computao em geral.
Visite-nos e assine nosso RSS:
blog.caelum.com.br
Acompanhe a Caelum no
Twitter:
twitter.com/caelum
O
GUJ
maior frum de Java em lngua portuguesa, com 700 mil posts e 70 mil
usurios. As pessoas da Caelum participam ativamente, participe tambm:
.
www.guj.com.br
Assine nossa
Newsletter para receber notcias tcnicas de Java, Rails, Agile e
Web, alm de novidades, eventos e artigos:
www.caelum.com.br/newsletter
No site da Caelum h algumas de nossas Apostilas
disponveis gratuitamente
para download e alguns dos
artigos
de destaque que escrevemos:
www.caelum.com.br/apostilas
www.caelum.com.br/artigos
-
7/18/2019 FJ27 Caelum Spring
3/98
ndice
1
Simplificando o desenvolvimento Enterprise
1
1.1 Por que Spring?
1
1.2 Sobre o curso FJ-27
1
1.3 Tirando dvidas
2
1.4
Bibliografia
2
2 Injeo de dependncias e Inverso de Controle
3
2.1
Nosso projeto
3
2.2
Dependncias e o alto acoplamento
4
2.3
Injeo de dependncias
5
2.4
Inverso de controle e o princpio de hollywood
7
2.5 Para saber mais: Registry como alternativa a Dl
7
2.6 Para saber mais..
8
3
Spring Framework
9
3.1
O que ?
9
3.2 Arquitetura do Spring
10
3.3
Introduo aos beans do Spring 12
3.4 Configurando o Spring 12
3.5
Iniciando o container
13
3.6
Injetando as Dependncias: por construtor e por setter
13
3.7
Exerccios: Projeto com Spring IoC
14
3.8
Exerccios opcionais: Injeco com Setter e Tipos Bsicos
17
3.9 Exerccios Opcionais: Valores Literais
18
-
7/18/2019 FJ27 Caelum Spring
4/98
4 Spring MVC
21
4.1 Spring MVC
21
4.2 Criando seu projeto web no Eclipse
21
4.3 Configurando o Spring MVC
22
4.4 View Resolvers
22
4.5 Seu primeiro Controller
23
4.6 Configurando
23
4.7 Exerccios: Nosso primeiro controller
24
4.8 Enviando dados para View
24
4.9 RequestMapping mais a fundo
25
4.10 O Controller de Produto
26
4.11 Gerenciamento e Injeo
26
4.12 Exerccios - Listando os Produtos
27
4.13 URLs amigveis
28
4.14 Melhor uso do HTTP
28
4.15 Exercicios: Melhor uso do http
29
4.16 Recebendo paramtros de Formulario
30
4.17 Forward X Redirect
31
4.18 Exerccios - Cadastro de Produto
32
4.19 Escopos
32
4.20 Web Escopos: Request, Session, Global Session
33
5 Integrando Spring, H ibernate e tecnologias de Persistncia
35
5.1 Introduo - Onde o Spring pode ajudar ao usar o Hibernate
35
5.2 Configurando o Hibernate no Spring
35
5.3 ProdutoHibernateDAO
36
5.4 @Repository
37
5.5 Exerccios
37
5.6 @Qualifier
39
5.7 Exerccios
39
5.8 No quero escolher um objeto, quero um padro
39
5.9 Exerccios
40
5.10 Transaes com Spring - Spring Transaction
40
5.11 Configurando o TransactionManager
41
ii
-
7/18/2019 FJ27 Caelum Spring
5/98
5.12 Controle de Session com o Spring
41
5.13 Exerccios
42
5.14 Exerccios - Alterar Produtos
43
5.15 Exerccio Opcional: Remoo de produtos
44
5.16 Aumentando nosso domnio
44
5.17 Entitidade
44
5.18 Exerccios
46
5.19 Mostrando as movimentaes na tela
49
5.20 Exerccios
49
5.21 Lidando com LazylnitializationException
50
5.22 Soluo Open Session in View
51
5.23 Exerccios
51
5.24 Transaes Avanadas
52
5.25 Para saber mais: HibernateTemplate e outros Templates
53
6 Validao com Bean Validation
55
6.1 Introduo
55
6.2 Bean Validation
55
6.3 Hibernate Validator
55
6.4 Exerccios
56
6.5 Mostrando erros em tela
57
6.6 Exerccios
58
6.7 Customizando menssagens
59
6.8 Exerccio
60
7 Spring Security
61
7.1 Introduo ao Spring Security
61
7.2 Exerccios - Configurando o Spring Security
62
7.3 - Access Control List
62
7.4 Exerccios - Criando as classes de Domnio
63
7.5 Interfaces de Acesso
64
7.6 Exerccios - Suporte a Acesso de Dados
67
7.7 Login
70
7.8 Exerccios - Logando no Sistema
71
iii
-
7/18/2019 FJ27 Caelum Spring
6/98
8 Apndice - AO P - Programao O rientada a Aspectos
75
8.1 Introduo a Programao Orientada a Aspectos
75
8.2 AOP na prtica
76
8.3 Elementos de um Aspecto
77
8.4 AOP com Spring
77
8.5 AOP no Spring com @AspectJ-style
77
8.6 Exerccios - AOP
78
8.7 Definindo Pointcuts e Advices
79
8.8 Exerccios
81
8.9 Outros Advices
82
8.10 Para saber mais: Combinando Pointcuts
83
8.11 Para saber mais: @Around
84
9 Apndice - Integrao entre Sistemas
85
9.1 Spring Integration
85
9.2 Exerccio: Spring Integration
86
10 Apndice - Enviando Email
89
10.1 Enviando E-mail com Spring
89
10.2 Exerccio: Spring Mail
90
Verso: 14.2.30
iv
-
7/18/2019 FJ27 Caelum Spring
7/98
CAPTULO
1
Simplificando o desenvolvimento Enterprise
H duas formas de se construir o design de um software: Uma forma faz-lo to simples que obviamente
no ter deficincias e a outra forma faz-lo to complicado que no ter deficincias bvias.
C.A.R. Hoare, The 1980 ACM Turing Award Lecture
1.1 - Por que Spring?
Com suas ideias de um container leve, o Spring vem sendo apresentado h anos como uma alternativa mais
simples arquitetura oficial do Java EE baseada em EJBs. J em 2008, a prpria SpringSource j mostrava
que a oferta de empregos com Spring se equiparava a de EJB:
http://bit.ly:springsourte-ejb
E uma busca atualizada mostra que, de 2008 at hoje, a tendncia se manteve: a procura por Spring cresceu
bastante e a de EJB continua estvel:
http://bitly/jobtrends-Spring-ejb
Como veremos, o princpio fundamental do Spring o uso de
Injeo de Dependncias
nos componentes
da sua aplicao. Alm disso, prov um container com diversos servios j prontos para sua aplicao. Desde
o surgimento do Spring, os princpios de
Inverso de Controle e
Injeo de Dependncias
se tornaram funda-
mentais em qualquer tipo de aplicao. Outros frameworks de injeo surgiram, como o Pico Container e o
Google Guice, e at o prprio Java EE incorporou essas tcnicas em sua ltima verso com o
CDI - Context
and Dependency Injection.
A importncia da injeo de dependncias hoje to grande que, em uma recente entrevista com os autores
do livro
Design Patterns
em comemorao aos 15 anos do livro, Erich Gamma, um dos autores, disse que, se
houvesse uma segunda edio do livro, um padro a ser includo seria
Dependency Injection:
http://bit .1y/entrevista-design-patterns
1.2 - Sobre o curso FJ-27
O curso FJ-27 foi reformulado com as novidades do Spring 3.x, a verso mais recente do framework. um
curso focado nos principais conceitos do Spring, desde Inverso de Controle e Injeo de Dependncias at
tpicos mais avanados como Orientao a Aspectos (AOP) e tecnologias como SpringMVC, REST e integrao
com Hibernate e outros frameworks.
Este um curso prtico, com muitos exerccios que abordam os tpicos discutidos em aula. Recomenda-
mos fortemente que voc faa todos os exerccios e esclarea suas dvidas em aula. Foque seus estudos
principalmente nos conceitos fundamentais.
1
-
7/18/2019 FJ27 Caelum Spring
8/98
Caelum http://www.caelum.com.br
Spring Framework 3
1.3 Tirando dvidas
Para tirar dvidas dos exerccios, ou de Java em geral, recomendamos o frum do site do GUJ
(http:
-
ww.guj.com.br
; ),
onde sua dvida ser respondida prontamente.
Fora isso, sinta-se vontade para entrar em contato com seu instrutor e tirar todas as dvidas que tiver
durante o curso.
1.4 - Bibliografia
possvel aprender muitos dos detalhes e pontos no cobertos no curso em tutoriais na Internet em portais
como o GUJ, em blogs (como o da Caelum:
http:,' blog.caelum.com .br
)
e em muitos Sites especializados.
Mas se voc deseja algum livro para expandir seus conhecimentos ou ter como guia de referncia, temos
algumas indicaes dentre vrias possveis:
Sobre Java e melhores prticas
Refactoring, Martin Fowler
Effective Java, Joshua Bloch
Design Patterns, Erich Gamma et al
Sobre o Spring Framework
Spring in Action, Craig Walls e Ryan Breidenbach
Referncia
oficial: http:, static.springsource.org/spring/docs /3.0.x
spring-frarnework-reference/html/
Captulo 1 - Simplificando o desenvolvimento Enterprise - Tirando dvidas - Pgina 2
-
7/18/2019 FJ27 Caelum Spring
9/98
CAPTULO
2
Injeo de dependncias e Inverso de
Controle
Se queres conversar comigo, define primeiro os termos que usas comigo
Voltaire
Nesse captulo, voc vai entender:
o que Injeo de Dependncias e que problemas ela resolve;
o que Inverso de Controle e tipos de inverses;
como usar frameworks para satisfazer as dependncias do seu projeto.
2.1 - Nosso projeto
Ao longo do curso FJ-27, vamos desenvolver um sistema de controle de
estoque de produtos.
Vamos
desenvolver desde seu modelo, sua persistncia, a camada Web, o controle de usurios e segurana. Tudo
usando o
Spring Framework
e diversas de suas caractersticas.
Vamos comear pensando na modelagem do domnio de negcio. Primeiro, temos a classe
Produto:
package br.com.caelum.estoque.model;
public class Produto {
private Long id;
private String descricao;
private Long quantidade;
//getters e setters
}
Para persistirmos os produtos, usaremos o padro
DAO.
Nosso DAO ser modelado como uma interface
Java. Desta forma, poderemos ter vrias implementaes do DAO e troc-las conforme necessrio.
As operaes que teremos no
ProdutoDAO:
package br.com.caelum.estoque.dao;
public interface ProdutoDAO {
void salvar(Produto produto);
void alterar(Produto produto);
List listar();
Produto buscarPorld(Long id);
}
3
-
7/18/2019 FJ27 Caelum Spring
10/98
Caelum http://www.caelum.com.br
Spring Framework 3
No curso, ser particularmente interessante ter o DAO como interface, j que vamos ver Hibernate apenas
mais pra frente. At l, para podermos criar nosso sistema usando persistncia, vamos criar uma implemen-
tao simples do DAO em memria. Mais pra frente, vamos troc-la por uma implementao completa com
Hibernate.
Nosso
ProdutoMemoriaDAO,
por enquanto apenas com os mtodos de listagem e adio implementados:
package br.com.caelum.estoque.dao;
public class ProdutoMemoriaDA0 implements ProdutoDA0 {
private List p rodutos = new ArrayList();
public ProdutoMem oriaDA0() {
Produto produto = new P roduto();
produto.setDescricao("Mac Book");
produto.setQuantidade(40);
produtos.add(produto);
}
public L ist listar(){
return produtos;
}
public void salvar(Produto produto) {
produtos.add(produto);
public Produto buscarPorld(Long id) {
/ / ainda no imp lementado
return nu ll;
}
public void al terar(Produto prod uto) {
/ / ainda no imp lementado
}
}
2.2 - Dependncias e o alto acoplamento
Teremos tambm uma classe
GerenciadorDeProduto
responsvel por pedir dados de um
Produto
ao usurio,
depois persistir esse objeto e por fim mostrar alguma confirmao.
Se estivssemos na Web, seria equivalente a pegar os dados do request enviado por um formulrio, persistir
e depois mostrar uma pgina
de confirmao. Vamos ver a
parte
Web
em um
captulo
mais
a frente. Por
enquanto, nossa classe
GerenciadorDeProduto
ser:
Captulo 2 - Injeo de dependncias e Inverso de Controle - Dependncias e o alto acoplamento - Pgina 4
-
7/18/2019 FJ27 Caelum Spring
11/98
Caelum http://www.caelum.com.br
Spring Framework 3
public class GerenciadorD eProduto {
private ProdutoDAO produtoDao;
public GerenciadorDeProduto() {
this.produtoDao = new ProdutoMemoriaDA0();
}
public void novoProduto() {
Produto produto = pedeD adosDoProdutoAoUsuario();
this.produtoDao.salvar(produto);
mostraConfirmacao();
}
}
uma classe bastante simples. Ela apenas controla a execuo das coisas entre o modelo, o DAO e a
interao com o usurio.
Mas ela tem um problema. Nossa classe
GerenciadorDeProduto
est acoplada no s interface
ProdutoDAO
como implementao concreta
ProdutoMemoriaDAO.
Repare que o construtor conhece a imple-
mentao especfica e d
new na classe.
Dizemos que a classe tem uma
dependncia tanto com
ProdutoDAO
quanto com
ProdutoMemoriaDAO.
Mas, quando olhamos a lgica de negcios propriamente dita, no mtodo
novoProduto,
percebemos que
o que realmente necessrio para execut-la
algum DAO.
A lgica em si no depende de qual instncia
especificamente da implementao que estamos usando. (imagine, como ser nosso caso daqui a pouco, que
tenhamos mais de uma implementao, como a
ProdutoHibernateDAO)
No fundo, precisamos ento apenas de
algum
ProdutoDAO
mas acabamos tendo que dar
new
diretamente
na implementao para us-la.
Nossa aplicao resolve a implementao e a dependncia, chamando
diretamente a classe especfica.
O problema desse tipo de chamada que, no dia que precisarmos mudar a implementao do DAO, precisa-
remos mudar nossa classe. Agora imagine que tenhamos 10 classes no sistema que usem nosso
ProdutoDAO.
Se todas do
new
na implementao especfica a ser usada (agora,
ProdutoMemoriaDAO),
quando formos mudar
a implementao para, digamos,
ProdutoHibernateDAO,
precisaremos mudar em vrios lugares.
E ainda ainda um segundo problema em gerenciar a dependncia diretamente na aplicao. Se a outra
classe precisar de um processo de construo mais complicado, precisaremos nos preocupar com isso. Imagine
a futura classe
ProdutoHibernateDAD
receba uma session do Hibernate. Ou ento uma
ProdutoJDBCDAD
que
precise da conneotion. Se formos dar
new
nessas classes, precisaramos resolver essas exigncias que, se
formos pensar bem, nem deveriam ser responsabilidades nossas.
2.3 Injeo de dependncias
O pattern
Dependency Injection Dl) -
Injeo de dependncias - procura resolver esses problemas. A
ideia a classe no mais resolver suas dependncias por conta prpria mas apenas declarar que depende de
alguma outra classe. E de alguma outra forma que no sabemos, algum resolver essa dependncia para ns.
O cdigo da GerenciadorDeProduto
fica com uma mudana sutil:
Captulo 2 - Injeo de dependncias e Inverso de Controle - Injeo de dependncias - Pgina 5
-
7/18/2019 FJ27 Caelum Spring
12/98
Caelum http://www.caelum.com.br
Spring Framework 3
public class GerenciadorDeProduto {
private ProdutoDA0 produtoDao;
public GerenciadorDeProduto(ProdutoDA0 produtoDao) {
this.produtoDao = produtoDao;
}
public void novoProduto() {
Produto produto = pedeDadosDoProdutoAoUsuario();
this.produtoDao.salvar(produto);
mostraConfirmacao();
}
}
Repare que, agora, nossa classe no est mais acoplada implementao alguma do
ProdutoDAO
nem
import
do
ProdutoMemoriaDA0
existe mais. O que nossa classe diz que ela
depende de algum ProdutoDAO
sem acoplar-se a nenhuma implementao especfica e sem se preocupar em como resolver essa dependncia.
Mas quem for usar essa minha classe, agora, vai precisar satisfazer as dependncias. Pode parecer que
estamos apenas empurrando o problema, mas temos que olhar as classes isoladamente. Perceba que, do
ponto de vista
apenas da
GerenciadorDeProduto,
estamos recebendo nossas dependncias no construtor. Elas
esto sendo
injetadas
para ns. Como isso vai acontecer de verdade no problema nosso.
E, o melhor, imagine que o DAO em uso aquele do Hibernate. E que a classe
ProdutoHibernateDA0
tambm vai usar injeo de dependncias para recebera
Session
que ela precisa. Veja um esboo dessa
classe:
public class ProdutoHibernateDAO implements ProdutoDAO {
private Session session;
public ProdutoHibernateDAO(Session session) {
this.session = session;
}
// implementacoes dos metodos com Hibernate, usando a Session
}
Aqui, temos dois pontos importantes. O primeiro que a classe
ProdutoHibernateDA0
est usando Dl para
no precisar se preocupar em abrir uma session (um processo complicado). Mas, mais importante, lembrar da
nossa
GerenciadorDeProduto:
magine ter que gerenciar nossa dependncia do DAO diretamente e ter que se
preocupar no s com o
ProdutoHibernateDA0
como com a dependncia de session que ele tem. Precisaramos
resolver as duas coisas, dando ainda mais trabalho.
Contudo, como usamos Dl na classe
GerenciadorDeProjeto,
nem sabemos qual a implementao do DAO
em uso e, muito menos, suas eventuais dependncias.
Se gerenciar as prprias dependncias j ruim, o
que dizer de gerenciar as dependncias das dependncias.
Mas voltamos ao ponto de que, quem for usar a
GerenciadorDeProjeto
ter um imenso trabalho Ele ter
que conhecer a
GerenciadorDeProjeto,
resolvera dependncia dela em
ProdutoDAO, 0
que, por sua vez, far
ele conhecera implementao
ProdutoHibernateDA0
e ainda suas dependncias em
Session,
alm de saber
como se cria uma Session. Parece muita coisa para uma classe s.
a que entram em cena os
Frameworks de Injeo de dependncia.
Em projetos maiores, teremos
muitas classes com muitas dependncias umas nas outras, tanto direta quanto indiretamente. Resolver esse
complexo grafo de dependncias na mo possvel mas muito trabalhoso. Existem frameworks cujo objetivo
resolver as dependncias.
Captulo 2 - Injeo de dependncias e Inverso de Controle - Injeo de dependncias - Pgina 6
-
7/18/2019 FJ27 Caelum Spring
13/98
Caelum http://www.caelum.com.br
Spring Framework 3
Registramos nesses frameworks todas as nossas classes e deixamos a cargo dele resolver as interdepen-
dncias entra elas. Nos preocupamos apenas em criar as classes usando o pattern de injeo de dependncias
e em registrar as classes nos frameworks.
E um dos frameworks mais importantes nessa parte de DI justo o
Spring.
2.4 - Inverso de controle e o princpio de hollyvvood
Injeo de dependncia , na verdade, um modo de aplicar uma tcnica muito mais ampla chamada de
Inverso de Controle (loC - Inversion of Control).
A ideia principal de IoC inverter quem est no controle
das invocaes no nosso cdigo.
Lembre do nosso sistema: antes, ns invocvamos diretamente o construtor da
ProdutoMemoriaDA0
resol-
vendo as dependncias manualmente. Ns controlvamos como e quando a criao do DAO aconteceria.
Quando passamos a usar DI, invertemos o controle da criao desse DAO. Nossa classe no sabe mais
nem como e nem quando a dependncia ser criada. Algum criar essa instncia e passar para ns. Usando
Spring, o framework que passa a dar
new
nas nossas classes e no nossa aplicao diretamente.
Isso inverter o controle. O framework passa a chamar as coisas para ns ao invs da nossa aplicao ser
a responsvel por isso.
H quem chame loC do
Princpio de Hollywood.
Dizem que h uma frase bastante famosa no mundo dos
artistas de Hollywood que diz:
"Don't call us; we call you" -
ou
No nos chame; ns te chamamos .
a ideia
do loC onde paramos de invocar os mtodos daquilo que precisamos e passamos a receber coisas prontas e a
ser invocados pelo nosso framework.
Dl uma forma de se fazer IoC mas no a nica. A ideia geral plugar o cdigo da aplicao em algum
framework que far as invocaes certas e tudo funcionar. Alguns outros exemplos:
Quando usamos uma
HttpServlet,
implementamos um mtodo
doGet
para tratar requisies Web. Mas
no nos preocupamos em receber essas requisies e invocar o mtodo no momento certo. Apenas
criamos nossa servlet, jogamos ela no container e ele invoca o mtodo para ns.
Quando programamos para Desktop com Swing, frequentemente precisamos tratar eventos do usurio
como, por exemplo, um clique. Ao invs de chamarmos um mtodo para saber se o clique for feito, no
Swing, registramos um
Listener
e somos notificados do evento. Ou seja,
o Swing invoca o mtodo do
nosso listener no momento do clique sem precisarmos nos preocupar.
Ao usar EJBs, s vezes precisamos saber, por exemplo, em que momento nosso objeto foi passivado. Po-
demos saber isso implementando um mtodo de
callback
que ser invocado pelo container no momento
da passivao. No EJB 2.x, usvamos o famoso
ejbPassivate;
no 3.x, podemos anotar qualquer mtodo
COM @PrePassivate.
H ainda outros exemplos onde invertemos o controle de invocao do nosso cdigo e deixamos a cargo de
algum as chamadas no momento certo.
2.5 - Para saber mais: Registry como alternativa a Dl
Outra forma de obtermos a instncia de um
ProdutoDAO
sem precisar dar new
diretamente e se acoplar com
a implementao da interface utilizar o design pattern
Registry.
Muito utilizado at a verso 1.4 da J2EE, o
Registry um padro de projeto que utiliza a soluo de registrar os recursos em um diretrio de componentes
central - no EJB, era o famoso
JNDI (Java Naming and Directory Interface).
Assim, temos um lugar
comum
onde as classes podem obter referncias a outras classes.
Captulo 2 - Injeo de dependncias e Inverso de Controle - Inverso de controle e o princpio de hollywood - Pgina 7
-
7/18/2019 FJ27 Caelum Spring
14/98
Caelum http://www.caelum.com.br
Spring Framework 3
No exemplo, poderamos fazer a classe
GerenciadorDeProduto
obter uma referncia de
ProdutoDAO
por meio
do Registry JNDI. Primeiro, precisamos registrara instncia do DAO que queremos (processo que chamado de
bind). Geralmente isto feito pelo container J2EE utilizando arquivos de configurao
(deployment descriptors)
em um cdigo parecido com este:
//Registra do DO no Registry
Context ctx = new InitialContext();
ctx.bind("produtoDao", new ProdutoMemoriaDA0());
Nossa classe
GerenciadorDeProduto
pode, ento, obter uma referncia do tipo
ProdutoDAO
buscando no
Registry JNDI pelo nome registrado. Este processo tem o nome de
lookup:
package br.com.caelum.fj27;
public class GerenciadorDeProduto {
private ProdutoDAO produtoDao;
public GerenciadorDeProduto() {
try{
Context ctx = new InitialContext();
produtoDao = (ProdutoDAO) ctx.lookup("produtoDao");
} catch (NamingException ex) {
// tratamento de exceo
}
}
// outros metodos
}
Desta maneira, a inicializao do componente fica fora da classe
GerenciadorDeProduto
e, normalmente,
pode ser feita atravs de arquivos de configurao. Mas, mesmo assim, o lookup da instncia de
ProdutoDAO
continuar na classe
GerenciadorDeProduto.
Ou
seja, continuamos invocando algo e, portanto, isso no con-
siderado Inverso de Controle. apenas mais uma forma de se evitar o acoplamento com as implementaes
especficas das dependncias.
2.6 - Para saber mais...
Para saber mais sobre loC e DI, recomendamos a leitura dos artigos do Martin Fowler:
http: //martinfowler.comiarticles/injection.html http: 'martinfowler.com/bliki' Inversion0fControl.html
Captulo 2 - Injeo de dependncias e Inverso de Controle - Para saber mais... - Pgina 8
-
7/18/2019 FJ27 Caelum Spring
15/98
CAPTULO
3
Spring Framework
Homens sbios fazem provrbios, tolos os repetem
Samuel Palmer
Neste captulo, vamos ver o que o Spring Framework, qual sua arquitetura e qual seu princpio bsico de
funcionamento.
3.1
- O que ?
O Spring na verdade um
framework de inverso de controle
e no apenas de um framework de injeo
de dependncias. Ele faz mais coisas que apenas resolver suas dependncias, um framework completo de
servios para seus componentes.
O
Spring Framework
um container leve
(lightweight container),
ou container de POJO's segundo o pes-
soal do prprio Spring, com recursos de inverso de controle e orientao aspectos. O termo
container
usado pelo Spring, pois ele gerencia o ciclo de vida dos objetos configurados nele, assim como um container
Java EE faz com os EJB's. Porm, considerado um container leve, pois ao contrrio do container Java
EE em
suas primeiras verses, ele no intrusivo e as classes da aplicao no possuem dependncias com o Spring.
Alm disso, podemos dizer que o Spring tambm um framework de infraestrutura, pois prov servios
como gerenciamento de transaes e de segurana, alm de se integrar com frameworks ORM. Com
ele voc
pode ter praticamente todos os benefcios de Java Enterprise Edition (JTA, JPA, JCA, Remoting, Servlets, JMS,
JavaMail, JDBC, etc) mas sem utilizar EJB's.
Container
Podemos dizer que containers so programas utilizados para gerenciar componentes de uma apli-
cao. Um exemplo de um container um container de servlets, onde sua funo gerenciar os
componentes de interface web que conhecemos como Servlets e JSPs.
Princpios do Spring
O cdigo da aplicao no deve depender da
API Spring;
Spring no deve competir com boas solues j existentes no mercado, mas deve ser capaz de se integrar
a elas;
Teste de unidade uma tarefa crtica e o container no deve interferir neste objetivo.
9
-
7/18/2019 FJ27 Caelum Spring
16/98
Caelum http://www.caelum.com.br
Spring Framework 3
Benefcios do Spring
O container leve elimina a necessidade de cdigos repetitivos como lookups;
Framework com inverso de controle da injeo de dependncia que resolve automaticamente as depen-
dncias entre beans;
Cdigo comum vrias sees, como gerenciamento de transaes, so implementados com AOP;
Disponibiliza camadas de abstrao para outras tecnologias (como Hibernate, JPA, JDBC, JavaMail,
Quartz, etc).
3.2 - Arquitetura
do Spring
DAO
Spring JDBC
Transaction
rnanngerrent
ORM
~orneie
JPA
TopLirik
JDo
OJB
iBatie
JEE
JMX
JMS
JCA
Remoto1g
EJBs
Ernail
Web
Spring Web MVC
Framework Integration
Struts
WetrWork
Tapestr
J$F
Rich Wew Supporl
JSPs
Velocity
FreeMarker
PDF
Jasper Repcds
Excel
Spring Portlet MVC
OP
Sprr
OP
sgectJ integr3tion
Core
The InC container
Atualmente, o Spring est dividido em sete mdulos:
Mdulo Core
O mdulo principal o Core e representa as principais funcionalidades do Spring, como o container para
inverso de controle e injeco de dependncias. Neste mdulo, o principal elemento a interface
BeanFactory,
que prov uma implementaco do factory pattern, removendo do sistema a necessidade de singletons e desa-
coplando as dependncias de configuraces e especificaces da lgica de negcio do sistema.
Os outros so mdulos de integrao com diversas outras tecnologias que o Spring suporta, tais como:
Mdulo AOP
Spring AOP
Integrao com AspectJ
Captulo 3 - Spring Framework - Arquitetura do Spring - Pgina 10
-
7/18/2019 FJ27 Caelum Spring
17/98
Caelum http://www.caelum.com.br
Spring Framework 3
Mdulo DAO
Spring JDBC
Gerenciamento de transaces
Mdulo ORM
Hibernate
JPA
TopLink
JDO
OJB
iBatis
Mdulo Java EE
JMX
JMS
JCA
Remoting
EJBs
Email
Mdulo Web
Spring Web MVC
Integrao com Struts
Integrao com WebWork
Integrao com Tapestry
Integrao com JSF
Integrao com Rich View Support
Integrao com JSPs
Integrao com Velocity
Integrao com FreeMaker
Integrao com
PDF
Captulo 3 - Spring Framework - Arquitetura do Spring - Pgina 11
-
7/18/2019 FJ27 Caelum Spring
18/98
Caelum http://www.caelum.com.br
Spring Framework 3
Integrao com JasperReports
Integrao com Excel
Integrao com Spring Portlet MVC
3.3 - Introduo aos beans do Spring
Para entendermos o funcionamento do Spring, temos que entender o conceito de
Bean
que ele usa. Para o
Spring, qualquer objeto da sua aplicao e que est sob o gerenciamento do Spring considerado um
bean.
Um bean
nada mais do que uma classe Java que estar sob o gerenciamento do Spring, o container de
loC/DI o responsvel pelo gerenciamento deste bean, bem como suas dependncias.
3.4 - Configurando o Spring
Configurando os beans
As configuraes do Spring acontecem principalmente em um arquivo XML chamado
applicationCon-
text.xml.
No Spring 2.5, foi adicionado o suporte a anotaes, mas muitas tarefas ainda precisam do XML
e ele ainda usado em muitos projetos. Por isso, vamos primeiro ver como fazer as configuraes dos nossos
beans via XML antes de ver a abordagem com anotaes.
Veja a configurao de um bean no XML do Spring:
Tag beans
A tag
o elemento root do nosso arquivo XML. Dentro dela teremos as tags
que representam
a configurao dos objetos do nosso sistema na forma de bean para o Spring.
Na tag
,
temos duas propriedades principais:
id -
representa o identificador do nosso bean, o Spring no aceita id's repetidos;
class -
representa o FQN da nossa classe.
FQN
FQN significa
FuIIy-Qualified Name,
ou nome completo de uma classe. O FQN de uma classe
o nome da classe com o seu pacote completo. Por exemplo, o FQN da classe object
j ava . lang . Obj ect ,
o FQN da interface List
j ava util Li st.
Captulo 3 - Spring Framew ork - Introduo aos beans do Spring - Pgina 12
-
7/18/2019 FJ27 Caelum Spring
19/98
Caelum - http://www.caelum.com.br
Spring Framework 3
3.5 Iniciando o container
Aps feita a configurao dos nossos
beans
no Spring, precisamos iniciar o container de IoC. Esta iniciali-
zao muito simples e pode ser feita de diversas formas. Quando trabalhamos dentro de um container Web
com algum framework MVC, essa inicializao costuma ser automtica com apenas algumas configuraes.
Mas quando estamos trabalhando direto no
main,
sem container, precisamos iniciar o Spring explicitamente.
Podemos fazer isso usando a classe
ApplicationContext:
ApplicationContext context =
new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
Criado o contexto do Spring, podemos pedir uma instncia de qualquer bean registrado l. Invocando o
framework diretamente, basta passar o id do componente:
ProdutoDA0 dao = (ProdutoDA0) context.getBean("produtoDao");
A partir da verso 3 do Spring podemos utilizar um segundo parmetro do mtodo
getBean
para definir o
tipo do bean. Assim nem preciso fazer o cast:
ProdutoDA0 dao = context.getBean("produtoDao", ProdutoDao.class);
Tambm podemos descobrir o bean apenas pelo tipo (e no pela id):
ProdutoDA0 dao = context.getBean(ProdutoDao.class);
No exemplo acima deve existir apenas um bean compatvel com a interface
ProdutoDao.
Caso contrrio o
Spring cria um exceo.
3 C -
injetando as Dependncias: por construtor e por setter
Como vimos anteriormente, um dos principais recursos do Spring o gerenciamento automtico das depen-
dncias dos beans. Mas, por padro, a amarrao
(wiring)
das dependncias no feita de forma automtica.
Por isso, somos obrigados a configur-las uma por uma no arquivo XML.
Para fazermos essa a amarrao das dependncias com o Spring, temos duas opes: por construtor ou
por mtodos
setter.
Injetando dependncia por construtor
Na classe
GerenciadorDeProduto
que fizemos antes, declaramos a dependncia com
ProdutoDA0
no cons-
trutor. a forma comumente preferida hoje em dia e o Spring a suporta sem problemas.
Captulo 3 - Spring Framework - Iniciando o container - Pgina 13
-
7/18/2019 FJ27 Caelum Spring
20/98
Caelum http://www.caelum.com.br
Spring Framework 3
Injetando dependncia por setter
Poderamos ter escrito nossa classe
GerenciadorDeProduto
para receber a instncia do DAO que ela precisa
atravs de um mtodo
setProdutoDao
ao invs de receber no construtor.
Essa foi a forma preferida e incentivada no Spring durante muito tempo. No XML, a configurao um pouco
diferehte:
lmport
Selecione
General, Existing Projects into workspace.
Clique Next
Selecione
Archive File
e indique o arquivo
/caelum/zips/27/fj27-projeto-spring.zip
2)
Crie a classe
Produto no pacote
br.com.caelum. estoque:
package br.com.caelum.estoque;
public class Produto {
private Long id;
private String descricao;
private Integer quantidade;
//getters e setters
}
3)
Crie a interface ProdutoDAO no pacote
br . com. caelum. estoque . dao
Captulo 3 - Spring Framework - Exerccios: Projeto com Spring loC - Pgina 14
-
7/18/2019 FJ27 Caelum Spring
21/98
Caelum http://www.caelum.com.br
Spring Framework 3
package br.com.caelum.estoque.dao;
public interface ProdutoDA0 {
void salvar(Produto produto);
void alterar(Produto produto);
List listar();
Produto buscarPorld(Long id);
}
4)
Como ainda no vimos a integrao do Spring com Hibernate e nosso objetivo focar no Spring por en-
quanto, vamos criar uma implementao de DAO bem simples que apenas adiciona os produtos em uma
lista em memria.
Crie a classe
ProdutoMemoriaDAO
no pacote
br. com. caelum.estoque.dao
com a implementao simples do
DAO em memria. Ainda no implementaremos o mtodo de alterao:
package br.com.caelum.estoque.dao;
public class ProdutoMemoriaDA0 implements ProdutoDA0 {
private List produtos = new ArrayList();
public List listar(){
return produtos;
}
public void salvar(Produto produto) {
produtos.add(produto);
}
public Produto buscarPorld(Long id) {
return produtos.get(id.intValue() - 1);
}
public void alterar(Produto produto) {
}
}
5)
Vamos criar agora nossa classe
GerenciadorDeProduto.
Mais tarde, vamos transform-la em um componente
de um sistema Web usando Spring MVC. Por isso, vamos faz-la um pouco diferente da que vimos antes.
Ao invs de mostrar uma mensagem de confirmao para o usurio, vamos apenas retornar uma String de
confirmao para ele. E o objeto
Produto
que pediramos para o usurio preencher com os dados, vamos
receber como argumento no mtodo.
Crie a classe
GerenciadorDeProduto
no pacote
br. com. caelum.estoque:
Captulo 3 - Spring Framew ork - Exerccios:
Projeto
com Spring IoC - Pgina 15
-
7/18/2019 FJ27 Caelum Spring
22/98
Caelum http://www.caelum.com.br
Spring Framework 3
package br.com.caelum.estoque;
public class GerenciadorDeProduto {
private ProdutoDA0 produtoDao;
public GerenciadorDeProduto(ProdutoDAO produtoDao) {
this.produtoDao = produtoDao;
}
public void novoProduto(Produto produto) {
System.out.println("Salvando Produto.");
this.produtoDao.salvar(produto);
}
public List getProdutos(){
return produtoDao.listar();
}
}
Repare que, como estamos usando
DI,
declaramos a dependncia com o
DAO
no construtor.
6) Falta agora criar toda a configurao do Spring com os beans que acabamos de fazer.
a)
Abra o arquivo chamado
applicationContext.xml
que se encontra no diretrio
src
do seu projeto. Este
o arquivo de configurao do Spring.
b)
Coloque a configurao entre a tag
:
7) Para testarmos a injeo dos componentes que temos at agora, vamos utilizar uma classe simples com
mtodo main chamada
Testelnjecao, que j existe em seu projeto.
Nela, criamos o
Appl icat ionContext
do Spring e, logo em seguida, pediremos uma instncia do nosso
gerenciador de produtos. Queremos obter essa instncia sem precisar satisfazer as dependncias dela.
Abra a classe
Testalnjecao
que est no pacote
br. com. caelum. estoque:
Captulo 3 - Spring Framework - E xerccios: Projeto com Spring loC - Pgina 16
-
7/18/2019 FJ27 Caelum Spring
23/98
Caelum http://www.caelum.com.br
Spring Framework 3
package br.com.caelum.estoque;
public class Testalnjecao {
public static void main (String[] args) {
// cria o contexto do Spring
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
// obtm o gerenciador
GerenciadorDeProduto gerenciador =
context.getBean("gerenciadorProduto", GerenciadorDeProduto.class);
// cria um Produto como se o usurio tivesse preenchido um formulrio
Produto produto = new Produto();
produto.setDescricao("Livro Spring in Action");
produto.setQuantidade(10);
// chama a lgica e v o resultado
gerenciador.novoProduto(produto);
// verifica que o produto foi adicionao ao nosso dao em memoria
for (Produto p : gerenciador.getProdutos()) {
System.out.println("Descricao: " + p.getDescricao());
System.out.println("Quantidade: " + p.getQuantidade());
}
}
}
Execute essa classe como um programa Java e veja o resultado.
3.8 - Exerccios opcionais: Injeco com Setter e Tipos Bsicos
1)
Vamos agora na nossa classe
GerenciadorDeProduto
njetar o ProdutoDAO
atravs do
setter
Na classe
GerenciadorDeProduto
comente o construtor e gere um setter para receber o
ProdutoDAO:
public class GerenciadorDeProduto {
private ProdutoDAO produtoDao;
//comente o construtor e gere o setter
public void setProdutoDAO(ProdutoDAO produtoDao)
this.produtoDao = produtoDao;
}
public String novoProduto(Produto produto) {
this.produtoDao.salvar(produto);
return "salvo";
}
public List getProdutos() {
return produtoDao.listar();
}
}
Repare que ainda estamos usando DI, mas declaramos agora a dependncia no setter.
2)
Falta alterar a configurao do Spring para definir a injeo pelo setter.
Captulo 3 - Spring Framework - Exerccios opcionais: Injeco com Setter e Tipos Bsicos - Pgina 17
-
7/18/2019 FJ27 Caelum Spring
24/98
Caelum http://www.caelum.com.br
Spring Framework 3
a)
Procure a declarao do bean
gerenciadorProduto
no arquivo
applicationContext.xml.
b)
Tire a injeo pelo construtor, coloque a pelo setter:
-
7/18/2019 FJ27 Caelum Spring
25/98
Caelum http://www.caelum.com.br
Spring Framework 3
Jose
Joao
4) Vamos criar uma classe para testar as injees:
rie a classe
Testelnjecao2
no pacote
br.com.caelum.estoque .
1
public class Testelnjecao2 {
2
3
4
public static void main(String[] args) {
5
ApplicationContext applicationContext =
6
new ClassPathXmlApplicationContext("applicationContext.xml");
7
SpringBean springBean =
8
(SpringBean) applicationContext.getBean("springBean");
9
19 if (springBea n = null) {
11
12
System .out.println("instanciado ");
13
System.out.println(springBean.getNome());
14
System.out.println(springBean.getQuantidade());
15
System.out.println(springBean.getPropriedades().get("cidade"));
16
17
for (String string : springBean.getNomesO) {
18
System.out.println(string);
19
20
21
22 }
Rode a classe e verifique na sada do console que todas os atributos foram injetados pelo Spring.
Captulo 3 - Spring Framework - Exerccios Opcionais: Valores
Literais - Pgina 19
-
7/18/2019 FJ27 Caelum Spring
26/98
Caelum http://www.caelum.com.br
Spring Framework 3
Captulo 3 - Spring Framework - Exerccios Opcionais: Valores Literais - Pgina 20
-
7/18/2019 FJ27 Caelum Spring
27/98
CAPTULO
4
Spring MVC
O verdadeiro discpulo aquele que supera o mestre.
Aristteles
4.1 - Spring MVC
O padro de projeto MVC a forma mais utilizada para o desenvolvimento de aplicaes Web. A diviso
entre as camadas
Model
e View
atravs do intermedirio
Controller
simplifica a evoluo da aplicao e tambm
a manuteno de cdigo existente.
Existem vrias implementaes de frameworks MVC no mercado. Entre os mais famosas temos o
JavaSer-
ver Faces
e o Struts.
Nos mdulos do Spring, encontramos tambm um framework MVC que traz aos desenvol-
vedores as vantagens citadas acima, mas tambm, integrao simples com os outros servios de infraestrutura
do Spring, como DI, AOP e Transaes.
4.2 - Criando seu projeto web no Eclipse
Vamos importar um novo projeto para nosso Eclipse
com toda a estrutura de um projeto Web j pronto. Alm
disso, os jars do Spring e as classes que fizemos at agora tambm sero includas.
Vamos usar como container Web o Apache Tomcat 6, que pode ser baixado em
http: torncat.apache.org
Instalando e configurando o Tomcat
Entre na pasta
caelum
no seu Desktop e v na pasta
21
D dois cliques para abrir o arquivo
apache-tomcat-6.x.x.zip
Clique em
Extract e selecione o
Desktop
Volte ao Eclipse e Clique com o boto direito na aba
Server
Selecione New -> Server
Adicione um Servidor da pasta
Apache Tomcat
verso 6.X
Clique em Finish
Inicie
o Tomcat pelo cone da barra de ferramentas
21
-
7/18/2019 FJ27 Caelum Spring
28/98
Caelum http://www.caelum.com.br
Spring Framework 3
Importando o projeto
V em
File -> lmport
Selecione
General, Existing Projects into workspace.
Clique Next
Selecione
Archive File
e indique o arquivo
/caelum/zips/27/fj27-projeto-mvc.zip
D start no Tomcat e teste a url
http: localhost:8080 estoque
4.3 - Configurando o Spring MVC
O Spring MVC foi desenvolvido com base na classe
org. springframework.web. servlet .DispatcherServlet
que um
Servlet
que trata as requisies, redirecionamentos e outras funes que facilitam o uso do framework.
Como todo
Servlet,
precisamos configur-lo no
web.xml
da aplicao. Na configurao do
DispatchServlet
importante lembrar de informar o diretrio onde est o XML com as configuraes dos beans que o Spring vai
gerenciar, esse diretrio indicado atravs do parmetro
contextConf igLocation.
Veja como fica o trecho do
web.xml
com a configurao:
Spring MVC Dispatcher Servlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
/WEB-INF/spring/app-config.xml
1
Spring MVC Dispatcher Servlet
*.html
4.4 View Resolvers
No XML de configurao do Spring necessrio registrar o
ViewResolver,
que tem como objetivo inte-
grar
Controller e
View, deixando-os desacoplados. Com
o View Resolver, podemos utilizar vrias tecnologias
diferentes com nossos controllers. Por exemplo, JSP, Velocity ou XSLT.
Na configurao do bean, podemos dizer o
pref ix
e suff ix de onde estaro nossas views. Quando um
Controller executado, ele devolve o nome da View que deve ser renderizada para
DispatchServlet.
Ela por
sua vez passa o nome para o
ViewResolver
que descobre a view concatenando o nome retornado ao
pref ix
e
suff ix configurados.
Vamos usar a seguinte configurao:
-
7/18/2019 FJ27 Caelum Spring
29/98
Caelum http://www.caelum.com.br
Spring Framework 3
Nesta configurao, se o Controller devolvesse, por exemplo, a string "index", o
ViewResolver
procuraria a
seguinte view para renderizar "WEB-INF/views/index.jsp".
4.5 - Seu primeiro Controller
A partir do Spring 2.5, possvel utilizar anotaes para a configurao dos Controllers. Essas anotaes
trouxeram muitos benefcios para a utilizao do Spring MVC como a simplicidade de configurao de objetos
para representar a camada Controller.
Entre as anotaes que o Spring MVC disponibiliza, temos a @Controller que indica que o Bean deve ser
gerenciado. E a anotao
@RequestMapping
que informa a URL de acesso ao devido mtodo no controller.
Usando essas duas anotaes para criar um controller teramos:
package br.com.caelum.fj27.exemplo;
@Controller
public class MundoC ontroller {
@RequestMapping("ola")
pub lic String executar {
System.out.println("Executando o Controller");
return "ok"
}
}
Para executar o exemplo acima, basta chamar a
URL
da aplicao terminando em
/ola. Ex: http:
localhost:8080 spring
ola.htinl
O mtodo anotado com
@RequestMapping,
no tem restrio quanto a sua assinatura. A opo de retornar
uma String utilizada para informar qual view deve ser renderizada aps a execuo do mtodo.
No exemplo anterior, a view renderizada se chama
ok
e ter seu diretrio e extenso informadas pelo
ViewResolver.
Por exemplo:
WEB-INF/views/ok.jsp.
4.6 - Configurando
A anotao @Controller no lida por default. O Spring sempre usa o XML como padro e para usarmos
classes anotadas, temos que configurar o XML do Spring com a seguinte instruo:
Com isso, o Spring vai reconhecer as classes anotadas com @Controller.
Alm do elemento para reconhecer as anotaes @Controller, precisamos informar qual o pacote o Spring
deve rastrear os componentes anotados:
Lembrando que necessrio configurar o namespace corretamente.
-
7/18/2019 FJ27 Caelum Spring
30/98
Caelum http://www.caelum.com.br
Spring Framework 3
xmlns:context="http://www.springframework.org/schema/context
"
xmlns:mvc="http://www.springframework.org/schema/mvc
"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
">
4.7 - Exerccios: Nosso primeiro controller
1)
Vamos agora, criar a classe
ProdutosController
no pacote
br.com.caelum.estoque.controller.
Iremos
tambm anot-la com @Controller para que o Spring MVC possa reconhec-la.
package br.com.caelum.estoque.controller;
//importa
@Controller
public class ProdutosCo ntroller {
@RequestMapping("index")
publ ic Str ing index() {
return "produ tos/index";
}
}
2)
Configure o XML do Spring para habilitar o suporte a anotao @Controller e informar onde o spring
deve procurar por beans anotados. Adicione as seguintes linhas ao seu
app-config.xml
no diretrio WEB-
INF/spring/app-config.xml:
3)
Falta criar nossa
View.
Crie uma pasta chamada produtos em
WEB-INF/views/ e, dentro, uma JSP cha-
mada index.jsp
com o seguinte contedo de teste:
Spring MVC
4)
Inicie o servidor e acesse seu controller chamando a URL http://localhost:8080
/estoque /index.html
4.8 - Enviando dados para View
Os controllers do Spring podem enviar dados para as view renderizadas. Os mtodos do
Controller que iro
devolver dados a tela, devem declarar
ModelAndView como seu tipo de retorno.
O objeto
ModelAndView
carrega a informao da view a ser renderizada e tambm dos dados que devem ser
disponibilizados na view. Exemplo:
Captulo 4 - Spring MVC - Exerccios: Nosso primeiro controller - Pgina 24
-
7/18/2019 FJ27 Caelum Spring
31/98
Caelum http://www.caelum.com.br
Spring Framework 3
@Controller
public class ProdutosController {
@RequestMapping("listarProdutos")
public ModelAndView listar(){
List produtos = new ArrayList();
Produto macBook = new Produto();
macBook.setDescricao("Mac Book");
macBook.setQuantidade(100);
Produto ipad = new Produto();
ipad.setDescricao("IPad");
ipad.setQuantidade(200);
produtos.add(macBook);
produtos.add(ipad)
ModelAndView modelAndView = new ModelAndView("produto/lista");
modelAndView.addObject(produtos);
return modelAndView;
}
}
Acessamos o
ProdutosController
pela URL
littp://localhost:8080/estoque, produtos listarProdutos.html
. Na execuo do mtodo listar(), criamos uma lista contendo alguns produtos. Depois, criamos um objeto
mod.elAndview e passamos no construtor a pgina de retorno
lista
que fica dentro do diretrio
produto "WEB-
INF/views/produto/lista.jsp".
Nossa lista de produtos ento adicionada no objeto
ModelAndView
e o mtodo termina retornando o objeto
modelAndView.
Agora, podemos acessar a lista de produtos na JSP usando
Expression Language.
importante sabe qual
o nome que usamos para o acesso de nossa lista de produtos. O Spring utiliza uma conveno para isso. No
nosso exemplo, acessaramos da seguinte maneira na JSP:
${produto.descricao} -
${produto.quantidade}
O nome
produtoList
gerado pelo Spring devido ao nosso
List
ser declarado com um tipo genrico Produto:
List.
Se tivermos um List de String - List
-
, a forma de acesso seria -
${stringList}
4.9 - RequestMapping mais a fundo
@RequestMapping
permite o mapeamento de urls por
Controller. Por exemplo, podemos mapear um controller
para
/produtos
e ento para o acesso a qualquer mtodo mapeado dentro do controller seria necessrio a
chamada
a URL
da classe anteriormente. Ex:
Captulo 4 - Spring MVC - RequestMapping mais a fundo - Pgina 25
-
7/18/2019 FJ27 Caelum Spring
32/98
Caelum http://www.caelum.com.br
Spring Framework 3
@Controller
@RequestMapping(value="/produtos")
public class ProdutosController {
@RequestMapping(value="/listar")
public ModelAndView listar(){
//.
.
}
@RequestMapping(value="/salvar")
public String salvar(){
}
}
Para acessar o mtodo
listar
)
de
ProdutosController
precisamos chamar a seguinte a url que nosso
controller foi mapeado
/produtos
e ento a url do mtodo
/listar. Ex:
http:f locadhost:8080/estoque/produtos
listar.html
4.10 - O Controller de Produto
O Controller
de Produto vai acessar a camada DAO que, no momento, representada com dados em
memria. O mtodo
listar
) de
ProdutoMemoriaDAO
retornar uma lista com todos os produtos cadastrados.
O
Controller
deve obter esses dados e disponibiliz-los para o view que ento vai list-los em tela.
4.11 - Gerenciamento e Injeo
No ltimo capitulo, mapeamos a classe
ProdutoMemoriaDAO
e informamos que ela era uma dependncia de
GerenciadorDeProduto
no XML. O Spring tambm prov a configurao de componentes e suas dependncias
fazendo o uso de anotaes. Ento vamos configurar
ProdutoMemoriaDAO
como um componente para poder
injeta-la como dependncia de
ProdutosController.
A anotao @component deve ser utilizada para configurar objetos que o Spring deve gerenciar em seu
container.
package br.com.caelum.dao;
@Component
public class ProdutoMemoriaDAO implements ProdutoDA0 {
// . .
}
Essa anotao equivalente a seguinte linha de XML:
A anotao
@Autowired
deve ser utilizada para indicar uma dependncia e que a mesma deve ter seu valor
injetado.
@Controller
public class ProdutosController {
@Autowired
private ProdutoDA0 produtoDAO;
}
Captulo 4 - Spring MVC - O Controller de Produto - Pgina 26
-
7/18/2019 FJ27 Caelum Spring
33/98
Caelum http://www.caelum.com.br
Spring Framework 3
S podemos injetar beans gerenciados em outros beans tambm gerenciados. No exemplo acima injetamos
O ProdutoDAO
no
ProdutosController
porque ambos so gerenciados pelo o Spring as anotaes @component e
@Controller tem como objetivo o mesmo, sendo informar o Spring que ele deve gerenciar aqueles objetos.
4.12 - Exerccios - Listando os Produtos
1)
Adicione a anotao @ component na sua classe
ProdutoMemoriaDAO.
@Component
public class ProdutoMemoriaDAO implements ProdutoDAO {
}
2)
Vamos criar o mtodo que vai listar os produtos em nossa classe
ProdutosController.
O mtodo listar()
vai fazer uma chamada ao ProdutoDAO que vai ser injetado pelo Spring e adicionar seu resultado no objeto
ModelAndVlew.
@Controller
@RequestMapping(value="/produtos")
public class ProdutosController {
@Autowired
private ProdutoDAO produtoDAO;
// metodo ndex()
@RequestMapping(value="/listar")
public ModelAndView listar() {
ModelAndView modelAndView = new ModelAndView("produtos/lista");
modelAndView.addObject(produtoDAO.listar());
return modelAndView;
}
}
3)
Crie um JSP chamado Iista.jsp
dentro do diretrio "WEB-INF/views/produtos/lista.jsp" para mostrar os pro-
dutos que so disponibilizados pela chamada do mtodo listar() de
ProdutosController.
Lista Produtos
-
7/18/2019 FJ27 Caelum Spring
34/98
Caelum http://www.caelum.com.br
Spring Framework 3
4.1:3 URLsanugavels
@RequestMapping
pode ser usada tambm para criao de urls bonitinhas. Supondo que temos o
ProdutosController
e ele tem um mtodo que deve listar um produto especifico de determinado
id.
O m-
todo poderia ter a seguinte estrutura:
@Controller
@RequestMapping(value="/produtos")
public class ProdutosController {
@RequestMapping(value="/listar")
public ModelAndView listar(Long id){
//
}
}
E poderamos executar o mtodo atravs da url "/produtos/listar?idade=22" o parmetro idade seria passado
ao listar )
que por sua vez filtraria o produto por seu
id
e ento devolveria para a View.
Ultimamente um recurso muito utilizado na web so as urls amigveis, que so urls mais legveis ao usurios.
Poderamos implementar nosso mtodo dessa forma:
@Controller
@RequestMapping(value="/produtos")
public class ProdutosController {
@RequestMapping(value="/listar/{id}")
public ModelAndView listar(@PathVariable Long id){
//..
}
}
Agora podemos executar nosso mtodo atravs da seguinte url "produtos/listar/22" e assim o mtodo
listar )
seria executado, o Spring por sua vez iria verificar que informamos que um valor vindo na url se-
ria uma varivel {id} e que informamos que o mesmo iria ser passado ao mtodo
@PathVariable
4
.
14 -
,,,Melh9r, uso do HTTP
O uso dos verbos do http corretamente muito importante trazem benefcios para nossa aplicao. O
GET
por exemplo, tem como objetivo buscar informaes e por isso seus parmetros so passados na url. Se
utilizarmos isso de maneira correta os usurios da aplicao podem se beneficiar para fazer o bookmark de
url de relatrios. Como as informaes vo por parmetros de url, eles podem chama-las todas as vezes sem
problemas e tambm passar para que outras pessoas vejam o mesmo relatrio. Podemos informar ao Spring
que devido mtodo s pode ser acessado por um determinado verbo. Ex:
@Controller
@RequestMapping(value="/produtos")
public class ProdutosController {
@RequestMapping(value="/listar/{id}", method=RequestMethod.GET)
public ModelAndView listar(@PathVariable Long id){
//
}
}
Captulo 4 - Spring MVC - URLs amigveis - Pgina 28
-
7/18/2019 FJ27 Caelum Spring
35/98
Caelumhttp://www.caelum.com.br
Spring Framework 3
Se tentarmos acessar a url "/produtos/listar/22" utilizando um formulrio com o verbo
POST
o spring no
permitira devido a uri ser ligada a utilizao do verbo
GET.
4.15 - Exercicios: Melhor uso do http
1)
Vamos criar o mtodo
mostrar()
em ProdutosController.
Nele vamos usar o recurso de Url Friendly e
receber o id do
Produto
detalhado na url. Iremos tambm colocar ambos mtodos
mostrar()
e listar()
para apenas responderem ao verbo GET do http porque ambos so utilizados para pesquisa.
package br.com.caelum.estoque.dao;
/ / im ports
@Controller
@RequestMapping(value="/produtos")
public class ProdutosC ontrol ler {
@Autowired
private ProdutoDA0 produtoDAO ;
/ /metodo index()
@RequestMapping(value="/listar", method=RequestMethod.GET)
public Mo delAndV iew listar() {
ModelAndView modelAndView = new ModelAndView("produtos/lista");
modelAndView.addObject(produtoDAO.listar());
return modelAndView;
}
@RequestMapping(value="/mostrar/{id}" , method=RequestMethod.GET)
public ModelAndView m ostrar(@PathVariable Long id){
ModelAndView m odelAndView = new M odelAndView("produtos/mostrar");
modelAndView.addObject(produtoDAO.buscarPorId(id));
return modelAndView;
}
2)
Precisamos tambm, criar a jsp que vai mostrar o
Produto
detalho. O nome da jsp
mostrar
e deve ser
criada no diretrio
"WEB-INF/views/produtos".
D etalhes do Produto
Id :
Descricao :
Quantidade :
3)
A listagem de produtos deve ser alterada para ter um link que vai chamar o mtodo mostrar, para o
Produto
ser detalhado.
Captulo
4 -
Spring MVC - Exercicios: Melhor uso do http - Pgina 29
-
7/18/2019 FJ27 Caelum Spring
36/98
Caelum http://www.caelum.com.br
Spring Framework 3
Lista Produtos
${produto.descricao} - ${produto.quantidade} -
detalhes
4) Reinicie o servidor de aplicao e teste a pgina de detalhes.
4.16 - Receben do paranttros de. Forrnulario
Um grande poder dos frameworks MVC atuais a capacidade de converter dados em texto passados como
parmetros via HTTP para objetos do nosso domnio. Se temos o seguinte bean:
public class Produto {
private Long id;
private String descricao;
private Integer quantidade;
// get e set
}
O Controller que tem que receber o objeto do tipo
Produto
como parmetro para o mtodo, deve declarar no
parmetro do mtodo que vai ser chamado.
@Controller
@RequestMapping(value="/produtos")
public class ProdutosController{
@RequestMapping(value="/salvar")
public String salvar(Produto produto){
System.out.println(produto.getDescricao());
System.out.println(produto.getQuantidade());
return "ok";
}
}
O formulrio HTML, que vai fazer a requisio ao mtodo
salvar () deve passar os parmetros que devem
ser setados no parmetro do mtodo. O nome dos parmetros sendo enviado devem seguir o nome do conjunto
de getters e setters do parmetro do mtodo sendo chamado. No nosso exemplo, o parmetro seria o
Produto
e os getters e setters seriam para as propriedades descricao
e quantidade.
Captulo 4 - Spring MVC - Recebendo paramtros de Formulario - Pgina 30
-
7/18/2019 FJ27 Caelum Spring
37/98
Caelum http://www.caelum.com.br
Spring Framework 3
Quando a requisio feita pela URL http:,./localhost:8080/estoque/produtos/salvar.html o mtodo
salvar()
de
ProdutosController
executado. O Spring MVC verifica que esse mtodo recebe um parme-
tro que do tipo Produto.
Ento o Spring MVC procura na requisio parmetros que tenham o nome de
alguma das propriedades do bean.
No exemplo acima, so enviados os parmetros
descricao
e
quantidade.
O Spring ento verifica que nosso
bean
Produto
tem duas propriedades com o mesmo nome. Lembrando que propriedades em Java o conjunto
get e set para um atributo, no exemplo
getDescricao(), setDescricao()
e
getQuantidade(), setQua_ntidade().
4.17 Forward X Redirect
Toda execuo de mtodo em algum
Controller
pode devolver String
ou ModelAndView
que informam qual
view deve ser renderizada. Podemos tambm no dizer o nome de uma view mas a url de outro mtodo em um
Controller.
Por exemplo:
@Controlller
@RequestMapping(value="/produtos")
public class ProdutosController {
@RequestMapping(value="/index")
public String index(){
return "produtos/listar.html"
}
@RequestMapping(value="/listar")
public ModelAndView listar(){
//....
}
No exemplo acima ao chamar /index
o Spring faz o foward para /produtos/listar
executando ento o mtodo
listar O. O forward o comportamento padro do spring mas podemos tambm fazer o
redirect da ao.
@Controlller
@RequestMapping(value="/produtos")
public class ProdutosController {
@RequestMapping(value="/index")
public String index(){
return "redirect:produtos/listar.html"
}
@RequestMapping(value="/listar")
public ModelAndView listar(){
//
}
}
Captulo 4 -
Spring MVC - Forward X Redirect - Pgina 31
-
7/18/2019 FJ27 Caelum Spring
38/98
Caelum http://www.caelum.com.br
Spring Framework 3
4.18 Exerccios Cadastro de Produto
1)
Crie a jsp
form.jsp
no diretrio "WEB-INF/views/produtos" para o cadastro de produtos.
Cadastro de Produtos
-
7/18/2019 FJ27 Caelum Spring
39/98
Caelum http://www.caelum.com.br
Spring Framework 3
Escopo Singleton
O escopo do tipo
singleton
define que ser criado uma nica instncia do bean para todas requisies
recebidas pelo Spring para aquele bean. O Spring garante que esta instncia ser nica para cada instncia
do loC container do Spring. Se tivermos um nico
BeanFactory
ou
ApplicationContext,
teremos uma nica
instncia de um bean do tipo
singleton. singleton
o padro.
Escopo Prototype
O escopo do tipo
prototype
define que ser criada uma nova instncia do bean para cada requisio recebida
pelo Spring para aquele bean.
4.20 Web Escopos: Request, Session, Global Session
Alm dos escopos
singleton
e
prototype,
o Spring disponibiliza mais trs escopos de uso especfico em
aplicaes web:
request, session e
global session.
Escopo Request
O escopo do tipo
request
define que o ciclo de vida do bean ser atrelado a um Request HTTP. O Spring
garante que cada request possui sua prpria instncia do bean. Ao final do request, o objeto descartado.
Escopo Session
O escopo do tipo
session
gerencia o ciclo de vida do bean baseado na
HttpSession
do usurio.
Escopo Global Session
O escopo do tipo
global session
gerencia o ciclo de vida do bean baseado na
HttpSession
do usurio. Este
escopo semelhante ao escopo de
session
visto anteriormente, com a diferena que ele pode ser lido em
outros contexto para aplicao que usam a tecnologia de Portlets.
Captulo 4 - Spring MVC - Web Escopos: Request, Session, Global Session - Pgina 33
-
7/18/2019 FJ27 Caelum Spring
40/98
Caelum http://www.caelum.com.br
Spring Framework 3
Captulo 4 - Spring MVC - Web Escopos: Request, Session, Global Session - Pgina 34
-
7/18/2019 FJ27 Caelum Spring
41/98
CAPTULO
5
Integrando Spring, Hibernate e tecnologias
de Persistncia
5.1 - Introduo - Onde o Spring pode ajudar ao usar o Hibernate
Dentre as diversas caractersticas do Spring uma das que mais chama a ateno a integrao nativa com
diversas tecnologias importantes do mercado, dentre eles est o
hibernate,
a principal ferramenta ORM para
Java.
Mas como o Spring ajuda a trabalhar com o Hibernate?
De diversas maneiras A primeira delas atravs da principal funcionalidade do Spring, o controle de
objetos. O Spring pode controlar a abertura e fechamento da
SessionFactory
do Hibernate, com isso
todos
os
componentes do Spring podem receber como dependncia a SessionFactory, agora, controlada pelo Spring.
Outra parte importante do Spring o controle transacional que ele oferece. Ao delegar o controle da Ses-
sionFactory para o Spring, ele consegue abrir e fechar transaes de maneira automtica, de maneira muito
parecida com o JTA.
Alm de se integrar ao Hibernate o Spring tambm pode se integrar JPA, JDBC e outras ferramentas de
persistncia.
5.2 - Configurando o Hibernate no Spring
Para funcionar a integrao com o Hibernate o Spring disponibiliza uma
Factory Bean
para a SessionFactory
do Hibernate. Utilizando esta
factory
fazemos com que a SessionFactory
do hibernate seja gerenciada pelo
Spring.
AnnotationSessionFactoryBean
A
Factory Bean
que o
Spring possui a
org. springframework.orm.hibernate3.annotation.AnnotationSessionFac
Esta classe deve ser configurada como um bean do Spring em seu xml de configurao.
A classe
AnnotationSessionFactoryBean
nos permite configurar todas as propriedades do Hibernate dire-
tamente no arquivo do Spring, no necessitando o uso do arquivo de configurao do prprio do Hibernate
hibernate.cfg.xml.
jdbc:mysql://localhost/fj27
com.mysql.jdbc.Driver
-
7/18/2019 FJ27 Caelum Spring
42/98
Caelum http://www.caelum.com.br
Spring Framework 3
true
org.hibernate.dialect.MySQLDialect
true
true
update
br.com.caelum.estoque.model.Produto
Ao integrarmos o Hibernate ao Spring, a configurao do Hibernate, que antes era feita separadamente,
passa a ser feita diretamente no Spring. Isso necessrio para deixarmos o Spring gerenciar a criaco da
SessionFactory
do Hibernate permitindo assim que o Spring faa a injeco automtica da sessionFactory do
Hibernate.
destroy-method
A propriedade
destroy
method
da tag
bean
o nome do mtodo que ser invocado sempre que o
Spring finalizar o ciclo de vida da nossa
SessionFactory.
hibernate.cfg.xml
Ao invs de configurar o hibernate direto no Spring, podemos manter o arquivo hibernate.cfg.xml
separado e apenas referenci-lo no Spring:
classpath:location_of_config_file/hibernate.cfg.xml
5.3 - ProdutoHibernateDA0
Agora podemos criar um novo DAO que realmente acesse o banco de dados. Para isso basta pedir para
o Spring injetar uma
SessionFactory
em alguma classe. Lembrando que o Spring injeta apenas beans geren-
ciados em outros tambm gerenciados, para isso devemos declarar que nosso DAO deve ser gerenciado pelo
Spring anotando-o com @component.
Captulo 5 - Integrando Spring, Hibernate e tecnologias de Persistncia - ProdutoHibernateDAO - Pgina 36
-
7/18/2019 FJ27 Caelum Spring
43/98
Caelum http://www.caelum.com.br
Spring Framework 3
@Component
public class ProdutoHibernateDA0 implements ProdutoDA0 {
private Session session;
@Autowired
public ProdutoHibernateDAO(SessionFactory factory) {
session = factory.openSession();
}
public List listar(){
List produtos = session.createQuery("from Produto").list();
return produtos;
}
public void salvar(Produto produto) {
session.save(produto);
}
public Produto buscar(Long id) {
return session.get(Produto.class, id);
}
public void alterar(Produto produto) {
session.update(produto);
}
}
5A
-
@Repository
Anteriormente comentamos que as anotaes
wontroner
e
@Component
tinham o mesmo objetivo, indicar
ao Spring que os beans anotados devem ser gerenciados e que a diferena entre as mesmas era apenas
semntica. Para o caso dos DAOs temos a mesma situao, podemos anotar nossos DAOs com
@Repository,
ela ter o mesmo efeito da @Component.
5.5
-
Exerccios
1) Faa o mapeamento da classe Produto.
package br.com.caelum.estoque;
@Entity
public class Produto {
@Id
@GeneratedValue
private Long id;
private String descricao;
private Integer quantidade;
//getters e setters
}
2)
Abra o arquivo
app-config.xml
no diretrio "WEB-INF/spring", e adicione as seguintes
linhas
Captulo 5 - Integrando Spring, Hibernate e tecnologias de Persistncia - @Repository - Pgina 37
-
7/18/2019 FJ27 Caelum Spring
44/98
Caelum http://www.caelum.com.br
Spring Framework 3
jdbc:mysql://localhost/fj27
com.mysql.jdbc.Driver
root
org.hibernate.dialect.MySQLDialect
true
true
update
true
br.com.caelum.estoque.Produto
3)
Crie a classe
ProdutoHibernateDAD
no pacote
br . com. caelum. estoque . dao:
@Repository
public class ProdutoHibernateDAO implements ProdutoDAO {
private Session session;
@Autowired
public ProdutoHibernateDAO(SessionFactory factory) {
session = factory.openSession();
}
public List listar(){
List produtos =
session.createQuery("from Produto").11st();
return produtos;
}
public void salvar(Produto produto) {
session.save(produto);
}
public Produto buscarPorld(Long id) {
return (Produto) session.get(Produto.class, id);
}
public void alterar(Produto produto) {
session.update(produto);
}
4)
Reinicie o servidor e tente fazer o cadastro de algum produto.
No funcionar.
Leia a exceo e sua causa
raiz
(root
cause .
O que aconteceu?
Capitulo 5 - Integrando Spring, Hibernate e
tecnologias de Persistncia - Exerccios - Pgina 38
-
7/18/2019 FJ27 Caelum Spring
45/98
Caelum http://www.caelum.com.br
Spring Framework 3
5.6 @Qualifier
Ao testar o sistema o Spring lanou uma exeo na nosso console. Isso aconteceu porque o Spring descobre
o que injetar nos
beans
atravs do
tipo
do objeto a ser injetado. No nosso caso o Spring tenta injetar algum
bean
que implemente a interface
ProdutoDAO, porm
existem duas implementaes, a
ProdutoMemoriaDAO
e a
ProdutoHibernateDAO,
com isso o Spring se perde na hora de fazer a injeo.
Neste nosso caso poderamos simplesmente apagar a
ProdutoMemoriaDA0
que resolveria o problema, po-
rm em cenrios que realmente devam existir duas implementaes devemos especificar qual delas queremos
receber como injeo. exatamente esse o objetivo da anotao
@Qualifier.
Com o
@Qualifier
podemos especificar atravs do id do bean
qual implementao queremos receber.
public class ProdutoC ontroller {
@Autowired
Nualifier("produtoHibernateDAO")
private ProdutoDAO produtoDAO;
/ /cdigo antigo
}
Indicamos o nome
produtoHibernateDAO
porque o Spring configura o id dos
beans
anotados atravs do
nome da classe. A sua politica se o nome no foi passado diretamente via uma das anotaes
@Controller
, @Component
e @Repository
ele simplesmente coloca o nome da classe anotada transformando a primeira letra
do nome em minuscula. Neste caso
ProdutoHibernateDAO
fica produtoHibernateDAO.
Fora a facilidade proporcionada pelo Spring, tambm tiramos proveito do uso do polimorfismo, que permitiu
uma troca tranquila da implementao.
5.7 - Exerccios
1) Altere sua classe controler para receber o
ProdutoHibernateDAO
ao invs do
ProdutoMemoriaDA0
@Controller
@RequestMapping(value="/produtos")
public class ProdutosC ontroller {
@Autowired
@Qualifier("produtoHibernateDA0")
private ProdutoDAO produtoDAO;
/ /cdigo antigo
}
2) Cadastre alguns produtos.
5.8 - No quero escolher um objeto, quero um padro
Embora possamos resolver a ambiguidade da injeo atravs do @Qualifier, muitas vezes um
bean
muito
mais injetado que o outro. Nesse cenrio o Spring oferece uma anotao que marca um bean como sendo o
padro a ser injetado a @Pr imary.
Caso no seja usado nenhum
@Qualifier
o bean anotado com @Primary
ser
o injetado.
Captulo 5 - Integrando Spring, Hibernate e tecnologias de Persistncia - @Qualifier - Pgina 39
-
7/18/2019 FJ27 Caelum Spring
46/98
Caelum - http://www.caelum.com.br
Spring Framework 3
Exefcidlos
1)
Anote a classe
ProdutoHibernateDA0
COM
@Primary:
@Repository
@Primary
public class ProdutoHibernateDA0 implements ProdutoDA 0{
//codigo ja existente
}
2)
Retire o
@Qualifier do atributo
produtoDAO da classe
ProdutoController,
deixando apenas a anotao
@Autowired:
public class ProdutoController{
@Autowired
ProdutoDAO produtoDAO;
}
5.10 - Transaes com Spring Spring Transaction
Alm do gerenciamento da
SessionFactory o
Spring tambm pode controlar a abertura e fechamento de
transaes.
O controle de transao pode ser feito via xml ou via anotao.
O
mais simples via anotao, porm, por motivos de referncia segue abaixo um exemplo de como o
controle de transao pode ser feito via xml:
-
7/18/2019 FJ27 Caelum Spring
47/98
ri Caelum
http://www.caelum.com.br
Spring Framework 3
@Repository
@Transactional
public class ProdutoHibernateDAO implements ProdutoDA0 {
//codigo
}
Porm at o momento nosso sistema no fez o uso de transaes. O hibernate est configurado com o
autocommit ativado, dando commit em todas nossas operaes automaticamente. Tambm temos que lembrar
que o tipo de tabela utilizada no MySQL no da suporte a transaes e por isso apenas o flush do autocommit
basta para os dados serem persistidos.
O MySQL tem dois tipos de tabela, Mylsam e InnoDB. Mylsam que a
default
no Ubuntu, no oferece
suporte a transaes e por isso no tivemos problemas at o momento. Para testarmos o controle de transaes
vamos alterar o tipo de tabela do MySQL, mudando o dialeto do Hibernate.
Alterar:
org.hibernate.dialect.MySQLDialect
Para :
org.hibernate.dialect.MySQL5InnoDBDialect
E tambm remover a linha do autocommit:
true
5.11 - Configurando o TransactionManager
Para o suporte a transao ser ativado precisamos fazer duas configuraes no xml do Spring.
A primeira habilitar o gerenciador de transao. Porm como o controle do Spring pode ser para JPA,
Hibernate, JDBC e outros, devemos configurar o gerenciador exatamente para uma dessas tecnologias. No
caso do hibernate a nica dependncia que o TransactionManager precisa uma
SessionFactory.
-
7/18/2019 FJ27 Caelum Spring
48/98
Caelum http://www.caelum.com.br
Spring Framework 3
@Repository
@Transactional
public class ProdutoHibernateDA0 implements ProdutoDAO {
private SessionFactory sessionFactory;
@Autowired
public ProdutoHibernateDAO(SessionFactory factory) {
this.sessionFactory = factory;
}
public void salvar(Produto produto) {
this.sessionFactory.getCurrentSession().save(produto);
}
//outros metodos
}
Obter a
session
atravs do
getCurrentSession
o recomendado pela documentao do Spring.
5
1
; EEm?nclicicns
1)
Altere o arquivo
app
-
conf ig xml
para que o dialeto do MySQL seja
InnoDB
e com isso tenhamos suporte s
transaes com o banco de dados manualmente:
org.hibernate.dialect.MySQL5InnoDBDialect
2)
Delete a linha que configura o autocommit:
true
3)
Tente cadastrar um produto novo
Entre no MySQL para conferir a insero do dado:
Abra o terminal do Linux
digite o comando
mysql -u root
agora dispare um select na tabela de Produtos
use fj27;
select * from Produto;
Repare que o produto no est l
Tabelas antigas
Se o produto foi inserido, provavelmente porque a tabela ainda est no formato
MyISAM, mude-a
para
InnoDB
com o comando: alter table Produto type=innodb;
Captulo 5 - Integrando Spring, Hibernate e tecnologias de Persistncia - Exerccios - Pgina 42
-
7/18/2019 FJ27 Caelum Spring
49/98
Caelum http://www.caelum.com.br
Spring Framework
3
4)
Adicione as seguintes linhas ao seu app-config.xml:
-
7/18/2019 FJ27 Caelum Spring
50/98
Caelum http://www.caelum.com.br
Spring Framework 3
${produto.descricao} - ${produto.quantidade} -
detalhes
- editar
3)
Crie a jsp editar.jsp
no diretrio "WEB
-
INF/views/produtos/"
Alterar Produto
Descricao:
Quantidade:
4)
Reinicie o servidor e altere algum produto.
5.15 - Exerccio Opcional: Remoo de produtos
1) Para deixar o sistema mais completo, desenvolva a funcionalidade de remoo dos produtos.
5.16 - Aumentando nosso dornnio
Nosso sistema de controle de estoque at o momento est bem simples. Apenas cadastrando, listando e
alterando produtos. Vamos adicionar agora o conceito de Movimentao. Uma movimentao deve ser gerada
para todas as operaes realizadas no estoque, ou seja, se aumentarmos a quantidade de produtos em estoque.
geramos uma movimentao de entrada, caso diminua, geramos uma movimentao de sada.
5.17 - Entitidade
Devido ao nosso novo problema vamos adicionar ao nosso projeto a entidade de movimentacao. Ele vai
representar as movimentaes realizadas. Entre seus atributos temos a data que foi efetuada, a quantidade do
produto que foi alterada, o tipo da movimentacao que pode ser ENTRADA ou SAIDA e um relacionamento ao
Produto em questo.
Captulo 5 - Integrando Spring, Hibernate e tecnologias de Persistncia - Exerccio Opcional: Remoo de produtos - Pgina 44
-
7/18/2019 FJ27 Caelum Spring
51/98
Caelum http://www.caelum.com.br
Spring Framework 3
package br.com.caelum.estoque;
@Entity
public class Movim entacao {
@Id
@GeneratedValue
private Long id;
private C alendar data;
@Enumerated(EnumType.STRING)
private TipoMovimentacao tipo;
private Integer quan tidade;
@ManyToOne
private Produto produto;
//getters e setters
}
Para facilitar o trabalho, o tipo de movimentao ser uma
Enum.
package br.com.caelum.estoque;
public enum TipoMovimentacao {
ENTRADA SAIDA
}
Porm no basta apenas termos esta nova entidade, precisamos alterar a lgica de alterao de produtos.
Nesta nova lgica ao alterar a quantidade de um produto, calcularemos se a movimentao de sada ou
entrada e a quantidade movimentada. Para isso isolaremos esta lgica em um novo cdigo:
@Service
public class GeradorDeM ovimentacao {
private final ProdutoDA O produtoDA O;
@Autowired
public GeradorDeMovimentacao(@Q ualifier("produtoHibernateDA0")ProdutoDA 0 produtoDAO) {
this.produtoDAO = produtoDAO;
public Movimentacao geraMovim entacao(Produto produto) {
Movimentacao mov = new Movimentacao();
mov.setData(Calendar.getInstance());
mov.setProduto(produto);
Integer quantidadeAtual = produtoDAO.estoqueAtual(produto);
if(produto.getQuantidade()>quantidadeAtual){
mov.setTipo(TipoMovimentacao.ENTRADA);
}else{
mov.setTipo(TipoMovimentacao.SAIDA);
}
mov. setQuantidade(Math. abs (produto .getQuantidadeO-quantidadeA
tual));
return m ov;
}
}
Basicamente o que o mtodo
geraMovimentacao
faz receber um produto com a quantidade nova de itens
e comparar com a atual, descobrindo se a movimentao de entrada ou sada.
Captulo 5 - Integrando Spring, Hibernate e tecnologias de Persistncia - Entitidade - Pgina 45
-
7/18/2019 FJ27 Caelum Spring
52/98
Caelum http://www.caelum.com.br
Spring Framework 3
Tambm precisamos mexer no mtodo
alterar da
ProdutosControl ler
para usar o geradorDeMovimenta-
cao:
@RequestMapping(value="/alterar" , method=RequestMethod.POST)
public String alterar(Produto produto) {
Movimentacao movimentacao = geradorDeMovimentacao.geraMovimentacao(produto);
movimentacaoDao.salvar(movimentacao);
produtoDAO.alterar(produto);
return "redirect:/produtos/listar.html";
}
Agora toda as vezes que alterarmos a quantidade de um produto, ser gerada uma movimentao.
5.18 Exerccios
1)
Crie a entidade Movimentacao e a classe
TipoMovimentacao,
no esquea das anotaes do Hibernate e de
registrar a entidade no xml do Spring:
package br.com.caelum.estoque;
@Entity
public class Movimentacao {
@Id
@GeneratedValue
private Long id;
private Calendar data;
@Enumerated(EnumType.STRING)
private TipoMovimentacao tipo;
private Integer quantidade;
@ManyToOne
private Produto produto;
//getters e setters
}
package br.com.caelum.estoque;
public enum TipoMovimentacao
ENTRADA, SAIDA
}
2)
Altere a interface
ProdutoDA0
adicionando o mtodo
estoqueAtual:
public interface ProdutoDA0 {
void salvar(Produto produuto);
void alterar(Produto produto);
List listar();
Produto buscarPorld(Long id);
Integer estoqueAtual(Produto produto);
}
Ao alterar a interface precisamos implementar este novo mtodo nas classes
ProdutoHibernateDAO
e
ProdutoMemoriaDAO.
Captulo 5 - Integrando Spring, Hibernate e tecnologias de Persistncia - Exerccios - Pgina 46
-
7/18/2019 FJ27 Caelum Spring
53/98
Caelumhttp://www.caelum.com.br
Spring Framework 3
public class ProdutoHibernateDAO
implements ProdutoDA0 {
/ /outros m etodos ja existentes
public
Integer estoqueA tual(Produto produto) {
Query query = factory.getCurrentSession()
.createQuery("select quantidade from Produto w here id = :pid");
query.setParameter("pid", produto.getId());
return (Integer) query.uniqueResu lt() ;
public
class ProdutoMem oriaDA0 implements ProdutoDA0 {
/ /outros metodos ja
existentes
public
Integer estoqueAtual(