Vous êtes sur la page 1sur 92
Spring Framework Parte 03 – Spring MVC

Spring Framework

Parte 03 Spring MVC

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.

Padrão front controller

Handler

mapping

2: HTTP request

Padrão front controller Handler mapping 2: HTTP request 3: Web controller Dispatcher Servlet 1: HTTP request

3: Web controller

Dispatcher

Servlet

2: HTTP request 3: Web controller Dispatcher Servlet 1: HTTP request 10: HTTP Response Web controller

1: HTTP request

3: Web controller Dispatcher Servlet 1: HTTP request 10: HTTP Response Web controller 4: HTTP request
3: Web controller Dispatcher Servlet 1: HTTP request 10: HTTP Response Web controller 4: HTTP request

10: HTTP Response

Web controller

4: HTTP request

request 10: HTTP Response Web controller 4: HTTP request 5: model and view name 7: view

5: model and view name

7: view
7: view

6: view name

9: HTTP Response

8: model

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.

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.

Atualizando as configurações

Adicionar JSTL como dependência no pom.xml:

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>jstl</artifactId>

</dependency>

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};

}

}

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;

CRUD Fabricante: listagem

Controlador web (2):

@RequestMapping public String inicio(Model model){ model.addAttribute("fabricantes", repositorio.todos()); return "fabricantes/inicio";

}

}

CRUD Fabricante: listagem

• Controlador web (2): @RequestMapping public String inicio(Model model){ model.addAttribute("fabricantes",
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.

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>

CRUD Fabricante: exclusão

Controlador web (1):

import org.springframework.web.bind.annotation.RequestParam;

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

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";

}

}

CRUD Fabricante: exclusão

Controlador web (2):

• @RequestMapping("/excluir") public String excluir(@RequestParam("id") Integer idFabricante, Model
@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.
}

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>

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.

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.

Forward

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.

Redirect

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.

CRUD Fabricante: exclusão com redirect

Controlador web (1):

import

org.springframework.web.servlet.mvc.support.RedirectAttributes;

public class CRUDFabricante {

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";

}

}

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>

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;

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>

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;

}

CRUD Fabricante: novo registro

Controlador web método novo:

import org.springframework.web.servlet.ModelAndView; import cursoSpring.revenda_veiculos.dominio.Fabricante;
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.

CRUD Fabricante: novo registro

Controlador web método novo:

import org.springframework.web.servlet.ModelAndView; import cursoSpring.revenda_veiculos.dominio.Fabricante;
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.

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" />

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>

Biblioteca de tags Spring para manipulação de formulários.

<h2>${titulo}</h2>

<c:url var="actionUrl" value="/fabricantes/salvar" />

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>

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=" <form:hidden path="id"/> <input type="hidden" name="titulo" value <br> <button type="submit">Salvar</button> </form:form>

</body>

</html>

color: red"/>

="${titulo}">

Define o identificador do objeto que será 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

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

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";

}

CRUD Fabricante: alterar registro

inicio.jsp link de edição:

<td> <a href="${actionUrl}/editar/${fabricante.id}"> ALTERAR </a> </td>

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";

}

}

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.

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 {

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;

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;

}

CRUD Veículo

Classe Veiculo (4):

public String getMimeTypeFoto() { if(foto != null) return foto.getMimeType(); return null;

}

//getters e setters

}

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;

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);

}

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 {

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);

}

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();

}

}

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>

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>

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>

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" >

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>

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>

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;

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();

}

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

através deste controlador.

@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

@ModelAttribute("modelos")

public List<Modelo> listaDeModelos(){ return modeloRepositorio.todos();

}

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;

}

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";

}

}

CRUD Veículo

Classe ModeloDAO:

import org.springframework.transaction.annotation.Transactional;

@Repository @Transactional public class ModeloDAO implements ModeloRepository {

}

CRUD Veículo: upload da foto

Dependência para upload de arquivos:

<dependency>

<groupId>commons-fileupload</groupId>

<artifactId>commons-fileupload</artifactId>

</dependency>

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;

}

}

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>

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);

}

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){

Será preenchido com o arquivo submetido. Note que a string

formulário de submissão.

file.getContentType()); dado ao campo file presente no

Foto foto = new Foto(file.getBytes(), arquivoFoto corresponde ao nome

veiculo.setFoto(foto);

}

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";

}

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 });

});

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>

Esta instrução foi movida para o início da tag head para que a URL já esteja disponível aos scripts em JS.

$(function() { $("#dialogFoto").dialog({ autoOpen: false });

});

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>

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>

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>

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);

}

}

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.

}

Pesquisa de veículo: Ajax + JSON

Adicionar biblioteca Jackson ao pom.xml:

<dependency>

<groupId>com.fasterxml.jackson.core</groupId>

<artifactId>jackson-databind</artifactId>

</dependency>

Pesquisa de veículo: Ajax + JSON

VeiculoRepositorio: método getPorModelo

import java.util.List;

public interface VeiculoRepositorio {

public List<Veiculo> getPorModelo(Integer idModelo);

}

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();

}

}

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;

Indica que a resposta do método deve ser colocada no payload da resposta HTTP. Por padrão, Spring MVC converterá os objetos Java retornados pelo método em uma string JSON.

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);

}

}

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>

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/");

}

}

Servindo conteúdo estático

É preciso registrar um gerenciador de recursos.

import

istry;

}

}

import istry; } } .addResourceLocations("/resources/"); Diretório em que se encontram os arquivos (JS, CSS,
.addResourceLocations("/resources/");
.addResourceLocations("/resources/");

Diretório em que se encontram os

arquivos (JS, CSS, imagens, etc).

em que se encontram os arquivos (JS, CSS, imagens, etc). 88
em que se encontram os arquivos (JS, CSS, imagens, etc). 88
em que se encontram os arquivos (JS, CSS, imagens, etc). 88
em que se encontram os arquivos (JS, CSS, imagens, etc). 88
em que se encontram os arquivos (JS, CSS, imagens, etc). 88
em que se encontram os arquivos (JS, CSS, imagens, etc). 88

88

org.springframework.web.servlet.config.annotation.ResourceHandlerReg

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

@Override public void addResourceHandlers(ResourceHandlerRegistry registry){

registry.addResourceHandler("/resources/**")

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>

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" Repare que não é necessário o uso da

prefix="form" %> <html> <body> <h2>Hello World!</h2>

<img src="resources/logo.jpg" > tag c:url para obter o endereço completo da URL resources .
<img src="resources/logo.jpg" > tag c:url para obter o endereço completo da URL resources .

<img src="resources/logo.jpg" >

<img src="resources/logo.jpg" >
<img src="resources/logo.jpg" > tag c:url para obter o endereço completo da URL resources .
<img src="resources/logo.jpg" > tag c:url para obter o endereço completo da URL resources .
<img src="resources/logo.jpg" > tag c:url para obter o endereço completo da URL resources .
tag c:url para obter o endereço completo da URL resources .

tag c:url para obter o endereço completo da URL resources.

<img src="resources/logo.jpg" > tag c:url para obter o endereço completo da URL resources .
<img src="resources/logo.jpg" > tag c:url para obter o endereço completo da URL resources .
<img src="resources/logo.jpg" > tag c:url para obter o endereço completo da URL resources .
<img src="resources/logo.jpg" > tag c:url para obter o endereço completo da URL resources .
<img src="resources/logo.jpg" > tag c:url para obter o endereço completo da URL resources .
<img src="resources/logo.jpg" > tag c:url para obter o endereço completo da URL resources .

</body>

</html>

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>

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.