Vous êtes sur la page 1sur 43

Spring MVC

Configuração, Servlet Front Controller,


Anotações, Passagem de parâmetros,
Organizando os JSPs, Bean Validation
Sergio Bonato – ARQDESISMULTI – USJT - 2019
Frameworks MVC, para quê?
• Facilitam o desenvolvimento,
liberando o programador para
manter seu foco nas regras de
negócio mais do que em
detalhes de implementação.
• Não precisamos lidar
diretamente com o protocolo
HTTP porque a API do Servlet já
faz isso por nós, por exemplo.
O Struts surgiu em 2000 e continua
evoluindo…
• Mas ainda dá muito trabalho ter
que pegar vários parâmetros do
servlet e montar um objeto.
• Formatar datas e números.
• Implementar o pattern Front
Controller.
• Desenvolver diretamente com
Servlets e JSP não é muito
produtivo.
• O framework MVC Struts foi um
dos primeiros a ajudar a lidar com
estes problemas.
https://struts.apache.org/
Spring MVC
• Um dos frameworks MVC mais
utilizados no mercado
atualmente.
• Não começou como um
framework MVC, mas como um
contêiner Java pouco intrusivo
baseado nos patternInjeção de
Dependência e Inversão de
Controle.
Spring Framework

http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/
Maven
• Ferramenta de gestão de build
de projetos.
• Baseada no conceito de project
object model (POM).
• Basicamente, o Maven faz
download dos JARs necessários
para o build do projeto Java.
Configurando o Spring MVC
• Baixar os JARs via Maven
configurando o pom.xml
(próximos slides)
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>mapa</groupId>
<artifactId>mapa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>

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

<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.13</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>

<warSourceDirectory>WebContent</warSourceDirectory>

<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
Configurando o Spring MVC
• Configurar o servlet que fará o papel do Front Controller no web.xml
• O web.xml fica no WebContents/WEB-INF
• Ele é o deployment descriptor da aplicação.
• É uma configuração normal de servlets, com a diferença que recebe um
parâmetro de inicialização, o spring-context.xml.
web.xml
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-context.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Configuração do Spring
• O Spring MVC possui um arquivo próprio de configuração, que também fica
no WebContents/WEB-INF, o spring-context.xml
• Nele iremos liberar o uso de anotações:
<context:component-scan base-package="br.usjt.mapeamento" />
<mvc:annotation-driven />
• Iremos informar ao Spring onde iremos “esconder” nossos JSP, para que
ninguém possa chamá-los diretamente.
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
spring-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
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">

<context:component-scan base-package="br.usjt.mapeamento" />


<mvc:annotation-driven />
<mvc:default-servlet-handler/>
<mvc:interceptors><bean
class="br.usjt.mapeamento.interceptor.AutorizadorInterceptor"/></mvc:interceptors>

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean id="mysqlDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost/mapeamento"></property>
<property name="username" value="root"></property>
<property name="password" value=""></property>
</bean>

</beans>
Criando um Olá Mundo
package br.usjt.mapeamento;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class OlaMundoController {

@RequestMapping("/olaMundoSpring")
public String execute() {
System.out.println("Olá, Mundo, com Spring MVC");
return "ola";
}
}

• Este é um pattern command – front controller; podemos criar novas lógicas para
diferentes urls configuradas no @RequestMapping.
• O Controller despacha a execução para o ola.jsp
ola.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>Olá, Mundo, com SpringMVC!</h2>
</body>
</html>

• Basta colocar este JSP no diretório WebContents/views


