Você está na página 1de 92

Spring Framework

Parte 03 – Spring MVC


Spring MVC
• Módulo do Spring Framework que permite o
desenvolvimento de aplicações web baseadas em
ações (action based) bem como o desenvolvimento
de serviços REST.
• Integra-se à API de Servlets.
• Suporta:
– Diversas tecnologias de visão tais como JSP/JSTL, Velocity,
FreeMarker, Thymeleaf, Tiles, XSLT e Groovy Markup
Templates.
– Processamento assíncrono.
– Internacionalização.
• Oferece funcionalidades de segurança e de testes.
2
Padrão front controller

Handler
mapping
2: HTTP request

3: Web controller

1: HTTP request
4: HTTP request
Dispatcher
Web controller
Servlet
10: HTTP Response 5: model and view name

6: view name
9: HTTP Response 8: model
7: view
View
resolver
View
3
Controlador web
• Objeto responsável por responder um conjunto
de requisições HTTP.
• As requisições atendíveis podem ser especificadas
através de padrões de URL, por cabeçalhos HTTP
e por métodos HTTP.

4
Anotações e classes
• @Controller: define um controlador web.
• @RequestMapping: definições das requisições HTTP
a serem atendidas.
• @RequestParam: define um parâmetro query string.
• @PathVariable: referencia parâmetros em URLs
estilo REST.
• org.springframework.ui.Model: para armazenar
objetos acessados pela view.
• org.springframework.web.servlet.ModelAndView:
para armazenar o nome da view e objetos acessados
pela view.

5
Atualizando as configurações
• Adicionar JSTL como dependência no pom.xml:

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>

6
Atualizando as configurações
• Disponibilizando o contexto do Spring para o
contexto da aplicação web:
...

public class SpringMVCServlet extends


AbstractAnnotationConfigDispatcherServletInitializer {

@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{AppConfig.class};
}

...
}

7
CRUD Fabricante: listagem
• Controlador web (1):
package cursoSpring.revenda_veiculos.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import cursoSpring.revenda_veiculos.dominio.FabricanteRepository;

@Controller
@RequestMapping("/fabricantes")
public class CRUDFabricante {

@Autowired
private FabricanteRepository repositorio;

8
CRUD Fabricante: listagem
• Controlador web (2):
@RequestMapping
public String inicio(Model model){
model.addAttribute("fabricantes", repositorio.todos());
return "fabricantes/inicio";
}
}

9
CRUD Fabricante: listagem
• Controlador web (2):
@RequestMapping
public String inicio(Model model){
model.addAttribute("fabricantes", repositorio.todos());
return "fabricantes/inicio";
}
}
Visão (página) a ser renderizada com
os dados inseridos em model.

10
CRUD Fabricante: listagem
• Página src/main/webapp/WEB-
INF/views/fabricantes/inicio.jsp (1):
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<title>Fabricantes</title>
</head>
<body>
<h2>Fabricantes</h2>
<table>
<tr>
<th>Fabricante</th>
<th colspan="2">Opções</th>
</tr> 11
CRUD Fabricante: listagem
• Página src/main/webapp/WEB-
INF/views/fabricantes/inicio.jsp (2):
<c:forEach var="fabricante" items="${fabricantes}">
<tr>
<td>${fabricante.descricao}</td>
<td>
EXCLUIR
</td>
<td>
ALTERAR
</td>
</tr>
</c:forEach>
</table>
</body>
</html>
12
CRUD Fabricante: exclusão
• Controlador web (1):
...
import org.springframework.web.bind.annotation.RequestParam;

@Controller
@RequestMapping("/fabricantes")
public class CRUDFabricante {
...

13
CRUD Fabricante: exclusão
• Controlador web (2):
...
@RequestMapping("/excluir")
public String excluir(@RequestParam("id") Integer idFabricante,
Model model){
try{
repositorio.excluir(idFabricante);
model.addAttribute("mensagem",
"Fabricante excluído com sucesso.");
}catch(Exception ex){
ex.printStackTrace();
model.addAttribute("mensagem",
"Ocorreu um erro durante a operação.");
}
return "forward:/fabricantes";
}
}
14
CRUD Fabricante: exclusão
• Controlador web (2):
...
@RequestMapping("/excluir")
public String excluir(@RequestParam("id") Integer idFabricante,
Model model){
try{
repositorio.excluir(idFabricante);
model.addAttribute("mensagem",
"Fabricante excluído com sucesso.");
}catch(Exception ex){
ex.printStackTrace();
model.addAttribute("mensagem", Como queremos voltar à listagem
"Ocorreu um erro durante a operação.");
de fabricantes após a exclusão,
} aproveitamos o método inicio
return "forward:/fabricantes"; realizando um forward para a URL
} /fabricantes.
}
15
CRUD Fabricante: exclusão
• fabricante/inicio.jsp:
<h2>Fabricantes</h2>
<c:url var="actionUrl" value="/fabricantes" />
<c:if test="${not empty mensagem}">
<p style="border: 1px solid black;">${mensagem}</p>
</c:if>
<table>
...
<td>${fabricante.descricao}</td>
<td>
<a href="${actionUrl}/excluir?id=${fabricante.id}">
EXCLUIR
</a>
</td>
...