Passando parâmetros
• O Spring já passa o javabean pronto para o controller, com os dados
dos campos do formulário passados via parâmetros da request
preenchidos.
• Para isso é preciso:
• Passar o Javabean como parâmetro do método do Controller
• Usar o mesmo nome do atributo do javabean no campo do formulário
Organizando JSP
• Para manter o código mais organizado e evitar que os JSPs sejam
chamados direto da URL do browser:
• Crie uma pasta views dentro do WEB-INF e coloque lá os JSPs
• Para organizar melhor, crie subpastas dentro da pasta views
• Note que os JSPs que estiverem dentro da pasta views podem ser
retornados direto pelos métodos do Controller. Já os que estiverem
dentro de subpastas é preciso que a subpasta venha antes.
Exemplo de Parâmetros e Organização de JSPs
@RequestMapping("/incluir_local")
public String inclusao(Local local, HttpServletRequest request){
LocalService ls = new LocalService();
try {
request.setCharacterEncoding("UTF-8");
ls.criar(local);
Local novolocal = ls.buscar(local.getId());
request.setAttribute("novo_local", novolocal);

return "local/mostrar_local";
} catch (IOException e) {
e.printStackTrace();
}
return "erro";
}
Validação com Bean Validation
Validação com Bean Validation
• A partir do JEE6 é possível usar anotações para fazer validações
dentro de um Java Bean (JSR-303)
• Para a validação funcionar você deve incluir os JARs de validação. A
implementação de referência é do Hibernate (http://hibernate.org/validator).
• As validações são realizadas por meio de anotações.
• Algumas das anotações disponíveis estão no slide a seguir.
Anotação Descrição Exemplo
@AssertFalse o valor do atributo deve ser false @AssertFalse
@AssertTrue (true) boolean isSuportado;
@DecimalMax (value=,inclusive=) verifica se o valor é menor ou igual ao @DecimalMax(value=“0.5”,
@DecimalMin (value=,inclusive=) valor informado se inclusive for true; inclusive=true);
ou se é menor se for false. double fator;
@Digits(integer=,fraction=) verifica se o valor é maior (menor) ou @DecimalMin(value=“0.5”, inclusive=true);
igual ao valor informado se inclusive double fator;
for true; ou se é maior (menor) se for
false.
@Future verifica se a data está no futuro ou no @Past
@Past passado Date dataDeCaptura;
@Max(value=) varifica se o inteiro é menor (maior) @Min(5)
@Min(valie=) ou igual ao inteiro digitado int quantidade;
@NotNull O valor deve ser não nulo (nulo) @NotNull
@Null String nome;
@Size(min=, max=) O valor deve estar dentro da faixa @Size (min=1, max=5)
especificada int numero;
@Pattern O valor deve ser valido para a @Pattern(regexp=\\(\\d{3}\\)\\d{3}-\\d{4})
expressão regular informada. String telefone;
Exemplo de Bean Validation
public class Local implements Serializable{
private static final long serialVersionUID = 1L;
private int id;

@NotNull @Size(max=128,min=5)
private String nome;

@NotNull @DecimalMax("5.27") @DecimalMin("-33.75")


private double latitude;

//incluindo Fernando de Noronha


@NotNull @DecimalMax("-32.38") @DecimalMin("-73.97")
private double longitude;

@Size(max=128,min=5)
private String imagem;
Informado o controller que queremos validar
o bean
@RequestMapping("/incluir_local")
public String inclusao(@ Valid Local local, HttpServletRequest request){
LocalService ls = new LocalService();
try {
request.setCharacterEncoding("UTF-8");
ls.criar(local);
Local novolocal = ls.buscar(local.getId());
request.setAttribute("novo_local", novolocal);

return "local/mostrar_local";
} catch (IOException e) {
e.printStackTrace();
}
return "erro";
}
E se não for válido?
• Será lançada uma exceção do tipo ConstraintViolationException.
• Para não mostrar uma exceção para o usuário, mas voltar para o
formulário de digitação, existe o objeto BindingResult
Tratando um erro específico
@RequestMapping("incluir_local")
public String inclusao(@Valid Local local, BindingResult result, Model
model) {

LocalService ls = new LocalService();


try {
if (result.hasFieldErrors("nome")) {
TipoService ts = new TipoService();
CidadeService cs = new CidadeService();
ArrayList<Tipo> tipos = ts.listarTipos();
model.addAttribute("tipos", tipos);
ArrayList<Cidade> cidades = cs.listarCidades();
model.addAttribute("cidades", cidades);
return "local/criar_local";
}
ls.criar(local);
Local novolocal = ls.buscar(local.getId());
model.addAttribute("novo_local", novolocal);

return "local/mostrar_local";
} catch (IOException e) {
e.printStackTrace();
}
return "erro";
}
Tratando um erro genérico
@RequestMapping("incluir_local")
public String inclusao(@Valid Local local, BindingResult result, Model
model) {

LocalService ls = new LocalService();


try {
if (result.hasErrors()) {
TipoService ts = new TipoService();
CidadeService cs = new CidadeService();
ArrayList<Tipo> tipos = ts.listarTipos();
model.addAttribute("tipos", tipos);
ArrayList<Cidade> cidades = cs.listarCidades();
model.addAttribute("cidades", cidades);
return "local/criar_local";
}
ls.criar(local);
Local novolocal = ls.buscar(local.getId());
model.addAttribute("novo_local", novolocal);

return "local/mostrar_local";
} catch (IOException e) {
e.printStackTrace();
}
return "erro";
}
Mostrando mensagens de validação no JSP
• Usar no JSP a tag

<form:errors path=“local.nome” />

• Importar a taglib no início do JSP

<%@ taglib uri=“http://www.springframework.org/tags/form” prefix=”form” %>


<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ 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>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Cadastro de Locais</title>
</head>
<body>
<h2>Criar Local</h2>
<br><br>
<form action="incluir_local" method="post">
<p>
<form:errors path="local.nome" cssStyle="color:red"/><br>
<label for="nome">Nome: </label>
<input type="text" id="nome" name="nome" maxlength="128" required>
</p>
<p>
<form:errors path="local.latitude" cssStyle="color:red"/><br>
<label for="latitude">Latitude: </label>
<input type="number" id="latitude" name="latitude" step="0.000001" required>
</p>
<p>
<form:errors path="local.longitude" cssStyle="color:red"/><br>
<!--restante do código omitido-->
Usando mensagens de erro
public class Local implements Serializable{
private static final long serialVersionUID = 1L;
private int id;

@NotNull
@Size(max=128, min=5, message="O tamanho máximo do nome está entre 5 e 128 caracteres")
private String nome;

@NotNull
@DecimalMax(value="5.27", message="latitude máxima do Brasil é 5.27 (Roraima)")
@DecimalMin(value="-33.75", message="latitude mínima do Brasil é -33.75 (Chuí)")
private double latitude;

//incluindo Fernando de Noronha


@NotNull
@DecimalMax(value="-32.38",message="longitude máxima do Brasil é -32.38 (Fernando de Noronha)")
@DecimalMin(value="-73.97",message="longitude mínima do Brasil é -73.97 (Acre)")
private double longitude;

@Size(max=128, min=5, message="O tamanho máximo do nome da imagem está entre 5 e 128 caracteres")
private String imagem;
Pode-se também criar um arquivo de
mensagens de erro.
• O arquivo deve se chamar ValidationMessages.properties.
• O conteúdo deve ser:

local.nome.vazio=Nome deve ser informado.


local.nome.grande=O tamanho máximo do nome é 128 caracteres

• O arquivo deve estar na pasta src.


Usando o arquivo de mensagem, o código
fonte fica assim
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class Local implements Serializable{


private int id;

@NotNull(message=“{local.nome.vazio}”)
@Size(max=128, message=“{local.nome.grande}”)

private String nome;


private double latitude, longitude;
Devemos usar HttpServletRequest
• O Spring disponibiliza uma forma melhor de passar parâmetros para o
JSP, que é o ModelAndView.

• Para usá-lo, o melhor é receber como parâmetro do método no


controller.
Uso do ModelAndView
@RequestMapping("/local")
public String form(Model model){

TipoService ts = new TipoService();


CidadeService cs = new CidadeService();
try {
ArrayList<Tipo> tipos = ts.listarTipos();
model.addAttribute("tipos", tipos);
ArrayList<Cidade> cidades = cs.listarCidades();
model.addAttribute("cidades", cidades);
return "local/criar_local";

} catch (IOException e) {
e.printStackTrace();
}
return "erro";
}
Uso do ModelAndView
@RequestMapping("/incluir_local")
public String inclusao(@ Valid Local local ,
BindingResult result, Model model){
LocalService ls = new LocalService();
try {
if(result.hasFieldErrors("nome")){
//restante do código omitido
return "local/criar_local";
}

ls.criar(local);
Local novolocal = ls.buscar(local.getId());
model.addAttribute("novo_local", novolocal);

return "local/mostrar_local";
} catch (IOException e) {
e.printStackTrace();
}
return "erro";
}
Redirecionando Requisições
• Ao removermos um local, é necessário redirecionar a aplicação para
uma outra tela, uma vez que o local removido não existe mais.
• Para remover uma tarefa, coloque na tabela do HTML que está
listando os locais a célula

<td><a href=“remover_local?id=${local.id}>Excluir></a></td>
Redirecionando Requisições
• Crie o método removeLocal no controller.
• No remove local, em vez de retornar para o JSP que lista locais
diretamente, pois isso tornaria necessário recarregar o bean de locais,
é melhor fazer um redirect para o controller e reexecutar tudo a partir
de lá. Para isso, faça:

@RequestMapping("remover_local")
public String remover(Model model) {

return "redirect:listar_locais";
}
Evitando que o controller responda a
requisições de arquivos estáticos
• No Spring MVC o controller acaba sendo chamado para atender
qualquer requisição.
• Para evitar que arquivos estáticos como imagens, css, javascrpts, etc,
coloque no spring-context.xml a tag abaixo:
<mvc:default-servlet-handler />

Vous aimerez peut-être aussi