16
Forward e Redirect
• É comum que após processar uma requisição o
controlador web direcione o fluxo da aplicação
para uma página diferente da utilizada na
submissão.
• Temos duas formas disponíveis: forward e
redirect.
• Diferença básica:
– No forward o processamento é realizado no servidor.
– No redirect a mudança de página é feita pelo browser.
17
Forward
• As mudanças de URL são todas processadas no
servidor antes da resposta ser enviada ao cliente.
• Por haver apenas uma requisição, o mesmo contexto
de requisição é utilizado pelas páginas e métodos
envolvidos no processamento.
– O mesmo model fica disponível a todos os métodos Java.
• Ao final do processamento da requisição, a URL na
barra de endereços do navegador não muda. Assim,
o reload da página resultante irá executar a
requisição original.
18
Forward

19
Redirect
• É um mecanismo especificado pelo HTTP.
• Dois passos. Ao receber uma requisição, a aplicação
pede ao browser para acessar uma segunda URL.
– Por isso a URL na barra de endereços muda.
– O “pedido” é um recurso do HTTP: código 301 ou 302 e
cabeçalho Location.
• O reload de página não repetirá a requisição original,
mas sim a segunda URL.
• Como acontecem duas requisições, os dados da
primeira requisição, não estarão disponíveis no
contexto da segunda requisição.
– Um model diferente por método Java.
20
Redirect

21
Flash scope
• Utilizado para manter dados que devem estar
disponíveis após um redirect.
• Para utilizar o flash scope basta declarar um
parâmetro do tipo RedirectAttributes.

22
CRUD Fabricante: exclusão com redirect

• Controlador web (1):


...
import
org.springframework.web.servlet.mvc.support.RedirectAttributes;
...
public class CRUDFabricante {
...

23
CRUD Fabricante: exclusão com redirect

• Controlador web (2):


...
@RequestMapping("/excluir")
public String excluir(@RequestParam("id") Integer idFabricante,
RedirectAttributes redAttr){
try{
repositorio.excluir(idFabricante);
redAttr.addFlashAttribute("mensagem",
"Fabricante excluído com sucesso.");
}catch(Exception ex){
ex.printStackTrace();
redAttr.addFlashAttribute("mensagem",
"Ocorreu um erro durante a operação.");
}
return "redirect:/fabricantes";
}
}
24
CRUD Fabricante: novo registro
• Atualizando pom.xml com bean validation:

<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>

25
CRUD Fabricante: novo registro
• Decorando Fabricante com anotações da bean
validation:
...
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@Entity
@Table(name="FABRICANTES")
public class Fabricante extends Entidade{

@NotNull
@Size(min=2)
private String descricao;
...

26
CRUD Fabricante: novo registro
• inicio.jsp – link para um novo registro:
...
<h2>Fabricantes</h2>
<c:url var="actionUrl" value="/fabricantes" />
<c:if test="${not empty mensagem}">
<p style="border: 1px solid black;">${mensagem}</p>
</c:if>
<a href="${actionUrl}/novo">Novo fabricante</a>
<table>
...

27
CRUD Fabricante: novo registro
• Controlador web – método novo:
import org.springframework.web.servlet.ModelAndView;
import cursoSpring.revenda_veiculos.dominio.Fabricante;
...
@RequestMapping("/novo")
public ModelAndView novo(){
ModelAndView modelAndView = new
ModelAndView("fabricantes/edicao");
modelAndView.addObject("fabricante", new Fabricante());
modelAndView.addObject("titulo", "Novo Fabricante");
return modelAndView;
}
...

28
CRUD Fabricante: novo registro
• Controlador web – método novo:
import org.springframework.web.servlet.ModelAndView;
import cursoSpring.revenda_veiculos.dominio.Fabricante;
...
@RequestMapping("/novo")
public ModelAndView novo(){
ModelAndView modelAndView = new
ModelAndView("fabricantes/edicao");
modelAndView.addObject("fabricante", new Fabricante());
modelAndView.addObject("titulo", "Novo Fabricante");
return modelAndView;
}
... O objeto fabricante será utilizado
para receber os valores do campos
do formulário.

29
CRUD Fabricante: novo registro
• Controlador web – método novo:
import org.springframework.web.servlet.ModelAndView;
import cursoSpring.revenda_veiculos.dominio.Fabricante;
...
@RequestMapping("/novo")
public ModelAndView novo(){
ModelAndView modelAndView = new
ModelAndView("fabricantes/edicao");
modelAndView.addObject("fabricante", new Fabricante());
modelAndView.addObject("titulo", "Novo Fabricante");
return modelAndView;
}
...
É informado o título da página pois a
mesma página será utilizada nas operações
de novo fabricante e edição de fabricante.

30
CRUD Fabricante: novo registro
• Página edicao.jsp (1):
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags/form"
prefix="form" %>
<!DOCTYPE html>
<html>
<head>
<title>${titulo}</title>
</head>
<body>
<h2>${titulo}</h2>
<c:url var="actionUrl" value="/fabricantes/salvar" />

31
CRUD Fabricante: novo registro
• Página edicao.jsp (1):
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags/form"
prefix="form" %>
<!DOCTYPE html>
<html>
<head>
<title>${titulo}</title> Biblioteca de tags Spring para
</head> manipulação de formulários.
<body>
<h2>${titulo}</h2>
<c:url var="actionUrl" value="/fabricantes/salvar" />

32
CRUD Fabricante: novo registro
• Página edicao.jsp (2):
<form:form action="${actionUrl}" method="post"
modelAttribute="fabricante">
<label for="descricao">DESCRIÇÃO</label>
<form:input path="descricao"/>
<form:errors path="descricao" cssStyle="color: red"/>
<form:hidden path="id"/>
<input type="hidden" name="titulo" value="${titulo}">
<br>
<button type="submit">Salvar</button>
</form:form>
</body>
</html>

33
CRUD Fabricante: novo registro
• Página edicao.jsp (2):
<form:form action="${actionUrl}" method="post"
modelAttribute="fabricante">
<label for="descricao">DESCRIÇÃO</label>
<form:input path="descricao"/>
<form:errors path="descricao" cssStyle="color: red"/>
<form:hidden path="id"/>
<input type="hidden" name="titulo" value="${titulo}">
<br>
<button type="submit">Salvar</button>
</form:form>
</body> Define o identificador do objeto que será
</html> utilizado (binding) para receber/preencher os
campos do formulário. O objeto será inserido no
contexto do model. Note que este é o
identificador a ser utilizado no controlador para
acessar os campos do formulário.
34
CRUD Fabricante: novo registro
• Controlador web – método salvar (1):
import javax.validation.Valid;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMethod;
...

@RequestMapping(value="/salvar", method=RequestMethod.POST)
public String salvar(
@Valid @ModelAttribute("fabricante") Fabricante fabricante,
BindingResult br,
@RequestParam("titulo") String titulo,
Model model,
RedirectAttributes rAttrs){
if(br.hasErrors()){
model.addAttribute("titulo", titulo);
return "fabricantes/edicao";
} 35
CRUD Fabricante: novo registro
• Indica
Controlador
que os atributosweb
do – método
Indica quesalvar (1):
o spring deve injetar um objeto
objeto org.springframework.validation.BindingResult;
import devem ser validados presente no contexto do model e que é
segundo
import as anotações da identificado pela string fabricante. Na
org.springframework.web.bind.annotation.ModelAttribute;
import Bean Validation. página, usamos o mesmo identificador.
org.springframework.web.bind.annotation.RequestMethod;
...

@RequestMapping(value="/salvar", method=RequestMethod.POST)
public String salvar(
@Valid @ModelAttribute("fabricante") Fabricante fabricante,
BindingResult br,
@RequestParam("titulo") String titulo,
Model model,
RedirectAttributes rAttrs){ Armazena o resultado
if(br.hasErrors()){ da validação.
model.addAttribute("titulo", titulo);
return "fabricantes/edicao";
}
36
CRUD Fabricante: novo registro
• Controlador web – método salvar (2):
try{
if(fabricante.getId() == null)
repositorio.inserir(fabricante);
else
repositorio.atualizar(fabricante);
rAttrs.addFlashAttribute("mensagem",
"Fabricante salvo com sucesso.");
}catch(Exception ex){
ex.printStackTrace();
rAttrs.addFlashAttribute("mensagem",
"Ocorreu um erro durante a operação.");
}
return "redirect:/fabricantes";
}
...

37
CRUD Fabricante: alterar registro
• inicio.jsp – link de edição:
...
<td>
<a href="${actionUrl}/editar/${fabricante.id}">
ALTERAR
</a>
</td>
...

38
CRUD Fabricante: alterar registro
• Controlador web:
import org.springframework.web.bind.annotation.PathVariable;
...
@RequestMapping("/editar/{id}")
public String editar(@PathVariable Integer id, Model model){
Fabricante f = repositorio.getPorId(id);
if(f == null)
return "forward:/fabricantes";
model.addAttribute("fabricante", f);
model.addAttribute("titulo", "Alterar Fabricante");
return "fabricantes/edicao";
}
}

39
Outras tags Spring para formulários
• checkbox: produz um campo input do tipo checkbox. Pode ser
associada a atributos com um ou muitos valores (coleções e
arrays). Quando seu valor não é indicado, é assumido o tipo
boolean.
• checkboxes: gera vários campos do tipo checkbox a partir de
uma coleção.
• radiobutton: produz uma tag input do tipo radio.
• radiobuttons: gera um conjunto relacionado de radio buttons a
partir de uma coleção.
• password: gera uma tag input do tipo password.
• option: gera uma tag option para um campo select.
• options: opções de um campo select gerados a partir de uma
coleção.
• textarea: produz uma tag textarea.
40
CRUD Veículo
• Classe Foto:
package cursoSpring.revenda_veiculos.dominio;
import javax.persistence.Embeddable;

@Embeddable
public class Foto {
@Basic(fetch=FetchType.LAZY)
private byte[] bytes;
private String mimeType;

public Foto() {}

public Foto(byte[] bytes, String mimeType) {


this.bytes = bytes;
this.mimeType = mimeType;
}
//getters e setters...
} 41
CRUD Veículo
• Classe Veiculo (1):
package cursoSpring.revenda_veiculos.dominio;

import javax.persistence.Basic;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

@Entity
@Table(name="VEICULOS")
public class Veiculo extends Entidade {
42
CRUD Veículo
• Classe Veiculo (2):
@Min(1900)
@NotNull
private Integer anoFabricacao;

@Pattern(regexp="[A-Z]{3}\\d{4}")
@NotNull
private String placa;

private String chassi;

@Embedded
private Foto foto;

@Min(50)
private Integer cilindradas;

43
CRUD Veículo
• Classe Veiculo (3):
@NotNull
@ManyToOne
@JoinColumn(name="ID_MODELO")
private Modelo modelo;

public Veiculo() {}

public Veiculo(Integer id, String placa){


super(id);
this.placa = placa;
}

44
CRUD Veículo
• Classe Veiculo (4):
public String getMimeTypeFoto() {
if(foto != null)
return foto.getMimeType();
return null;
}

//getters e setters ...


}

45
CRUD Veículo
• create-schema.sql:
...
create table VEICULOS (ID int auto_increment, ANOFABRICACAO int
not null, PLACA varchar(10) not null, CHASSI varchar(50),
CILINDRADAS int, BYTES blob, MIMETYPE varchar(50),
ID_MODELO int not null, primary key(ID),
foreign key(ID_MODELO) references MODELOS);

• drop-schema.sql:
drop table VEICULOS;
...

46
CRUD Veículo
• Interface VeiculoRepositorio:
package cursoSpring.revenda_veiculos.dominio;

import java.util.List;

public interface VeiculoRepositorio {

public Integer inserir(Veiculo v);

public void excluir(Integer id);

public List<Veiculo> todos();

public Veiculo getPorId(Integer id);

public Foto getFoto(Integer idVeiculo);


}
47
CRUD Veículo
• Classe VeiculoDAO (1):
package cursoSpring.revenda_veiculos.dao;

import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import cursoSpring.revenda_veiculos.dominio.Foto;
import cursoSpring.revenda_veiculos.dominio.Veiculo;
import cursoSpring.revenda_veiculos.dominio.VeiculoRepositorio;

@Repository
@Transactional
public class VeiculoDAO implements VeiculoRepositorio {
48
CRUD Veículo
• Classe VeiculoDAO (2):
@Autowired
private SessionFactory sessionFactory;

@Override
public Integer inserir(Veiculo v) {
sessionFactory.getCurrentSession().save(v);
return v.getId();
}

@Override
public void excluir(Integer id) {
String hql = "delete Veiculo where id = :idVeiculo";
Session session = sessionFactory.getCurrentSession();
Query q = session.createQuery(hql).
setParameter("idVeiculo", id);
q.executeUpdate();
} 49
CRUD Veículo
• Classe VeiculoDAO (3):
@Override
public List<Veiculo> todos() {
Session session = sessionFactory.getCurrentSession();
return session.createQuery("from Veiculo").list();
}

@Override
public Veiculo getPorId(Integer id) {
Session session = sessionFactory.getCurrentSession();
return (Veiculo)session.get(Veiculo.class, id);
}

50
CRUD Veículo
• Classe VeiculoDAO (4):
@Override
public Foto getFoto(Integer idVeiculo) {
String hql = "select v.foto from Veiculo v where v.id = :id ";
Session session = sessionFactory.getCurrentSession();
Query q = session.createQuery(hql).
setParameter("id", idVeiculo);
return (Foto)q.uniqueResult();
}
}

51
CRUD Veículo
• Página veiculos/inicio.jsp (1):
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<title>Veículos</title>
</head>
<body>
<h2>Veículos</h2>
<c:url var="actionUrl" value="/veiculos" />
<c:if test="${not empty mensagem}">
<p style="border: 1px solid black;">${mensagem}</p>
</c:if>
<a href="${actionUrl}/novo">Novo veículo</a>

52
CRUD Veículo
• Página veiculos/inicio.jsp (2):
<table>
<tr>
<th>Placa</th>
<th>Fabricante</th>
<th>Modelo</th>
<th>Ano</th>
<th>Cilindradas</th>
<th colspan="2">Opções</th>
</tr>
<c:forEach var="veiculo" items="${veiculos}">
<tr>
<td>${veiculo.placa}</td>
<td>${veiculo.modelo.fabricante.descricao}</td>
<td>${veiculo.modelo.descricao}</td>
<td>${veiculo.anoFabricacao}</td>
<td>${veiculo.cilindradas}</td>
53
CRUD Veículo
• Página veiculos/inicio.jsp (3):
<td>
<a href="${actionUrl}/excluir/${veiculo.id}">
EXCLUIR
</a>
</td>
</tr>
</c:forEach>
</table>
</body>
</html>

54
CRUD Veículo
• Página veiculos/edicao.jsp (1):
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags/form"
prefix="form" %>
<!DOCTYPE html>
<html>
<head>
<title>Novo veículo</title>
</head>
<body>
<h2>Novo veículo</h2>
<c:url var="actionUrl" value="/veiculos/salvar" />
<form:form action="${actionUrl}" method="post"
modelAttribute="veiculo" >

55
CRUD Veículo
• Página veiculos/edicao.jsp (2):
<label for="placa">PLACA</label>
<form:input path="placa"/>*
<form:errors path="placa" cssStyle="color: red"/><br>

<label for="anoFabricacao">ANO</label>
<form:input path="anoFabricacao"/>*
<form:errors path="anoFabricacao" cssStyle="color: red"/><br>

<label for="cilindradas">CILINDRADAS</label>
<form:input path="cilindradas"/>
<form:errors path="cilindradas" cssStyle="color: red"/><br>

<label for="chassi">CHASSI</label>
<form:input path="chassi"/>
<form:errors path="chassi" cssStyle="color: red"/><br>

56
CRUD Veículo
• Página veiculos/edicao.jsp (3):
<label for="selectModelo">MODELO</label>
<form:select path="modelo.id" id="selectModelo" >
<form:options items="${modelos}"
itemValue="id"
itemLabel="descricao" />
</form:select>
<form:errors path="modelo" cssStyle="color: red"/><br>

<button type="submit">Salvar</button>
</form:form>
</body>
</html>

57
CRUD Veículo
• Classe CRUDVeiculo (1):
package cursoSpring.revenda_veiculos.web;
import java.util.List;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import
org.springframework.web.servlet.mvc.support.RedirectAttributes;
import cursoSpring.revenda_veiculos.dominio.Modelo;
import cursoSpring.revenda_veiculos.dominio.ModeloRepository;
58
CRUD Veículo
• Classe CRUDVeiculo (2):
import cursoSpring.revenda_veiculos.dominio.Veiculo;
import cursoSpring.revenda_veiculos.dominio.VeiculoRepositorio;

@Controller
@RequestMapping("/veiculos")
public class CRUDVeiculo {

@Autowired
private VeiculoRepositorio veiculoRepositorio;
@Autowired
private ModeloRepository modeloRepositorio;

@ModelAttribute("modelos")
public List<Modelo> listaDeModelos(){
return modeloRepositorio.todos();
}
59
CRUD Veículo
• Classe CRUDVeiculo (2):
import cursoSpring.revenda_veiculos.dominio.Veiculo;
import cursoSpring.revenda_veiculos.dominio.VeiculoRepositorio;

@Controller
@RequestMapping("/veiculos")
public class CRUDVeiculo {
@ModelAttribute insere o
@Autowired retorno do método no
private VeiculoRepositorio veiculoRepositorio;
contexto model. Assim, a lista
@Autowired de modelos ficará disponível
private ModeloRepository modeloRepositorio;para as páginas acessadas
através deste controlador.
@ModelAttribute("modelos")
public List<Modelo> listaDeModelos(){
return modeloRepositorio.todos();
}
60
CRUD Veículo
• Classe CRUDVeiculo (3):
@RequestMapping
public ModelAndView inicio(){
ModelAndView modelAndView = new ModelAndView("veiculos/inicio");
modelAndView.addObject("veiculos", veiculoRepositorio.todos());
return modelAndView;
}

@RequestMapping("/novo")
public ModelAndView novo(){
ModelAndView modelAndView = new ModelAndView("veiculos/edicao");
modelAndView.addObject("veiculo", new Veiculo());
return modelAndView;
}

61
CRUD Veículo
• Classe CRUDVeiculo (4):
@RequestMapping(value="/salvar", method=RequestMethod.POST)
public String salvar(@Valid @ModelAttribute("veiculo") Veiculo
veiculo, BindingResult br, Model model, RedirectAttributes rAttrs){
if(br.hasErrors()){
return "veiculos/edicao";
}
try{
veiculoRepositorio.inserir(veiculo);
rAttrs.addFlashAttribute("mensagem",
"Veículo salvo com sucesso.");
}catch(Exception ex){
ex.printStackTrace();
rAttrs.addFlashAttribute("mensagem",
"Ocorreu um erro durante a operação.");
}
return "redirect:/veiculos";
} 62
CRUD Veículo
• Classe CRUDVeiculo (5):
@RequestMapping("/excluir/{id}")
public String excluir(@PathVariable Integer id,
RedirectAttributes redAttr){
try{
veiculoRepositorio.excluir(id);
redAttr.addFlashAttribute("mensagem",
"Veículo excluído com sucesso.");
}catch(Exception ex){
ex.printStackTrace();
redAttr.addFlashAttribute("mensagem",
"Ocorreu um erro durante a operação.");
}
return "redirect:/veiculos";
}
}

63
CRUD Veículo
• Classe ModeloDAO:
...
import org.springframework.transaction.annotation.Transactional;

@Repository
@Transactional
public class ModeloDAO implements ModeloRepository {
...
}

64
CRUD Veículo: upload da foto
• Dependência para upload de arquivos:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>

65
CRUD Veículo: upload da foto
• Classe AppConfig – adição do bean gerenciador
de uploads:
...
import
org.springframework.web.multipart.commons.CommonsMultipartResolver;

...
@Bean
public CommonsMultipartResolver multipartResolver(){
CommonsMultipartResolver resolver =
new CommonsMultipartResolver();
resolver.setMaxUploadSize(1024 * 1024 * 5);
resolver.setMaxInMemorySize(1024 * 1024 * 5);
return resolver;
}
}
66
CRUD Veículo: upload da foto
• Página veiculos/edicao.jsp:
<form:form action="${actionUrl}" method="post"
modelAttribute="veiculo" enctype="multipart/form-data">
...
<label for="arquivoFoto">FOTO</label>
<input type="file" name="arquivoFoto" accept="image/*"/>

<button type="submit">Salvar</button>
</form:form>
...

67
CRUD Veículo: upload da foto
• CRUDVeiculo – atualização do método salvar (1):
...
@RequestMapping(value="/salvar", method=RequestMethod.POST)
public String salvar(@Valid @ModelAttribute("veiculo") Veiculo
veiculo, BindingResult br, Model model, RedirectAttributes rAttrs,
@RequestParam("arquivoFoto") MultipartFile file){

if(br.hasErrors()){
return "veiculos/edicao";
}
try{
if(file != null){
Foto foto = new Foto(file.getBytes(),
file.getContentType());
veiculo.setFoto(foto);
}

68
CRUD Veículo: upload da foto
• CRUDVeiculo – atualização do método salvar (1):
...
@RequestMapping(value="/salvar", method=RequestMethod.POST)
public String salvar(@Valid @ModelAttribute("veiculo") Veiculo
veiculo, BindingResult br, Model model, RedirectAttributes rAttrs,
@RequestParam("arquivoFoto") MultipartFile file){

if(br.hasErrors()){
return "veiculos/edicao";
}
try{ Será preenchido com o arquivo
if(file != null){ submetido. Note que a string
Foto foto = new Foto(file.getBytes(),
arquivoFoto corresponde ao nome
file.getContentType());
dado ao campo file presente no
veiculo.setFoto(foto); formulário de submissão.
}

69
CRUD Veículo: upload da foto
• CRUDVeiculo – atualização do método salvar (2):
veiculoRepositorio.inserir(veiculo);
rAttrs.addFlashAttribute("mensagem",
"Veículo salvo com sucesso.");
}catch(Exception ex){
ex.printStackTrace();
rAttrs.addFlashAttribute("mensagem",
"Ocorreu um erro durante a operação.");
}
return "redirect:/veiculos";
}
...

70
CRUD Veículo: acessando a foto com Ajax

• veiculos/inicio.jsp (1):
...
<head>
<c:url var="actionUrl" value="/veiculos" />
<title>Veículos</title>
<script src="http://code.jquery.com/jquery-1.11.3.min.js">
</script>
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.min.js">
</script>
<script>
$(function() {
$("#dialogFoto").dialog({
autoOpen: false
});
});

71
CRUD Veículo: acessando a foto com Ajax

• veiculos/inicio.jsp (1):
...
<head>
<c:url var="actionUrl" value="/veiculos" />
<title>Veículos</title>
<script src="http://code.jquery.com/jquery-1.11.3.min.js">
</script>
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.min.js">
</script>
<script>
$(function() { Esta instrução foi movida para o início
$("#dialogFoto").dialog({ da tag head para que a URL já esteja
autoOpen: false disponível aos scripts em JS.
});
});

72
CRUD Veículo: acessando a foto com Ajax

• veiculos/inicio.jsp (2):
function verFoto(idVeiculo){
var imgUrl = '${actionUrl}/foto/'+idVeiculo;
$('#imgFoto').attr('src', imgUrl);
$('#dialogFoto').dialog("open");
}
</script>
</head>
...

73
CRUD Veículo: acessando a foto com Ajax

• veiculos/inicio.jsp (3):
...
<td>${veiculo.cilindradas}</td>
<td>
<c:choose>
<c:when test="${not empty veiculo.foto}">
<a href="#" onclick="verFoto(${veiculo.id})">
VER FOTO
</a>
</c:when>
<c:otherwise>
--
</c:otherwise>
</c:choose>
</td>
...

74
CRUD Veículo: acessando a foto com Ajax

• veiculos/inicio.jsp (4):
...
</table>

<div id="dialogFoto" title="foto"


style="border: 1px black solid;">
<img id="imgFoto">
</div>
</body>

75
CRUD Veículo: acessando a foto com Ajax

• CRUDVeiculo – método foto:


...
@RequestMapping("/foto/{id}")
public ResponseEntity<byte[]> foto(@PathVariable Integer id){
Foto foto = veiculoRepositorio.getFoto(id);
HttpHeaders headers = new HttpHeaders();
String[] tokens = foto.getMimeType().split("/");
MediaType mimeType = new MediaType(tokens[0], tokens[1]);
headers.setContentType(mimeType);
return new ResponseEntity<>(foto.getBytes(), headers,
HttpStatus.OK);
}
}

76
CRUD Veículo: acessando a foto com Ajax

• CRUDVeiculo – método foto:


...
@RequestMapping("/foto/{id}")
public ResponseEntity<byte[]> foto(@PathVariable Integer id){
Foto foto = veiculoRepositorio.getFoto(id);
HttpHeaders headers = new HttpHeaders();
String[] tokens = foto.getMimeType().split("/");
MediaType mimeType = new MediaType(tokens[0], tokens[1]);
headers.setContentType(mimeType);
return new ResponseEntity<>(foto.getBytes(), headers,
HttpStatus.OK);
}
}
Um ResponseEntity representa dados a serem inseridos
na resposta HTTP. Pelo tipo de retorno deste método,
SringMVC entende que não deve renderizar uma visão.

77
Pesquisa de veículo: Ajax + JSON
• Adicionar biblioteca Jackson ao pom.xml:
...
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
...

78
Pesquisa de veículo: Ajax + JSON
• VeiculoRepositorio: método getPorModelo
...
import java.util.List;
...
public interface VeiculoRepositorio {
...
public List<Veiculo> getPorModelo(Integer idModelo);
}

79
Pesquisa de veículo: Ajax + JSON
• VeiculoDAO: método getPorModelo
...
@Repository
@Transactional
public class VeiculoDAO implements VeiculoRepositorio {
...

@Override
public List<Veiculo> getPorModelo(Integer idModelo) {
String hql = "from Veiculo v where v.modelo.id = :id ";
Session session = sessionFactory.getCurrentSession();
Query q = session.createQuery(hql).setParameter("id", idModelo);
return q.list();
}
}

80
Pesquisa de veículo: Ajax + JSON
• CRUDVeiculo:
package cursoSpring.revenda_veiculos.web;
import java.util.List;
import org.springframework.web.bind.annotation.ResponseBody;
...
public class CRUDVeiculo {
...
@RequestMapping("/busca")
public String paginaDeBusca(){
return "veiculos/busca";
}

@RequestMapping("/pesquisar")
@ResponseBody
public List<Veiculo> pesquisar(@RequestParam Integer idModelo){
return veiculoRepositorio.getPorModelo(idModelo);
}
} 81
Pesquisa de veículo: Ajax + JSON
• CRUDVeiculo:
package cursoSpring.revenda_veiculos.web;
import java.util.List;
import org.springframework.web.bind.annotation.ResponseBody;
...
public class CRUDVeiculo { Indica que a resposta do método deve
... ser colocada no payload da resposta
@RequestMapping("/busca") HTTP. Por padrão, Spring MVC
public String paginaDeBusca(){ converterá os objetos Java retornados
return "veiculos/busca"; pelo método em uma string JSON.
}

@RequestMapping("/pesquisar")
@ResponseBody
public List<Veiculo> pesquisar(@RequestParam Integer idModelo){
return veiculoRepositorio.getPorModelo(idModelo);
}
} 82
Pesquisa de veículo: Ajax + JSON
• Página veiculos/busca.jsp (1):
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<c:url var="actionUrl" value="/veiculos" />
<title>Veículos</title>
<script src="http://code.jquery.com/jquery-1.11.3.min.js">
</script>
<script>
$(document).ready(function($){
$('#formPesquisa').submit(function(event){
event.preventDefault();
buscar();
});
}) 83
Pesquisa de veículo: Ajax + JSON
• Página veiculos/busca.jsp (2):
function buscar(){
$.getJSON('${actionUrl}/pesquisar',
$('#formPesquisa').serialize(),
function(data){
var linhas = '';
for(var i=0; i<data.length; i++){
linhas += '<tr><td>'+data[i].placa+'</td>'+
'<td>'+data[i].modelo.descricao+'</td>'+
'<td>'+data[i].anoFabricacao+'</td></tr>';
}
console.log(">>"+linhas);
var $tbody = $('#tabelaVeiculos').children('tbody');
$tbody.empty();
$tbody.append(linhas);
});
}
</script> 84
Pesquisa de veículo: Ajax + JSON
• Página veiculos/busca.jsp (3):
</head>
<body>
<h2>Busca de Veículos</h2>
<form id="formPesquisa">
<select name="idModelo">
<c:forEach var="modelo" items="${modelos}">
<option value="${modelo.id}">${modelo.descricao}</option>
</c:forEach>
</select>
<input type="submit" value="Pesquisar">
</form>
<table id="tabelaVeiculos">
<thead>
<tr>
<th>Placa</th>
<th>Modelo</th>
<th>Ano</th> 85
Pesquisa de veículo: Ajax + JSON
• Página veiculos/busca.jsp (4):
</tr>
</thead>
<tbody>
</tbody>
</table>
</body>
</html>

86
Servindo conteúdo estático
• É preciso registrar um gerenciador de recursos.
...
import
org.springframework.web.servlet.config.annotation.ResourceHandlerReg
istry;

@EnableWebMvc
@ComponentScan(basePackageClasses={OlaMundoController.class})
public class AppWebConfig extends WebMvcConfigurerAdapter{

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry){
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
...
}
87
Servindo conteúdo estático
• É preciso registrar um gerenciador de recursos.
...
import
org.springframework.web.servlet.config.annotation.ResourceHandlerReg
istry;

@EnableWebMvc
URL de acesso aos arquivos.
@ComponentScan(basePackageClasses={OlaMundoController.class})
public class AppWebConfig extends WebMvcConfigurerAdapter{

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry){
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
... Diretório em que se encontram os
} arquivos (JS, CSS, imagens, etc).
88
Servindo conteúdo estático
• index.jsp:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags/form"
prefix="form" %>
<html>
<body>
<h2>Hello World!</h2>
<img src="resources/logo.jpg" >
</body>
</html>

89
Servindo conteúdo estático
• index.jsp:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags/form"
prefix="form" %> Repare que não é necessário o uso da
<html> tag c:url para obter o endereço
<body> completo da URL resources.
<h2>Hello World!</h2>
<img src="resources/logo.jpg" >
</body>
</html>

90
Referências
• Johnson, Rod et al. Spring Framework Reference
Documentation, 4.2.1 release. Disponível em
<http://docs.spring.io/spring/docs/current/spring-framework-
reference/html/>
• Márcio d’Ávila. Informações úteis sobre cabeçalhos HTTP e
tipos MIME. Disponível em
<http://www.mhavila.com.br/topicos/web/http_mime.html>
• Paraschiv, Eugen. Serve static resources with Spring. Disponível
em <http://www.baeldung.com/spring-mvc-static-resources>.
• Souza, Alberto. Spring MVC: domine o principal framework web
Java. São Paulo: Casa do Código, 2015.
• Stack Overflow. JSTL tag wiki. Disponível em
<http://stackoverflow.com/tags/jstl/info>

91
Instituto Federal de Educação, Ciência e Tecnologia do Rio
Grande do Norte
Campus Natal Central
Diretoria Acadêmica de Gestão e Tecnologia da Informação

Curso de formação em Spring Framework 4


Parte 03 – Spring MVC

Autor: Alexandre Gomes de Lima


Natal, outubro de 2015.

92

Você também pode gostar